最近學(xué)習(xí)了MVP田柔,Retrofit2,RxJava2框架,感覺收獲頗多忧换,于是決定利用所學(xué)知識(shí)干一番大事業(yè)
ps:對(duì)這三種框架還不太清楚的童鞋可以看我之前的博客
傳送門:
MVP
Retrofit2
RxJava2
效果圖
話不多說瘾婿,先上圖
勉勉強(qiáng)強(qiáng)能看過去吧(●ˇ?ˇ●)
那么最重要的來了
那就是
實(shí)現(xiàn)
首先蜻牢,我這里用的后臺(tái)api接口是和風(fēng)天氣的接口,完全免費(fèi)偏陪,很實(shí)用抢呆,大家可以去注冊(cè)一個(gè)
和風(fēng)天氣
這個(gè)接口會(huì)提供很多天氣方面的信息,我們只需要取我們想要的就ok了
1.先修改一下build.gradle文件笛谦,引入依賴
//recyclerview
implementation 'com.android.support:recyclerview-v7:28.+'
//retrofit2
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
//Rxjava and Retrofit(Retrofit+Rx需要添加的依賴)
implementation 'com.squareup.retrofit2:adapter-rxjava:2.4.0'
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'io.reactivex:rxjava:1.2.1'
//TextInputLayout
implementation 'com.android.support:design:28.+'
2.看一下后臺(tái)的數(shù)據(jù)樣式
根據(jù)json格式構(gòu)建我們的bean用于接收數(shù)據(jù)
由于bean類過長(zhǎng)抱虐,這里我就不再展示了,有興趣的朋友可以看我的源碼
3.創(chuàng)建Retrofit的api接口揪罕,用于寫請(qǐng)求數(shù)據(jù)的方法
public interface DataRequest {
//獲取天氣數(shù)據(jù)梯码,baseURL在model類里聲明
@GET("now")
Observable<Weather> getNowWeather(@Query("location")String location,@Query("key")String key);
}
4.構(gòu)建自己的MVP架構(gòu)
我們先思考一下每層需要做的事情宝泵,
view:通過presenter從model層獲取到數(shù)據(jù)并展示到界面上,因此我們構(gòu)建一個(gè)setWeather方法轩娶,并傳一個(gè)location用于告訴model層我們要獲取哪里的數(shù)據(jù)
presenter:連接model和view儿奶,因此其中的方法就是model和view方法的集合
model:通過presenter從view層得到要獲取哪里的數(shù)據(jù),運(yùn)用Retrofit向后臺(tái)發(fā)出數(shù)據(jù)請(qǐng)求
工程的圖紙有了鳄抒,下面我們就該蓋樓了闯捎!
MainContract
public class MainContract {
public interface Presenter{
//獲取天氣數(shù)據(jù)
void getWeather(String location);
//設(shè)置天氣到view上
void setWeather(List<Weather> weathers);
}
public interface View{
//獲取數(shù)據(jù)成功
void getSuccess();
//獲取失敗
void getFailed();
//把數(shù)據(jù)顯示到view上
void setWeather(List<Weather> weathers);
}
}
MainPresenter(Presenter的具體實(shí)現(xiàn))
public class MainPresenter implements MainContract.Presenter{
private MainRepository mainRepository;
private MainContract.View mainView;
public MainPresenter(MainContract.View mainView) {
mainRepository = new MainRepository(this);
this.mainView = mainView;
}
@Override
public void getWeather(String location) {
mainRepository.getWeather(location);
}
@Override
public void setWeather(List<Weather> weathers) {
mainView.setWeather(weathers);
}
}
MainRepository(請(qǐng)求數(shù)據(jù)方法的具體實(shí)現(xiàn),其中運(yùn)用了Retrofit+RxJava)
public class MainRepository {
private final static String KEY = "你自己的key";
private final static String TAG = "MainRepository";
private final static String BASE_URL = "https://free-api.heweather.com/s6/weather/";
private List<Weather> weathers = new ArrayList<>();
private MainContract.Presenter presenter;
public MainRepository(MainContract.Presenter presenter) {
this.presenter = presenter;
}
/**
* 獲取天氣數(shù)據(jù)
* @param location 城市
* @return Weather類的數(shù)據(jù)
*/
public void getWeather(String location){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
DataRequest dataRequest = retrofit.create(DataRequest.class);
dataRequest.getNowWeather(location,KEY)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Weather>() {
@Override
public void onCompleted() {
presenter.setWeather(weathers);
Log.d(TAG, "onCompleted: " + weathers.get(0).getHeWeather6().get(0).getBasic().getLocation());
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError: " + e.getMessage());
}
@Override
public void onNext(Weather weather) {
weathers.add(weather);
Log.d(TAG, "onNext: " + weather.getHeWeather6().get(0).getBasic().getLocation());
}
});
weathers.clear();
}
}
MainActivity(視圖層的具體實(shí)現(xiàn)许溅,ps:部分代碼)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
onClick();
}
public void init(){
presenter = new MainPresenter(this);
editText = findViewById(R.id.et_city);
tAdminArea = findViewById(R.id.t_admin_area);
tCnty = findViewById(R.id.t_cnty);
tCondTxt = findViewById(R.id.t_cond_txt);
tFl = findViewById(R.id.t_fl);
tHum = findViewById(R.id.t_hum);
tLat = findViewById(R.id.t_lat);
tLoc = findViewById(R.id.t_loc);
tLocation = findViewById(R.id.t_location);
tLon = findViewById(R.id.t_lon);
tParentCity = findViewById(R.id.t_parent_city);
tTmp = findViewById(R.id.t_tmp);
tWindDir = findViewById(R.id.t_wind_dir);
tWindSc = findViewById(R.id.t_wind_sc);
tWindSpd = findViewById(R.id.t_wind_spd);
bSearch = findViewById(R.id.b_search);
background = findViewById(R.id.background);
//隱藏標(biāo)題欄
ActionBar actionBar = getSupportActionBar();
if(actionBar != null){
actionBar.hide();
}
}
public void onClick(){
bSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sCity = editText.getText().toString();
presenter.getWeather(sCity);
Log.d(TAG, "onClick: " + sCity);
//隱藏軟鍵盤
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
}
});
//回車鍵的監(jiān)聽
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
if (i == EditorInfo.IME_ACTION_UNSPECIFIED) {
sCity = editText.getText().toString();
presenter.getWeather(sCity);
Log.d(TAG, "onClick: " + sCity);
//隱藏軟鍵盤
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
}
return false;
}
});
}
@Override
public void getSuccess() {
Toast.makeText(getApplicationContext(),"獲取數(shù)據(jù)成功",Toast.LENGTH_SHORT).show();
}
@Override
public void getFailed() {
Toast.makeText(getApplicationContext(),"獲取數(shù)據(jù)失敗",Toast.LENGTH_SHORT).show();
}
@Override
public void setWeather(List<Weather> weathers) {
tWindSpd.setText("風(fēng)速: " + weathers.get(0).getHeWeather6().get(0).getNow().getWindSpd() + "公里/小時(shí)");
tWindSc.setText("風(fēng)力: " + weathers.get(0).getHeWeather6().get(0).getNow().getWindSc() + "級(jí)");
tWindDir.setText("風(fēng)向: " + weathers.get(0).getHeWeather6().get(0).getNow().getWindDir());
tTmp.setText("溫度: " + weathers.get(0).getHeWeather6().get(0).getNow().getTmp() + "℃");
tParentCity.setText("市: " + weathers.get(0).getHeWeather6().get(0).getBasic().getParentCity());
tLon.setText("經(jīng)度: " + weathers.get(0).getHeWeather6().get(0).getBasic().getLon());
tLocation.setText("地區(qū): " + weathers.get(0).getHeWeather6().get(0).getBasic().getLocation());
tLat.setText("緯度: " + weathers.get(0).getHeWeather6().get(0).getBasic().getLat());
tHum.setText("相對(duì)濕度: " + weathers.get(0).getHeWeather6().get(0).getNow().getHum());
tFl.setText("體感溫度: " + weathers.get(0).getHeWeather6().get(0).getNow().getFl() + "℃");
tCondTxt.setText("天氣狀況: " + weathers.get(0).getHeWeather6().get(0).getNow().getCondTxt());
tCnty.setText("國(guó)家: " + weathers.get(0).getHeWeather6().get(0).getBasic().getCnty());
tAdminArea.setText("省: " + weathers.get(0).getHeWeather6().get(0).getBasic().getAdminArea());
addWeatherPhoto();
}
就這樣瓤鼻,項(xiàng)目完成了是不是很簡(jiǎn)單?MVP架構(gòu)讓我們的整個(gè)項(xiàng)目都很清晰贤重,Retrofit讓我們能夠輕松的實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求茬祷,Rxjava配合Retrofit使用,整個(gè)代碼成一條鏈?zhǔn)讲⒒龋⑶铱梢宰匀绲那袚Q線程祭犯,簡(jiǎn)直太方便了!
能看我廢話到這里的朋友我真的很感激滚停,作為一個(gè)剛剛上路的小白沃粗,未來還有更多的路要走,希望能和大家一起進(jìn)步键畴,感謝大家的觀看最盅,上男神!
最后起惕,附上我的github上的項(xiàng)目地址:
github傳送門