mvp+rxjava+rxbus+retrofit+butterknife最新实践
了解android的人应该经常听到一些框架术语,比如说mvc,mvp, mvvp ,rxjava,rxandroid等等,最近有时间所以整理了一些基本的demo,下面我们来具体看看.
mvp:相对于mvc来说将view和model分离开来,由persenter控制,这样有利于代码解耦和,如果业务新增需求,则只需要改动model,不需要改动view层,下面看下目录结构和需要引用的jar
首先定义一个接口model,里面包含了需要做的method,
void setUserName(String username);
void setPwd(String pwd);
UserBean load(int id);//通过id读取user信息,返回一个
UserBean Listsave(int id, String username, String pwd);//通过id保存user信息,返回一个UserBean
然后写一个model实现类,实现类中接受presenter传过来的值或者方法,
@Override
public Listsave(intid,String username,String pwd) {
UserBean userBean =newUserBean(id,username,pwd);
userBeens.add(userBean);
returnuserBeens;
}
然后定义一个view接口
StringgetUserName();
StringgetPwd();
voidsetUserName(StringuserName);
voidsetPwd(Stringpwd);
之后在定义一个persenter类,这里persenter管理着view 和model两个实现类,
public classUserPresenter {
privateIUserViewmUserView;
privateIUserModelmUserModel;
publicUserPresenter(IUserView mUserView) {
this.mUserView= mUserView;
this.mUserModel=newIUserModelimpl();
}
public voidsaveUser(intid,String username,String pwd) {
mUserModel.setId(id);
mUserModel.setUserName(username);
mUserModel.setPwd(pwd);
mUserModel.save(id,username,pwd);
}
public voidloadUser(intid) {
UserBean bean =mUserModel.load(id);
mUserView.setUserName(bean.getName());//通过调用IUserView的方法来更新显示
mUserView.setPwd(bean.getPwd());
}
之后就是我们自己的activity里面了或者fragment里面了,我们需要实现view接口,在view实现类中new 一个presenter对象,然后在执行方法时候调用
presenter.saveUser(getID(),getUserName(),getPwd());
presenter.loading(MainActivity.this);
如果需要新增一个方法,比如加载一个loading ,我们可以直接在presenter中添加
public voidloading(Context context) {
finalProgressDialog dialog = ProgressDialog.show(context,"登录中...","正在登录...");
newThread(newRunnable() {
@Override
public voidrun() {
try{
Thread.sleep(2000);
dialog.cancel();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
这样确实比较方便,拓展性也比较强.总结一些mvp就是说我们的presenter完成二者的交互,那么肯定需要二者的实现类。大致就是从View中获取需要的参数,交给Model去执行业务方法,执行的过程中需要的反馈,以及结果,再让View进行做对应的显示。
rxjava异步任务其主要的核心就是观察者模式,以前的文章中有专门说过观察者,通过observer观察者和observerble被观察者进行的订阅事件,这里来说的是用Retrofit+rxjava一起使用.Retrofit是一个底层由okhttp封装的网络请求框架,可以取消单个网络请求,主要使用配置如下:
OkHttpClient.Builder httpclientBuilder =newOkHttpClient.Builder();
httpclientBuilder.connectTimeout(DEFAULT_TIMEOUT,TimeUnit.SECONDS);
retrofit=newRetrofit.Builder()
.client(httpclientBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(baseUrl)
.build();
movieService=retrofit.create(MovieService.class);
addCallAdapterFactory可以添加对rxjava的支持,也就是说原有的retrofit在请求成功后用Call来回调,这里如果用rxjava的话,就是Subscriber来进行回调处理.
原生的请求方式:
@GET("top250")
CallgetTopMovie(@Query("start")intstart,@Query("count")intcount);
rxjava请求方式:
@GET("top250")
ObservablegetTopMoviebyRx(@Query("start")intstart,@Query("count")intcount);
配置MovieService时候可以用到
在bean中建立右键找到GsonFormat
粘贴json文件就可以一次性生成方法.如MovieBean
继续来说retrofit使用
public voidgetTopMovie(Subscriber subscriber, intstart, intcount) {
movieService.getTopMoviebyRx(start,count)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
}
定义一个观察者,执行请求时候调用:
private voidgetMovieByRx() {
subscriber=newSubscriber() {
@Override
public voidonCompleted() {
Toast.makeText(RetrofitActivity.this,"Get Top Movie Completed",Toast.LENGTH_SHORT).show();
}
@Override
public voidonError(Throwable e) {
//subscriber.unsubscribe();//取消一个网络请求
Toast.makeText(RetrofitActivity.this,e.getMessage(),Toast.LENGTH_SHORT).show();
}
@Override
public voidonNext(MovieBean movieBean) {
Log.e("content",movieBean.getTitle());
}
};
BaseUrl.getInstance().getTopMovie(subscriber,0,10);
}
onComplete网络请求结束;onError请求失败,onEext获取请求结果,这里观察者是没有unrester方法的,如果需要取消网络请求可以用subscrrber的unsubcrible来取消订阅就可以取消网络请求.
Butterknife注解,可以方便xml中生成id属性的定义,
下载好后重启as,然后
右键选择需要生成的id和是否生成关联的onclick点击事件,生成好后就是
@Bind(R.id.retrofit)
Buttonretrofit;
@Bind(R.id.retrofitrx)
Buttonretrofitrx;
@Bind(R.id.rxbus)
Buttonrxbus;
onclick方法中:
@OnClick({R.id.retrofit,R.id.retrofitrx,R.id.rxbus})
public voidonViewClicked(View view) {
switch(view.getId()) {
caseR.id.retrofit:
break;
caseR.id.retrofitrx:
getMovieByRx();
break;
caseR.id.rxbus:
RxBus.getInstance().post(newRefreshMessage("mingzi","333"));
break;
}
现在在来说说rxbus这个的使用 方法,以前经常用的是eventBus,里面有一个otto.jar,但是在引入了rxjava和rxandroid.jar后,去执行otto方法时候Bus.getInstance.post(new Method(params))时候,执行就会报错,而且接收方@subscribe方法也监听不到,既然这样,那就使用rxbus看看是否可以,与eventbus使用方法大同小异,目的就是在当前代码中执行任何一个地方的方法,使用如下:
定一个基类,说明发送消息和接收消息等方法
public classRxBus {
private static volatileRxBusmInstance;
private finalSubjectbus;
publicRxBus() {
bus=newSerializedSubject<>(PublishSubject.create());
}
/**
*单例模式RxBus
*
*@return
*/
public staticRxBusgetInstance() {
RxBus rxBus2 =mInstance;
if(mInstance==null) {
synchronized(RxBus.class) {
rxBus2 =mInstance;
if(mInstance==null) {
rxBus2 =newRxBus();
mInstance= rxBus2;
}
}
}
returnrxBus2;
}
/**
*发送消息
*
*@paramobject
*/
public voidpost(Object object) {
bus.onNext(object);
}
/**
*接收消息
*
*@parameventType
*@param
*@return
*/
public ObservabletoObserverable(Class eventType) {
returnbus.ofType(eventType);
}
然后定义我们需要传递的参数,这里可以什么也不传,也可以传递对象
public classRefreshMessage {
privateStringname;
privateStringid;
publicRefreshMessage(String name,String id) {
this.name= name;
this.id= id;
}
publicStringgetName() {
returnname;
}
public voidsetName(String name) {
this.name= name;
}
publicStringgetId() {
returnid;
}
public voidsetId(String id) {
this.id= id;
}
}
执行发送方法:
RxBus.getInstance().post(newRefreshMessage("mingzi","333"));
然后在需要接收的类里面接收方法,activity中可以写在onCreate或者onStart中:
rxbus= RxBus.getInstance().toObserverable(RefreshMessage.class)
.subscribe(newAction1() {
@Override
public voidcall(RefreshMessage refreshMessage) {
Toast.makeText(MainActivity.this,refreshMessage.getName() + refreshMessage.getId(),Toast.LENGTH_LONG).show();
}
});
为了避免oom问题,在onDestroy中解除订阅
@Override
protected voidonDestroy() {
if(!rxbus.isUnsubscribed()) {
rxbus.unsubscribe();
}
super.onDestroy();
}
这里附上源码地址,欢迎star,fork,后续继续更新中...