Hement:MVP架构中的网络框架(RxJava2+Retrofit2+RxAndroid)(二)

作者 : 开心源码 本文共7589个字,预计阅读时间需要19分钟 发布时间: 2022-05-12 共192人阅读
  • GitHub地址:Hement:持续升级中
  • 因为使用Dagger2的未知性,所以创立一个分支没有使用Dagger2 Hement
  • 如何设计好网络框架,我心中也没答案,看过很多别人的轮子,有些太简单,有限过于复杂,有些为了满足去请求网络,褒贬不一
  • 本文的网络框架基于我三年前的网络框架的更新版,具体请看这里 MVP网络框架(Retorfit+Rxjava+Rxandroid)

加入依赖

    api "com.squareup.retrofit2:retrofit:2.5.0"    api "com.squareup.retrofit2:converter-gson:2.5.0"    api "com.squareup.retrofit2:adapter-rxjava2:2.5.0"    api 'io.reactivex.rxjava2:rxandroid:2.1.0'    api 'io.reactivex.rxjava2:rxjava:2.2.2'    api "com.squareup.okhttp3:logging-interceptor:3.12.0"
  • rxjava:是反应式扩展的Java VM实现:一个用于使用可观察序列组成异步和基于事件的程序的库。
  • rxandroid:这个板块向RxJava增加了最少的类,使得在Android应用程序中编写反应性组件变得简单且无麻烦。更具体地说,它提供了在主线程或者在任何Looper上调度的调度器。
  • converter-gson:通过GsonConverterFactoryRetrofit增加Gson支持
  • logging-interceptor:可以很直观的观察到网络请求的日记
    image.png
    image.png
  • adapter-rxjava2:一个用于适应RXJava 2类型的适配器。

搭建网络框架

  • IMvpView
public interface IMvpView {  /**   * 数据失败的同一解决   * @param errorCode   * @param errorMsg   */  void getDataFail(String errorCode, String errorMsg);  /**   * 发成异常的同一解决   * @param e   */  void onError(Throwable e);}
  • IPresenter 解决和View的生命周期
public interface IPresenter<V extends IMvpView> {    /**     * 和view结合     * @param mvpView     */    void attachView(V mvpView);    /**     * 和view 断开     */    void detachView();}
  • BasePresenter 所有Presenter的基类,同时绑定所有Activity的生命周期
public class BasePresenter<V extends IMvpView> implements IPresenter<V> {    private V mMvpView;    @Override    public void attachView(V mvpView) {        mMvpView = mvpView;    }    @Override    public void detachView() {        mMvpView = null;    }    /**     * 判断能否还在连接在一起的     * @return     */    public boolean isViewAttached() {        return mMvpView != null;    }    public V getMvpView() {        return mMvpView;    }    /**     * 检查View能否附着     */    public void checkViewAttached() {        if (!isViewAttached()) throw new MvpViewNotAttachedException();    }    public static class MvpViewNotAttachedException extends RuntimeException {        public MvpViewNotAttachedException() {            super("在绑定数据之前肯定要绑定视图");        }    }    /**     * 这是Observer 中的 onServer ,当我们调用这个方法,直接就不会走到 onNext中去     * @param disposable     */    public  void dispose(Disposable disposable) {        if (disposable != null && !disposable.isDisposed()) {            disposable.dispose();        }    }}
  • 总体结构图

    总体结构图

网络框架DataManager

  • 根据上篇文章的设计思路 Hement:MVP架构设计(一)
    Android中的MVP模式.jpg
  • 可以知道DataManager不仅仅是解决网络请求那么简单,同时还需要解决本地存储SharedPreferencesSQLite
  • 所以就转变成了,DataManager向外界提供数据对象,数据的解决已经帮您解决好了,使用的时候只要要获取你想要的对象实例,即可以了,具体封装如下
@Singletonpublic class DataManager {    private final IRemoteServer mIRemoteServer;    private final PreferencesHelper mPreferencesHelper;    private final DatabaseHelper mDatabaseHelper;    @Inject    public DataManager(IRemoteServer server, PreferencesHelper preferencesHelper, DatabaseHelper databaseHelper) {        mIRemoteServer = server;        mPreferencesHelper = preferencesHelper;        mDatabaseHelper = databaseHelper;    }    public void loadData(String key, String day, BaseObserver observer) {        Observable<SMResponse<ArrayList<TodayBean>>> today = mIRemoteServer.getToday(key, day);        today.observeOn(AndroidSchedulers.mainThread())                .subscribeOn(Schedulers.io())                .subscribe(observer);    }    public PreferencesHelper getPreferencesHelper() {        return mPreferencesHelper;    }    /**     * 从网络获取数据,缓存到数据库,而后从数据库中取数据     * @return     */    public Observable<TodayBean> syncDBBean() {        return mIRemoteServer.getToday("b15674dbd34ec00ded57b369dfdabd90", "1/1").concatMap(new Function<SMResponse<ArrayList<TodayBean>>, ObservableSource<? extends TodayBean>>() {            @Override            public ObservableSource<? extends TodayBean> apply(@NonNull SMResponse<ArrayList<TodayBean>> response)                    throws Exception {                return mDatabaseHelper.setDBData(response.result);            }        });    }    /**     * 从数据库中取数据     * @return     */    public Observable<List<TodayBean>> getDBBean() {        return mDatabaseHelper.getDBData().distinct();    }}

网络框架如何使用

  • 这里使用的是聚合数据的接口 ,在这里感谢无私的贡献,三年了这个接口还能用,万分感谢
http://v.juhe.cn/todayOnhistory/queryEvent.php?key=b15674dbd34ec00ded57b369dfdabd90&date=1/1
  • 1、定义远程Server:IRemoteServer,在这里我把以前的单独生成的RetrofitServer抽取到IRemoteServer,由于项目使用了Dagger2,后面详情
public interface IRemoteServer {    /**     * http://v.juhe.cn/todayOnhistory/queryEvent.php?key=b15674dbd34ec00ded57b369dfdabd90&date=1/1     * @param key 申请的key     * @param date 日期     * @return 返回历史上的今天     */    @GET("queryEvent.php")    Observable<SMResponse<ArrayList<TodayBean>>> getToday(@Query("key") String key, @Query("date") String date);    class Creator {        public static IRemoteServer newHementService() {          return  SMRetrofit.getService(HementApplication.getContext(), IRemoteServer.class);        }    }}
  • 2、DataManager中的线程调度,结果回调到AndroidSchedulers.mainThread()线程,就是安卓的UI线程。
   private final IRemoteServer mIRemoteServer;    private final PreferencesHelper mPreferencesHelper;    private final DatabaseHelper mDatabaseHelper;    @Inject    public DataManager(IRemoteServer server, PreferencesHelper preferencesHelper, DatabaseHelper databaseHelper) {        mIRemoteServer = server;        mPreferencesHelper = preferencesHelper;        mDatabaseHelper = databaseHelper;    }    public void loadData(String key, String day, BaseObserver observer) {        Observable<SMResponse<ArrayList<TodayBean>>> today = mIRemoteServer.getToday(key, day);        today.observeOn(AndroidSchedulers.mainThread())                .subscribeOn(Schedulers.io())                .subscribe(observer);    }
  • 3、NetWorkPresenter定义
@ConfigPersistentpublic class NetWorkPresenter  extends BasePresenter<NetWorkView> {    private final DataManager mDataManager;    private Disposable mDisposable;    @Inject    public NetWorkPresenter(DataManager dataManager) {        mDataManager = dataManager;    }    @Override    public void attachView(NetWorkView mvpView) {        super.attachView(mvpView);    }    @Override    public void detachView() {        super.detachView();        if (mDisposable != null) mDisposable.dispose();    }    public void loadData(String key,String day){        //检查View能否附着在上面,不在直接抛出异常        checkViewAttached();        //检查能否往下运行        dispose(mDisposable);        mDataManager.loadData(key,day,new BaseObserver<SMResponse<ArrayList<TodayBean>>>(new SubscriberListener<SMResponse<ArrayList<TodayBean>>>() {            @Override            public void onSubscribe(Disposable disposable) {                super.onSubscribe(disposable);                mDisposable = disposable;            }            @Override            public void onSuccess(SMResponse<ArrayList<TodayBean>> response) {                getMvpView().getDataSuccess(response.result);            }            @Override            public void onFail(String errorCode, String errorMsg) {                getMvpView().getDataFail(errorCode,errorMsg);            }            @Override            public void onError(Throwable e) {                getMvpView().onError(e);            }        }));    }}
  • 4、在Activity中的使用,通过Dagger2依赖注入NetWorkPresenter,同时在 onDestroy()中,销毁RxJava2正在调度的任务,个人了解的就是,关闭Activity,网络请求也有可能是在执行中,所以需要销毁。
public class NetWorkActivity extends BaseActivity implements NetWorkView, View.OnClickListener {    String key="b15674dbd34ec00ded57b369dfdabd90";    @Inject    NetWorkPresenter mMainPresenter;    private Button mBtn;    private EditText mDay;    private EditText mMonth;    private RecyclerView mRecyclerView;    private SMAdapter mSmAdapter;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        activityComponent().inject(this);        setContentView(R.layout.activity_net_work);        Timber.tag(getClassName()).i("mMainPresenter   =%s",mMainPresenter);        mMainPresenter.attachView(this);        initView();        initListener();    }    private void initView() {        mBtn = (Button) findViewById(R.id.btn);        mMonth = (EditText) findViewById(R.id.et_month);        mDay = (EditText) findViewById(R.id.et_day);        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);    }    private void initListener() {        mBtn.setOnClickListener(this);        mSmAdapter = new SMAdapter(this, null);        mRecyclerView.setAdapter(mSmAdapter);        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));    }    @Override    public void getDataFail(String errorCode, String errorMsg) {        Toast.makeText(this,errorMsg+errorCode,Toast.LENGTH_LONG).show();    }    @Override    public void onError(Throwable e) {        Toast.makeText(this,e.toString(),Toast.LENGTH_LONG).show();    }    @Override    public void getDataSuccess(ArrayList<TodayBean> result) {        String s = new Gson().toJson(result);        Timber.tag(getClassName()).i(s);        Thread thread = Thread.currentThread();        Timber.tag(getClassName()).i(thread.toString());        mSmAdapter.addData(result);    }    @Override    protected void onDestroy() {        super.onDestroy();        mMainPresenter.detachView();    }    @Override    public void onClick(View v) {        if (TextUtils.isEmpty(mMonth.getText())||TextUtils.isEmpty(mDay.getText())){            Toast.makeText(NetWorkActivity.this,"不能为空",Toast.LENGTH_SHORT).show();        }else {            mMainPresenter.loadData(key,mMonth.getText()+"/"+mDay.getText());        }    }}
  • 未完待续 Hement:关于项目中的Dagger2的使用(三)

  • GitHub地址:Hement:持续升级中

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Hement:MVP架构中的网络框架(RxJava2+Retrofit2+RxAndroid)(二)

发表回复