国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

基于retrofit+rxjava+knife的mvp模式demo

2019-11-06 09:36:57
字體:
來源:轉載
供稿:網友

最近學習了挺多東西,所以想寫個demo把最近所學的全都用到,于是就有了這篇博客,這個demo實現的功能特別簡單,就是一個查詢天氣,并且放到textview及recyclerview上顯示出來,用的mvp設計框架,也是這兩天才稍微看懂的東西,如果有錯,還請各路大佬指出,那么廢話不多說,先上效果圖

從圖中能看出有以下功能:

1. 顯示PRogress2. 隱藏progress3. 請求數據成功或失敗彈出toast提示4. 將獲取到的數據設置到TextView上5. 將獲取到的數據設置到recyclerview上6. 如果查詢出錯清空所有的數據

確定了功能那么就是如何實現了,根據mvp的思想,V層只負責初始化view,并將view層接收到的數據(即EditText等)傳遞到P層,P層再傳遞給M層,讓M層操作數據,包括存儲和耗時操作等,然后M層再將數據傳回給P層,P層來更新UI,說得再明白點,mvp就是面向接口,那么m,v,p層的接口該怎么寫呢?很簡單,根據上面我們列出的功能來寫相應的接口,直接來看代碼:

public interface IMainActivity {	//顯示progress	void showProgress();	//隱藏progress	void hideProgress();	/*	* 設置文本	* @param temperaturestr:今日溫度,@param  coldstr:今日建議,@param citystr:城市	* @param yesterdayflstr:昨日風力,@param yesterdayfxstr:昨日風向,@param yesterdayhighstr:昨日最高溫	* @param yesterdaylowstr:昨日最低溫,@param yesterdaytypestr:昨日天氣類型,@param yesterdaydatestr:昨日時間	*	* */	void setText(String temperaturestr, String coldstr, String citystr, String yesterdayflstr,	             String yesterdayfxstr, String yesterdayhighstr, String yesterdaylowstr,	             String yesterdaytypestr, String yesterdaydatestr);	//設置item	void setItem(MyAdapter adapter);	//Toast提示	void showMsg(String msg);	//輸入錯誤時清空textview,recyclerview的item	void clearAll();}那么現在V層,也就是Activity只需要實現這個接口即可,看代碼:

public class MainActivity extends Activity implements IMainActivity {	@BindView(R.id.temperature)	TextView temperature;	@BindView(R.id.rv)	RecyclerView rv;	@BindView(R.id.citykey)	EditText citykey;	@BindView(R.id.query)	Button query;	@BindView(R.id.progress)	ProgressBar progress;	private WeatherPresenter weatherPresenter;	//初始化控件,并new出P層實例	@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.activity_main);		ButterKnife.bind(this);		weatherPresenter = new WeatherPresenter(this);	}	//點擊監聽,用P層實例去調用請求數據的接口	@OnClick(R.id.query)	void query() {		if (citykey.getText().toString().equals("")) {			citykey.setError("不能為空");		}		weatherPresenter.validateCredentials(citykey.getText().toString());	}	@Override	public void showProgress() {		progress.setVisibility(View.VISIBLE);	}	@Override	public void hideProgress() {		progress.setVisibility(View.GONE);	}	@Override	public void setText(String temperaturestr, String coldstr, String citystr, String yesterdayflstr,	                    String yesterdayfxstr, String yesterdayhighstr, String yesterdaylowstr,	                    String yesterdaytypestr, String yesterdaydatestr) {		temperature.setText("城市:" + citystr + "/n" +				"今日溫度:" + temperaturestr + "/n" +				"今日建議:" + coldstr + "/n" +				"昨日時間:" + yesterdaydatestr + "/n" +				"昨日天氣:" + yesterdaytypestr + "/n" +				"昨日最" + yesterdayhighstr + "/n" +				"昨日最" + yesterdaylowstr + "/n" +				"昨日風力:" + yesterdayflstr + "/n" +				"昨日風向:" + yesterdayfxstr		);	}	//設置適配器,顯示recyclerview,adapter由P層傳回	@Override	public void setItem(MyAdapter adapter) {		rv.setLayoutManager(new LinearLayoutManager(this));		rv.setAdapter(adapter);	}	@Override	public void showMsg(String msg) {		Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();	}	@Override	public void clearAll() {		rv.setAdapter(null);		temperature.setText("");	}這里注意一下,我在onCreate方法中實例化了P層,原因就是要讓P層拿到V層的實例,這樣才能讓P層去操作UI,那么P層需要做哪些操作呢,前面說了,M層去操作數據,P層操作UI,再看看我們的效果圖,V層獲取到了EditText輸入的字符串,并且點擊查詢后獲取到了相應的數據,現在要做的,就是把V層獲取到的數據傳遞給M層,讓M層去做耗時操作,但是MVP模式,V層是不能直接跟M層進行交互的,怎么辦?很簡單,我們還有P層沒用到,P層的作用就是V層和M層的橋梁,讓V層把數據通過P層傳遞給M層即可,具體怎么做?我們再來分析一下,V層需要傳遞數據給M層,那么P層就需要一個方法,來接收V層的數據,這個方法就是點擊查詢按鈕后要執行的方法,那么P層現在要做的工作就很簡單了,let me show you code:

public interface IWeatherPresenter {	//請求數據	void validateCredentials(String citykey);}接下來在定義一個類去實現該接口

//進行數據請求,請求時顯示progress	@Override	public void validateCredentials(String citykey) {		view.showProgress();		model.getWeather(citykey, this);	}有同學就要問了,model.getWeather又是從哪里來的方法,都是什么鬼,不要急,前面說了,P層需要一個方法來接收V層傳遞過來數據,然后才能讓P層把數據傳遞給M層,那model.getWeather肯定就是M層的方法了,沒錯,M層需要做耗時操作,而具體要查詢哪一個城市的天氣數據,就是從V層傳遞過來的,邏輯是不是一下就通了,再來分析下M層,M層需要的就是耗時操作,那么耗時操作就有兩種可能:

1、請求成功

2、請求失敗

所以我們M層的接口寫成這樣:

public interface IWeatherModel {	interface OnLinstener {		//請求失敗		void onFailed();		//請求成功		void onSuccess();	}	//請求數據	void getWeather(String citykey, OnLinstener linstener);}

現在萬事具備,就剩個M層的類來實現這個接口就行了,但是,先暫停一下,看看我們的標題,基于retrofit+rxjava,前面一直沒用,當然就是在這個時候來用的,先給個完整的URL,現在來看看retrofit用來實現get請求的接口:

public interface APIService {	@GET("/weather_mini")	Observable<Bean> getApi(@Query("citykey") String citykey);}有同學要問,返回的Observable是個啥,這個是rxjava特有的,我能力不足,只限于能用的階段。。還不能很好的解釋其中的原理,有興趣的可以去看看這位大佬rxjava的系列文章,接下來是用于解析json的bean類,太長就不放了。。有興趣可以下載源碼看看,現在,要開始寫M層的邏輯了,M層就是用來操作數據的,說白了就是耗時操作,存儲數據,看代碼:

public class WeatherModel implements IWeatherModel {	private static final String TAG = "WeatherModel";	private Retrofit retrofit;	private OkHttpClient client;	private MyBean bean;	//進行耗時操作,訪問數據	@Override	public void getWeather(String citykey, final OnLinstener linstener) {		Interceptor interceptor = new Interceptor() {			@Override			public Response intercept(Chain chain) throws IOException {				Request request = chain.request().newBuilder().build();				return chain.proceed(request);			}		};		client = new OkHttpClient.Builder().addInterceptor(interceptor).build();		retrofit = new Retrofit.Builder()				.baseUrl("http://wthrcdn.etouch.cn")				.addCallAdapterFactory(RxJava2CallAdapterFactory.create())				.addConverterFactory(GsonConverterFactory.create())				.client(client)				.build();		APIService api = retrofit.create(APIService.class);		api.getApi(citykey)				.subscribeOn(Schedulers.io())//在io線程執行				.observeOn(AndroidSchedulers.mainThread())//執行完成后回調給UI線程				.subscribe(new Observer<Bean>() {					@Override					public void onSubscribe(Disposable d) {						Log.i(TAG, "onSubscribe: ");					}					@Override					public void onNext(Bean value) {						if (value.getDesc().equals("OK")) {							bean = new MyBean();							bean.setWendu(value.getData().getWendu());							bean.setGanmao(value.getData().getGanmao());							bean.setCity(value.getData().getCity());							bean.setYesterdayfl(value.getData().getYesterday().getFl());							bean.setYesterdayfx(value.getData().getYesterday().getFx());							bean.setYesterdayhigh(value.getData().getYesterday().getHigh());							bean.setYesterdaylow(value.getData().getYesterday().getLow());							bean.setYesterdaytype(value.getData().getYesterday().getType());							bean.setYesterdaydate(value.getData().getYesterday().getDate());							bean.setList(value.getData().getForecast());							bean.setMsg("請求數據正確,請稍后");							linstener.onSuccess();							Log.i(TAG, "onNext: ");						} else {							bean = new MyBean();							bean.setMsg("請求數據錯誤,請重新輸入");							linstener.onFailed();						}					}					@Override					public void onError(Throwable e) {						linstener.onFailed();						Log.e(TAG, "onError: ");					}					@Override					public void onComplete() {						Log.i(TAG, "onComplete: ");					}				});	}我寫了另一個bean類來存儲所有數據,這樣P層才能直接把數據拿來用,但是在M層存儲好說,怎么在P層取出來呢,如果兩個類持有的不是同一個對象,那P層肯定是取不出數據的,很簡單,有什么需求就寫什么接口,P層需要M層存儲的bean類,那么我們在M層的接口再寫個getBean的方法,然后讓M層去實現不就行了,P層拿到M層的實例直接調用方法就可以拿到我們想要的bean類了,所以完整的M層接口代碼:

public interface IWeatherModel {	interface OnLinstener {		//請求失敗		void onFailed();		//請求成功		void onSuccess();	}	//請求數據	void getWeather(String citykey, OnLinstener linstener);	//獲取bean類	MyBean getBean();}完整的M層代碼:

public class WeatherModel implements IWeatherModel {	private static final String TAG = "WeatherModel";	private Retrofit retrofit;	private OkHttpClient client;	private MyBean bean;	//進行耗時操作,訪問數據	@Override	public void getWeather(String citykey, final OnLinstener linstener) {		Interceptor interceptor = new Interceptor() {			@Override			public Response intercept(Chain chain) throws IOException {				Request request = chain.request().newBuilder().build();				return chain.proceed(request);			}		};		client = new OkHttpClient.Builder().addInterceptor(interceptor).build();		retrofit = new Retrofit.Builder()				.baseUrl("http://wthrcdn.etouch.cn")				.addCallAdapterFactory(RxJava2CallAdapterFactory.create())				.addConverterFactory(GsonConverterFactory.create())				.client(client)				.build();		APIService api = retrofit.create(APIService.class);		api.getApi(citykey)				.subscribeOn(Schedulers.io())//在io線程執行				.observeOn(AndroidSchedulers.mainThread())//執行完成后回調給UI線程				.subscribe(new Observer<Bean>() {					@Override					public void onSubscribe(Disposable d) {						Log.i(TAG, "onSubscribe: ");					}					@Override					public void onNext(Bean value) {						if (value.getDesc().equals("OK")) {							bean = new MyBean();							bean.setWendu(value.getData().getWendu());							bean.setGanmao(value.getData().getGanmao());							bean.setCity(value.getData().getCity());							bean.setYesterdayfl(value.getData().getYesterday().getFl());							bean.setYesterdayfx(value.getData().getYesterday().getFx());							bean.setYesterdayhigh(value.getData().getYesterday().getHigh());							bean.setYesterdaylow(value.getData().getYesterday().getLow());							bean.setYesterdaytype(value.getData().getYesterday().getType());							bean.setYesterdaydate(value.getData().getYesterday().getDate());							bean.setList(value.getData().getForecast());							bean.setMsg("請求數據正確,請稍后");							linstener.onSuccess();							Log.i(TAG, "onNext: ");						} else {							bean = new MyBean();							bean.setMsg("請求數據錯誤,請重新輸入");							linstener.onFailed();						}					}					@Override					public void onError(Throwable e) {						linstener.onFailed();						Log.e(TAG, "onError: ");					}					@Override					public void onComplete() {						Log.i(TAG, "onComplete: ");					}				});	}	//將保存的MyBean類返回給P層	@Override	public MyBean getBean() {		return this.bean;	}}P層完整的代碼:

public class WeatherPresenter implements IWeatherPresenter, IWeatherModel.OnLinstener {	private IMainActivity view;	private IWeatherModel model;	private List<Bean.Data.forecast> list;	//構造器,需要傳入v層實例,并new一個m層實例,以達到讓P層實現橋梁的作用	public WeatherPresenter(IMainActivity view) {		this.view = view;		this.model = new WeatherModel();	}	//進行數據請求,請求時顯示progress	@Override	public void validateCredentials(String citykey) {		view.showProgress();		model.getWeather(citykey, this);	}	//數據請求失敗時隱藏progress	@Override	public void onFailed() {		view.clearAll();		MyBean bean = model.getBean();		view.showMsg(bean.getMsg());		view.hideProgress();	}	//數據請求成功后將數據顯示在控件上,且在請求成功后隱藏progress	@Override	public void onSuccess() {		MyBean bean = model.getBean();		if (bean.getMsg().equals("請求數據正確,請稍后")) {			view.showMsg(bean.getMsg());			view.setText(bean.getWendu(), bean.getGanmao(), bean.getCity(), bean.getYesterdayfl(),					bean.getYesterdayfx(), bean.getYesterdayhigh(), bean.getYesterdaylow(),					bean.getYesterdaytype(), bean.getYesterdaydate());			list = bean.getList();			MyAdapter adapter = new MyAdapter((Context) view, list);			view.setItem(adapter);			view.hideProgress();		}	}}recyclerview的adapter非常簡單,就不貼出來了,有興趣的話就下載源碼自己看看吧,歡迎各位大佬提出建議

demo源碼


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 和政县| 鄢陵县| 上虞市| 关岭| 汉寿县| 土默特左旗| 岳普湖县| 思茅市| 简阳市| 临泽县| 汕头市| 龙江县| 黔江区| 峨眉山市| 克东县| 邹城市| 湘西| 莫力| 南皮县| 本溪| 沂源县| 昌图县| 新昌县| 张家口市| 九龙城区| 喜德县| 溧水县| 新竹县| 保德县| 孙吴县| 马山县| 类乌齐县| 九江市| 金堂县| 敦煌市| 宜君县| 锡林郭勒盟| 鄂伦春自治旗| 马鞍山市| 宜丰县| 黄龙县|