您的位置:首页 > 移动开发 > Android开发

Android MVP+RXJava+Retrofit框架的初步构建

2017-01-22 11:57 393 查看
之前看了关于MVP、RXJava、Retrofit的开发资料就尝试把它们都整合在一起,这里介绍的内容和搭建的框架是基于我的理解去做的,而且也是初步去构建自己的开发框架,所以难免会有理解不到的地方,不敢保证一点bug都没有,也不建议大家用到真实的项目中去,只是拿来学习。

一、MVP模式的简介



view则用来展示数据,显示界面,业务的的处理就交给Presenter 来处理,数据的访问存储就交给Model 来处理,这样分工比较明确,逻辑也清晰,修改起来也比较方便。

(1)其中View可以对应着Activity、Fragment;

(2)Presenter就是一个中介,响应View发出的请求,同时去调用Model来处理,最后也会把请求的结果返回到view中去;

(3)model响应Presenter的请求,并把请求结果返回给presenter,比如请求网络的工作就可以交给它来做;

(4)它们通过接口来实现相互之间的调用。

二、基础框架的搭建

1、Retrofit的构建

(1) 添加依赖库



我这里把它做成依赖库,这样就可以给其它app公用了,就是netlib,

然后在它的build.gradle添加依赖库。

compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.1.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.0'
compile 'com.squareup.retrofit2:converter-scalars:2.0.0'
compile 'com.squareup.retrofit2:retrofit:2.0.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0'
compile 'io.reactivex:rxjava:1.0.10'
compile 'io.reactivex:rxjava:1.1.0'
compile 'io.reactivex:rxandroid:1.1.0'


(2)设置OkHttp

a.可以设置日志信息

b.获取头部信息,比如sessionid,我这里就有获取到登录返回的session

c.设置超时的时间

public class OkhttpManage {
//超时时间,60s
private final static long timeOut=60;
private static OkHttpClient okHttpClient;
public static OkHttpClient getOkHttp(Context applicationContext){
if(okHttpClient==null){
//日志
HttpLoggingInterceptor logging = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
okHttpClient = new OkHttpClient().newBuilder()
.connectTimeout(timeOut, TimeUnit.SECONDS)
.addInterceptor(new GetCookiesInterceptor(applicationContext))
.addInterceptor(logging)
.build();
}
return okHttpClient;
}

/**
* 获取请求头信息,保存cookie
*/
static class GetCookiesInterceptor implements Interceptor {
Context context;
SharedPreferences sp;
SharedPreferences.Editor editor;
public GetCookiesInterceptor(Context context){
this.context = context;
sp = context.getSharedPreferences("Cookie",Context.MODE_PRIVATE);
editor = sp.edit();
}
@Override
public Response intercept(Chain chain) throws IOException {
Response originnalResponse=null;
try {
originnalResponse = chain.proceed(chain.request());
if (!originnalResponse.headers("Set-Cookie").isEmpty()) {
List<String> header = originnalResponse.headers("Set-Cookie");
for (String s : header) {
if (s.contains("JSESSIONID")) {
editor.putString("cookie",s.split(";")[0]);
editor.commit();
}
}
}
}catch (Exception e){
if(e instanceof java.net.SocketTimeoutException){
new LThread(context,1).start();
System.out.println("GetCookiesInterceptor  超时:");
}else if(e instanceof java.net.ConnectException){
new LThread(context,0).start();
System.out.println("网络不通");
}
e.printStackTrace();
}
return originnalResponse;
}
}
static class LThread extends Thread{
Context context;
int flag;
public LThread(Context context,int flag){
this.context = context;
this.flag=flag;
}
@Override
public void run() {
Looper.prepare();
Handler h = new Handler(){
@Override
public void dispatchMessage(Message msg) {
if(msg!=null&&msg.what==0){
Toast.makeText(context,"网络不通,请检查网络",Toast.LENGTH_SHORT).show();
}else if(msg!=null&&msg.what==1){
Toast.makeText(context,"请求超时",Toast.LENGTH_SHORT).show();
}
}
};
h.sendEmptyMessage(flag);
Looper.loop();
}
}

}


(3)创建retrofit的管理类

其中泛型就是下文提到的Model定义的接口,用gson处理返回的数据,用Rxjava做处理数据的适配器。

public class RetrofitManage {

/**
* @param tClass 自定义的请求接口
* @param baseUrl 请求基本路径
* @param context 请求上下文
* @param &
d470
lt;T>
* @return
*/
public static <T> T getNetWorkApi(Class<T> tClass,String baseUrl,Context context){
Converter.Factory gsonConverterFactory = GsonConverterFactory.create();
Converter.Factory scalarsConverterFactory = ScalarsConverterFactory.create();
CallAdapter.Factory rxJavaCallAdapterFactory = RxJavaCallAdapterFactory.create();
Retrofit retrofit = new Retrofit.Builder()
.client(OkhttpManage.getOkHttp(context))
.baseUrl(baseUrl)
.addConverterFactory(scalarsConverterFactory)
.addConverterFactory(gsonConverterFactory)
.addCallAdapterFactory(rxJavaCallAdapterFactory)
.build();
return retrofit.create(tClass);
}

}


2、MVP的构建

(1)定义view的接口

这是用在activity或fragment上显示数据的,根据自己实际的需要定义即可。

public interface GetDataInterface {
//登录成功的回调
void loginSuccess(UserInfoResult userInfoResult);
//错误信息的显示
void onError(Throwable e);
//查询数据成功的回调
void getBusSuccess(AllBusinessResult allBusinessResult);
}


(2)定义presenter 的接口

public interface Loginpresenter {
public  void getAllBus(@NonNull String session);
public void login(String userName, String pwd, String did);
}


(3)定义model接口

这是retrofit的,其中@post代表post请求

a.参数@Header(“Cookie”) String session ,就是要添加到叫“Cookie”头部的内容,根据实际需求修改即可。

b.参数@Query(“username”) String userName,就是请求的参数有username=””

c.像上面一个一个写比较多的时候就不友好了,可以用

@QueryMap Map

public interface LoginAndOther {
@POST("pda/queryGlobalQuantityByDay.action")
Observable<AllBusinessResult> getAllBus(@Header("Cookie") String session);
@POST("pda/mobileLogin.action")
Observable<UserInfoResult> login(@Query("username") String userName,
@Query("password") String pwd, @Query("devId") String did);
@POST("pda/mobileLogin.action")
Observable<UserInfoResult> login2(@QueryMap Map<String,String> opts);
}


(4)实现presenter定义的接口

a、baseUrl就是基本的路径,最好以“/”结尾,这里涉及到公司内容,我就不显示它的路径了

b、GetDataInterface gt; 就是上面定义的view 的接口

c、CompositeSubscription ss;//是RXJava 的内容,用来管理subscription

d、通过RetrofitManage.getNetWorkApi来进行网络请求,这在上面的Retrofit构建里设置的,同时也调用到model的接口了,这是Retrofit的使用

e、subscribeOn(Schedulers.io())可以让请求运行在其它的线程中,

observeOn(AndroidSchedulers.mainThread())可以让显示数据操作运行在主线程中去,

subscribe(oblogin) 用来处理数据、显示数据等操作,并在这个参数的对象里面调用View的接口,即GetDataInterface gt,这样MVP就相互关联起来了,请求数据不会再主线程中,显示数据又回到主线程中去。

Subscription s = RetrofitManage.getNetWorkApi(LoginAndOther.class,baseUrl,context.getApplicationContext())
.login2(opts)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(oblogin);
ss.add(s);


public class LoginImpl implements Loginpresenter{
Context context ;
CompositeSubscription ss;
String baseUrl = "";
GetDataInterface gt;
public LoginImpl(Context context, GetDataInterface gt,CompositeSubscription ss){
this.context = context;
this.ss = ss;
this.gt = gt;
}
Observer<UserInfoResult> oblogin = new Observer<UserInfoResult>() {
@Override
public void onCompleted() {
Log.d("omCompleted","请求完成");
System.out.println("请求完成");
}
@Override
public void onError(Throwable e) {
gt.onError(e);
Log.d("onError",e.getMessage());
e.printStackTrace();
}
@Override
public void onNext(UserInfoResult userInfoResult) {
gt.loginSuccess(userInfoResult);
System.out.println(userInfoResult.toString());
Log.d("userInfoResult ",userInfoResult.success);
}
};

@Override
public  void login(String userName, String pwd, String did) {
Map<String,String> opts = new HashMap<String, String>() ;
opts.put("username",userName);
opts.put("password",pwd);
opts.put("devId",did);
Subscription s = RetrofitManage.getNetWorkApi(LoginAndOther.class,baseUrl,context.getApplicationContext())
.login2(opts)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(oblogin);
ss.add(s);
}

@Override
public void getAllBus(String session) {
Subscription s = RetrofitManage.getNetWorkApi(LoginAndOther.class,baseUrl,context)
.getAllBus(session)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<AllBusinessResult>() {
@Override
public void onCompleted() {
Log.d("omCompleted","请求完成");
System.out.println("请求完成");
}

@Override
public void onError(Throwable e) {
if(e==null)return;
Log.d("onError",e.getMessage());
e.printStackTrace();
}

@Override
public void onNext(AllBusinessResult allBusinessResult) {
gt.getBusSuccess(allBusinessResult);
}
});
ss.add(s);
}
public void destroySubscription(){
System.out.println("unsubscribe");
ss.unsubscribe();
}
}


(5) 在activity或fragment中实现已经定义view的接口

a、就是上面定义的GetDataInterface

b、定义presenter

Loginpresenter lp;

lp = new LoginImpl(this,this,subscriptions);

c、这样就可以通过lp来调用它里面的方法了,比如请求数据

public class DemoActivity extends BaseActivity implements View.OnClickListener,GetDataInterface


三、总结

这是自己动手搭建的框架,其中也遇到不少问题,也参考了RxJavaSamples-master的代码,也是一种尝试。

有需要的也可以下载源码,但是我把url去掉了,不能够直接看效果。

源码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息