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

来源:互联网 发布:开淘宝商城要多少钱 编辑:程序博客网 时间:2024/04/29 16:20

之前看了关于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 <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去掉了,不能够直接看效果。
源码

0 0
原创粉丝点击