一个例子包含mvp、rxjava以及retrofit2的使用
2017-04-25 13:29
429 查看
前言:之前就学习了相关的知识,一直未结合使用,现在打算结合起来使用,这个例子就是包含mvp、rxjava以及retrofit2的基本用法。下一篇文章会基于这篇文章的基础介绍dagger2的用法。
首先,在gralde文件中引入后续要用到的库:
MVP这里就简单介绍下:
View :负责绘制UI元素、与用户进行交互(在Android中体现为Activity);
View interface :需要View实现的接口,View通过View interface与 Presenter进行交互,降低耦合,方便进行单元测试;
Model :负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合)
Presenter :作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。
注意 presenter和view的交互一般是通过接口来实现的。view和model是不能直接交互的,以上设计主要是为了降低代码间的耦合。
我们这里的例子是使用上面的这些框架来实现listview中数据的填充,数据来源于网络。使用retrofit 实现数据的下载和解析,rxjava来保持代码简洁以及线程间的快速切换。
项目的结构如下图:
MyServiceBase 代码如下:
该类主要就是初始化retrofit,以及通过参数isGetImg来选择是加载图片还是加载数据,很简单,都有注释。
IMyService代码如下:
getData 是获取数据,getBitmap是用于listview每个item获取图片。
@GET(“api/teacher”) 以及@Query(“type”)都是retrofit的基本用法,用来填充获取数据的URL。
MyImageLoaderUtils 是用来获取图片的,其中增加了用LruCache做图片缓存,代码如下:
上面用到了rxjava的主要方法都有注释。
下面主要是mvp的内容了,我们的界面很简单,就是ListView和progressbar,当加载数据的时候显示progressbar,加载数据完成后 隐藏progressbar。
所以我们先定义一个IBaseView接口,Presenter就是通过该接口和View交互。
我们这个接口需要哪几个方法呢?
1. 请求数据是要显示 progressbar
2. 请求数据完成是要隐藏 progressbar
3. 请求数据成功后将数据set到View中。
4. 请求数据失败要toast “获取数据失败”
在MainActivity里面实现IBaseView 接口:
MainActivity 持有Presenter,通过Presenter来请求数据,MainPresenter如下:
MainPresenter 中持有 IBaseView,以及请求数据操作的Model。由于rxjava在请求数据完成后将现场转到主线程,所以我们可以在回调onSuccess以及onFailed 中操作UI。
MainModel 如下:
下一篇在本文的基础上讲 dagger2的应用。
学习rxjava
可以访问:https://gank.io/post/560e15be2dca930e00da1083
首先,在gralde文件中引入后续要用到的库:
//rxjava 以及rxandroid compile 'io.reactivex:rxjava:1.0.14' compile 'io.reactivex:rxandroid:1.0.1' //retrofit compile 'com.squareup.retrofit2:retrofit:2.0.2' compile 'com.squareup.retrofit2:converter-gson:2.0.2' //okhttp 以及在retrofit中使用rxjava要导入的库 compile 'com.squareup.okhttp3:okhttp:3.1.2' compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2' //图片加载经典库universalimageloader compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
MVP这里就简单介绍下:
View :负责绘制UI元素、与用户进行交互(在Android中体现为Activity);
View interface :需要View实现的接口,View通过View interface与 Presenter进行交互,降低耦合,方便进行单元测试;
Model :负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合)
Presenter :作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。
注意 presenter和view的交互一般是通过接口来实现的。view和model是不能直接交互的,以上设计主要是为了降低代码间的耦合。
我们这里的例子是使用上面的这些框架来实现listview中数据的填充,数据来源于网络。使用retrofit 实现数据的下载和解析,rxjava来保持代码简洁以及线程间的快速切换。
项目的结构如下图:
MyServiceBase 代码如下:
public class MyServiceBase { public static IMyService getService(boolean isGetImg, int readTimeOut, int connectTimeOut){ OkHttpClient client = new OkHttpClient.Builder() .readTimeout(readTimeOut <= 0 ? 30 : readTimeOut, TimeUnit.SECONDS) .connectTimeout(connectTimeOut <= 0 ? 30 : connectTimeOut, TimeUnit.SECONDS) .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(isGetImg ? "http://img.mukewang.com/":"http://www.imooc.com/") .addConverterFactory(GsonConverterFactory.create())//gson 解析 .addCallAdapterFactory(RxJavaCallAdapterFactory.create())// rxjava 方法 .client(client) .build(); IMyService myService = retrofit.create(IMyService.class); return myService; } }
该类主要就是初始化retrofit,以及通过参数isGetImg来选择是加载图片还是加载数据,很简单,都有注释。
IMyService代码如下:
public interface IMyService { @GET("api/teacher") Observable<DataBean> getData(@Query("type") int type, @Query("num") int num); @GET Observable<ResponseBody> getBitmap(@Url String url); }
getData 是获取数据,getBitmap是用于listview每个item获取图片。
@GET(“api/teacher”) 以及@Query(“type”)都是retrofit的基本用法,用来填充获取数据的URL。
MyImageLoaderUtils 是用来获取图片的,其中增加了用LruCache做图片缓存,代码如下:
public class MyImageLoaderUtils { private LruCache<String , Bitmap> bitmapLruCache ; private ImageView imageView; private String mImgUrl; public MyImageLoaderUtils(){ int maxMemorySize = (int) Runtime.getRuntime().maxMemory(); int cacheSize = maxMemorySize/4; bitmapLruCache = new LruCache<String , Bitmap>(cacheSize){ @Override protected int sizeOf(String key, Bitmap value) { return value.getByteCount(); } }; } private void setBitmapToCache(String url, Bitmap bm){ if(getBitmapFromCache(url) == null){ bitmapLruCache.put(url, bm); } } private Bitmap getBitmapFromCache(String url){ return bitmapLruCache.get(url); } public void setImgByUrl(ImageView imgView, String url) { mImgUrl = url; Bitmap bm = getBitmapFromCache(url); if(bm != null){ imgView.setImageBitmap(bm); }else{ getBitmap(imgView, url); } } public interface ImgService { @GET Observable<ResponseBody> getImgBody(@Url String url); } private void getBitmap(final ImageView imgView, final String url) { IMyService imgService = MyServiceBase.getService(true, 0, 0); imgService.getBitmap(url).subscribeOn(Schedulers.newThread()) .observeOn(Schedulers.io())//io线程获取图片 .map(new Func1<ResponseBody, Bitmap>() {//map方法是用来将ResponseBody转换成Bitmap输出 @Override public Bitmap call(ResponseBody responseBody) { InputStream is = null; try { is = responseBody.byteStream(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (is != null) { is.close(); } } catch (IOException e) { e.printStackTrace(); } } if (is != null) { return BitmapFactory.decodeStream(is); } return null; } }).observeOn(AndroidSchedulers.mainThread())//跳转到主线程 .subscribe(new Action1<Bitmap>() { @Override public void call(Bitmap bitmap) { Log.e(TestListViewActivity.TAG, "bitmap = " + bitmap); bitmapLruCache.put(url, bitmap); String imgUrl = (String) imgView.getTag(); if(imgUrl.equals(url)){//防止滑动listview的时候图片加载错乱 imgView.setImageBitmap(bitmap); } } }); } }
上面用到了rxjava的主要方法都有注释。
下面主要是mvp的内容了,我们的界面很简单,就是ListView和progressbar,当加载数据的时候显示progressbar,加载数据完成后 隐藏progressbar。
所以我们先定义一个IBaseView接口,Presenter就是通过该接口和View交互。
我们这个接口需要哪几个方法呢?
1. 请求数据是要显示 progressbar
2. 请求数据完成是要隐藏 progressbar
3. 请求数据成功后将数据set到View中。
4. 请求数据失败要toast “获取数据失败”
public interface IBaseView { void showProgressView(); void hideProgressView(); void setData(List<DataBean.ItemData> datas); void getDataFailed(); }
在MainActivity里面实现IBaseView 接口:
public class MainActivity extends Activity implements IBaseView { private ProgressBar mProgressBar; private ListView mListView; private List<DataBean.ItemData> mdDatas; private LvAdapter mLvAdapter; private MainPresenter mMainPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.mvp_rxjava_dagger2_retrofit2_main_layout); initView(); mMainPresenter.getLessonData(); } private void initView() { mProgressBar = (ProgressBar) findViewById(R.id.mvp_rxjava_progressbar); mListView = (ListView) findViewById(R.id.mvp_rxjava_listview); mdDatas = new ArrayList<>(); mLvAdapter = new LvAdapter(this); mMainPresenter = new MainPresenter(this); } @Override public void showProgressView() { mProgressBar.setVisibility(View.VISIBLE); } @Override public void hideProgressView() { mProgressBar.setVisibility(View.INVISIBLE); } @Override public void setData(List<DataBean.ItemData> datas) { mLvAdapter.setItemDataList(datas); mListView.setAdapter(mLvAdapter); } @Override public void getDataFailed() { Toast.makeText(this, "获取数据失败", Toast.LENGTH_SHORT).show(); } }
MainActivity 持有Presenter,通过Presenter来请求数据,MainPresenter如下:
public class MainPresenter { private final static String TAG = "MainPresenter"; private MainModel mainModel; private IBaseView baseView; public MainPresenter(IBaseView baseView){ this.baseView = baseView; mainModel = new MainModel(); } public void getLessonData(){ baseView.showProgressView(); mainModel.getData(new onDataListener() { @Override public void onSuccess(List<DataBean.ItemData> datas) { Log.e(TAG, "onSuccess thread name = "+Thread.currentThread().getName()); baseView.setData(datas); baseView.hideProgressView(); } @Override public void onFailed() { Log.e(TAG, "onFailed thread name = "+Thread.currentThread().getName()); baseView.getDataFailed(); baseView.hideProgressView(); } }); } public interface onDataListener { void onSuccess(List<DataBean.ItemData> datas); void onFailed(); }
MainPresenter 中持有 IBaseView,以及请求数据操作的Model。由于rxjava在请求数据完成后将现场转到主线程,所以我们可以在回调onSuccess以及onFailed 中操作UI。
MainModel 如下:
public class MainModel { private static final String TAG = "MainModel"; public void getData(final MainPresenter.onDataListener listener) { IMyService myService = MyServiceBase.getService(false, 0, 0); myService.getData(4, 30).subscribeOn(Schedulers.newThread())//在子线程中下载 .observeOn(AndroidSchedulers.mainThread())//数据下载好后转到main线程 .subscribe(new Subscriber<DataBean>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { Log.e(TAG, e.getMessage()); if (listener != null) { listener.onFailed(); } } @Override public void onNext(DataBean dataBean) { Log.e(TAG, "SIZE = " + dataBean.getDatas().size()); List<DataBean.ItemData> datas = dataBean.getDatas(); if (listener != null) { listener.onSuccess(datas); } } }); }
下一篇在本文的基础上讲 dagger2的应用。
学习rxjava
可以访问:https://gank.io/post/560e15be2dca930e00da1083
相关文章推荐
- TensorFlow自带例子已经包含了android和ios下的摄像头图像分类示例Inception v1,这里补充一个Windows下的,使用AForge库(www.aforgenet.com)操作
- 转VC6.0中gdiPlus的使用以及一个bmp转jpg的小例子[bobob原创]
- spring笔记--使用springAPI以及自定义类 实现AOP的一个例子
- VC6.0中gdiPlus的使用以及一个小例子
- 事件代理总结: 已经有一些使用主流类库的事件代理示例出现了,比如说jQuery、Prototype以及Yahoo! UI。你也可以找到那些不用任何类库的例子,比如说Usable Type blog上的这一个。一旦需要的话,事件代理将是你工具箱里的一件得心应手的工具,而且它很容易实现。
- VC6.0中gdiPlus的使用以及一个bmp转jpg的小例子
- 使用MVP框架,retrofit结合Rxjava以及fresco加载图片,用recycleview实现
- Redis的安装、使用以及php中扩展redis并实现php操作redis的一个例子
- 使用retrofit框架的网络请求方法使用例子,同时+MVP +rxjava + rxandroid使用
- 一个App架构例子分析--UI层使用MVP模式;各层之间使用Otto实现通信
- 使用RxJava+Retrofit+MVP+Glide开发一个简单的新闻客户端
- FMDB的使用详解以及一个简单的小例子
- VC6.0中gdiPlus的使用以及一个小例子
- 一个mat和iplimage以及使用cvInRangeS批量修改矩阵值例子
- Retrofit2.0的学习以及Rxjava与Retrofit2的结合使用
- MVP+Dagger2+Retrofit2.0+Rxjava看这一个例子就够了
- 使用retrofit框架的网络请求方法使用例子,同时+MVP +rxjava + rxandroid使用
- spring笔记--使用springAPI以及自定义类 实现AOP的一个例子
- 总结:用一个例子包含c++的所有的基本知识点(一)
- [数据库测试]强烈推荐一个python ODBC数据源插件,可支持Oracle,Db2,Mysql,Sql-server以及各种数据库版本,附例子和测试程序