带你封装自己的MVP+Retrofit+RxJava2框架(一)

在搞清楚这个问题之前,我们回顾一下基本概念

RxJava: ReactiveXJVM上的一个实现,ReactiveX使用Observable序列组合异步和基于事件的程序;掌握了它,你可以优美地处理异步任务和事件的回调

Retrofit:一个 RESTfulHTTP网络请求框架的封装,网络请求的工作本质上是OkHttp 完成,而 Retrofit仅负责 网络请求接口的封装:掌握了它,你能优美地进行网络请求。

MVP:一种解耦模型和视图的模式,是现在很多公司的主流模式。

由此可见,在平时的开发中熟练运用这种模式,不仅可以满足生活中大部分应用程序的场景,还可以为将来的工作积攒宝贵的实战经验。

二.核心用法

本项目基于Android X 进行构建,完整代码可在我的Github上下载:带你封装自己的MVP+Retrofit+RxJava2框架

首先,看一下我们项目的基本结构,下面笔者将为大家详细介绍每个类的相关信息

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

项目基本结构

2.1 基类Base

Base基类是封装了一些基类,方便后面新建新的Activity或者Fragment,减少耦合

2.1.1 BaseActivity

这个类是Activity的基类,注意与下面的BaseMvpActivity区分开

`/**

  • Description : BaseActivity 基类活动
  • @author XuCanyou666
  • @date 2020/2/2
    /
    public abstract class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(getLayoutId());
    initPresenter();
    initViews();
    ButterKnife.bind(this);
    }
    /
    *
  • 抽象方法:实例化Presenter
    /
    protected abstract void initPresenter();
    /
    *
  • 抽象方法:初始化控件,一般在BaseActivity中通过ButterKnife来绑定,所以该方法内部一般我们初始化界面相关的操作
  • @return 控件
    /
    protected abstract void initViews();
    /
    *
  • 抽象方法:得到布局id
  • @return 布局id
    /
    protected abstract int getLayoutId();
    /
    *
  • 启动Fragment
  • @param id id
  • @param fragment 碎片
    */
    protected void startFragment(int id, Fragment fragment) {
    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
    fragmentTransaction.add(id, fragment);
    fragmentTransaction.commit();
    }
    }`
2.1.2 BaseView

一个接口,说明了每一个View基本需要的一些操作

`package com.users.xucanyou666.rxjava2_retrofit_mvp.base;
/**

  • created by xucanyou666
  • on 2020/1/31 18:26
  • email:913710642@qq.com
    /
    public interface BaseView {
    /
    *
  • 显示进度框
    /
    void showProgressDialog();
    /
    *
  • 关闭进度框
    /
    void hideProgressDialog();
    /
    *
  • 出错信息的回调
  • @param result 错误信息
    */
    void onError(String result);
    }`
2.1.3 BaseMvpActivity
  • MVP活动的基类

  • 继承自BaseActivity,它是MVP活动的基类,封装好了Presenter的相关操作

`package com.users.xucanyou666.rxjava2_retrofit_mvp.base;
/**

  • created by xucanyou666 MVP活动的基类,封装好了presenter的相关操作
  • on 2019/12/24 20:53
  • email:913710642@qq.com
    /
    public abstract class BaseMvpActivity<V extends BaseView, P extends BasePresenter> extends BaseActivity {
    private P presenter;
    /
    *
  • 初始化presenter
    /
    @Override
    protected void initPresenter() {
    presenter = createPresenter();
    if (presenter != null) {
    presenter.attachView((V) this);
    }
    }
    /
    *
  • 创建presenter
  • @return Presenter
    /
    protected abstract P createPresenter();
    /
    *
  • 得到presenter
  • @return presenter
    /
    protected P getPresenter() {
    return presenter;
    }
    /
    *
  • 销毁
    */
    @Override
    protected void onDestroy() {
    super.onDestroy();
    if (presenter != null) {
    presenter.detachView();
    }
    }
    }`
2.1.4 BaseFragment
  • Fragment的基类

  • 需要注意的是,这里用了ButterKnife框架,对碎片进行了绑定和解绑操作

`/**

  • Fragment的基类,封装了一些Fragment的相关操作
  • created by xucanyou666
  • on 2020/1/31 16:21
  • email:913710642@qq.com
    /
    public abstract class BaseFragment extends Fragment implements BaseView {
    protected T mPresenter;
    protected Context mContext;
    protected Bundle mBundle;
    protected Unbinder unbinder;
    protected View view;
    /
    *
  • 恢复数据
  • @param outState bundle
    /
    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
    if (mBundle != null) {
    outState.putBundle(“bundle”, mBundle);
    }
    }
    /
    *
  • 绑定activity
  • @param context context
    /
    @Override
    public void onAttach(@NonNull Context context) {
    super.onAttach(context);
    mContext = context;
    }
    /
    *
  • 运行在onAttach之后,可以接收别人传递过来的参数,实例化对象
  • 可以解决返回的时候页面空白的bug
  • @param savedInstanceState
    /
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) {
    mBundle = savedInstanceState.getBundle(“bundle”);
    } else {
    mBundle = getArguments() == null ? new Bundle() : getArguments();
    }
    //初始化presenter
    mPresenter = initPresenter();
    }
    protected T getPresenter() {
    return mPresenter;
    }
    /
    *
  • 运行在onCreate之后,生成View视图
  • @param inflater
  • @param container
  • @param savedInstanceState
  • @return
    /
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    view = initView(inflater, container, savedInstanceState);
    unbinder = ButterKnife.bind(this, view);
    return view;
    }
    /
    *
  • 运行在onCreateView之后
  • 加载数据
  • @param savedInstanceState
    /
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mPresenter.attachView(this);
    }
    /
    *
  • 跳转Fragment
  • @param toFragment 跳转去的fragment
    /
    public void startFragment(Fragment toFragment) {
    Log.d(TAG, “haha”);
    startFragment(toFragment, null);
    }
    /
    *
  • 跳转Fragment
  • @param toFragment 跳转到的fragment
  • @param tag fragment的标签
    /
    public void startFragment(Fragment toFragment, String tag) {
    FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
    fragmentTransaction.hide(this).add(android.R.id.content, toFragment, tag);
    fragmentTransaction.addToBackStack(tag);
    fragmentTransaction.commitAllowingStateLoss();
    }
    @Override
    public void onDestroyView() {
    super.onDestroyView();
    unbinder.unbind();
    }
    /
    *
  • fragment进行回退
  • 类似于activity的OnBackPress
    /
    public void onBack() {
    getFragmentManager().popBackStack();
    }
    @Override
    public void onDetach() {
    mPresenter.detachView();
    super.onDetach();
    }
    /
    *
  • 初始化Fragment应有的视图
  • @return view
    /
    public abstract View initView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState);
    /
    *
  • 创建presenter
  • @return 必须是BasePresenter的子类
    /
    public abstract T initPresenter();
    /
    *
  • 得到context
  • @return context
    /
    @Override
    public Context getContext() {
    return mContext;
    }
    /
    *
  • 得到bundle
  • @return bundle
    /
    public Bundle getBundle() {
    return mBundle;
    }
    /
    *
  • 得到fragment
  • @return fragment
    */
    public Fragment getFragment() {
    return this;
    }
    }`
2.1.5 BasePresenter

`/**

  • created by xucanyou666
  • on 2020/1/16 17:12
  • email:913710642@qq.com
    /
    public abstract class BasePresenter {
    //将所有正在处理的Subscription都添加到CompositeSubscription中。统一退出的时候注销观察
    private CompositeDisposable mCompositeDisposable;
    private V baseView;
    /
    *
  • 和View绑定
  • @param baseView
    /
    public void attachView(V baseView) {
    this.baseView = baseView;
    }
    /
    *
  • 解绑View,该方法在BaseMvpActivity类中被调用
    /
    public void detachView() {
    baseView = null;
    // 在界面退出等需要解绑观察者的情况下调用此方法统一解绑,防止Rx造成的内存泄漏
    if (mCompositeDisposable != null) {
    mCompositeDisposable.dispose();
    }
    }
    /
    *
  • 获取View
  • @return view
    /
    public V getMvpView() {
    return baseView;
    }
    /
    *
  • 将Disposable添加,在每次网络访问之前初始化时进行添加操作
  • @param subscription subscription
    */
    public void addDisposable(Disposable subscription) {
    //csb 如果解绑了的话添加 sb 需要新的实例否则绑定时无效的
    if (mCompositeDisposable == null || mCompositeDisposable.isDisposed()) {
    mCompositeDisposable = new CompositeDisposable();
    }
    mCompositeDisposable.add(subscription);
    }
    }`
2.1.6 MyApplication
  • 封装了一个可以全局获取Context的方法,参考写法自:《第一行代码–第二版》
  • 注意:记得在AndroidManifest中注册Application

`package com.users.xucanyou666.rxjava2_retrofit_mvp.base;
import android.app.Application;
import android.content.Context;
/**

  • 基类
  • created by xucanyou666
  • on 2019/11/2 14:46
  • email:913710642@qq.com
  • @author xucanyou666
    */
    public class MyApplication extends Application {
    private static Context context;
    @Override
    public void onCreate() {
    super.onCreate();
    context = getApplicationContext();
    }
    public static Context getContext() {
    return context;
    }
    }`

2.2 工具类 Util

2.2.1 RetrofitManager

Retrofit单例工具类

`/**

  • Retrofit单例工具类
  • created by xucanyou666
  • on 2020/1/16 16:38
  • email:913710642@qq.com
    /
    public class RetrofitManager {
    private Retrofit mRetrofit;
    //构造器私有,这个工具类只有一个实例
    private RetrofitManager() {
    OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
    httpClientBuilder.connectTimeout(15, TimeUnit.SECONDS);
    mRetrofit = new Retrofit.Builder()
    .client(httpClientBuilder.build())
    .addConverterFactory(GsonConverterFactory.create())
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .baseUrl(BASE_URL)
    .build();
    }
    /
    *
  • 静态内部类单例模式
  • @return
    /
    public static RetrofitManager getInstance() {
    return Inner.retrofitManager;
    }
    private static class Inner {
    private static final RetrofitManager retrofitManager = new RetrofitManager();
    }
    /
    *
  • 利用泛型传入接口class返回接口实例
  • @param ser 类
  • @param 类的类型
  • @return Observable
    */
    public T createRs(Class ser) {
    return mRetrofit.create(ser);
    }
    }`
2.2.2 RxJavaUtil

RxJava的工具类,执行线程调度工作

`/**

  • created by xucanyou666
  • on 2019/11/17 19:20
  • email:913710642@qq.com
  • @author xucanyou666
    /
    public class RxJavaUtil {
    /
    *
  • 线程调度工作
  • @param observable 被观察者
  • @param 类型
    */
    public static Observable toSubscribe(Observable observable) {
    return observable.subscribeOn(Schedulers.io())
    .unsubscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread());
    }
    }`

2.3 常量类 Contant

常量池,特别感谢api open网提供的免费API

`/**

  • created by xucanyou666
  • on 2019/11/17 19:01
  • email:913710642@qq.com
    */
    public class StaticQuality {
    public static final String BASE_URL=“https://api.gushi.ci/”;
    }`

2.4 接口管理器 Contract

这里集中了一些Model层,Presenter层,View层的与诗歌相关的接口

`/**

  • 诗歌的接口管理器
  • created by xucanyou666
  • on 2020/2/2 15:33
  • email:913710642@qq.com
    /
    public interface IPoetryContract {
    interface IPoetryModel {
    /
    *
  • 得到诗歌
  • @return 诗歌
    /
    Observable getPoetry();
    }
    interface IPoetryPresenter {
    void getPoetry();
    }
    interface IPoetryView extends BaseView {
    /
    *
  • @param author 作者
    */
    void searchSuccess(String author);
    }
    }`

2.5 实体类 Entity

`/**

  • 诗歌的实体类
  • created by xucanyou666
  • on 2020/1/23 21:23
  • email:913710642@qq.com
  • API返回示例:
  • {
  • “content”: “胡瓶落膊紫薄汗,碎叶城西秋月团。”,
  • “origin”: “从军行七首”,
  • “author”: “王昌龄”,
  • “category”: “古诗文-天气-月亮”
  • }
    */
    public class PoetryEntity {
    private String content; //诗歌内容
    private String origin; //来源
    private String author; //作者
    private String category; //分类
    public String getContent() {
    return content;
    }
    public void setContent(String content) {
    this.content = content;
    }
    public String getOrigin() {
    return origin;
    }
    public void setOrigin(String origin) {
    this.origin = origin;
    }
    public String getAuthor() {
    return author;
    }
    public void setAuthor(String author) {
    this.author = author;
    }
    public String getCategory() {
    return category;
    }
    public void setCategory(String category) {
    this.category = category;
    }
    }`

2.6 Retrofit接口 iApiService

`/**

  • retrofit接口
  • created by xucanyou666
  • on 2020/1/23 21:25
  • email:913710642@qq.com
    /
    public interface GetPoetryEntity {
    /
    *
  • 获取古诗词
  • @return 古诗词
    */
    @GET(“all.json”)
    Observable getPoetry();
    }`

2.7 视图层 View

这里为了减少代码量,方便读者们掌握核心操作,故View层都是用的同一个PresenterModel,仅作学习参考

2.7.1 MainActivity

需要注意的是,这里BaseMvpActivity<activity, presenter>Activity填入的是当前的ActivityPresenter填入的是对应的Presenter

`/**

  • Description : MainActivity
    自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

上面分享的百度、腾讯、网易、字节跳动、阿里等公司2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

【Android高级架构视频学习资源】

**Android部分精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

上面分享的百度、腾讯、网易、字节跳动、阿里等公司2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

[外链图片转存中…(img-9TYkLSzU-1712406228077)]

【Android高级架构视频学习资源】

**Android部分精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
对于Android项目中的网络请求,RxJavaRetrofitMVP是常用的框架组合。下面是一个简单的网络框架封装示例: 首先,在项目中引入RxJavaRetrofit的依赖。 ``` implementation 'io.reactivex.rxjava2:rxjava:2.2.19' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0' ``` 然后,创建一个Retrofit的单例类,用于进行网络请求的初始化和配置。 ```java public class RetrofitClient { private static Retrofit retrofit; private static final String BASE_URL = "https://api.example.com/"; public static Retrofit getClient() { if (retrofit == null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); } return retrofit; } } ``` 接下来,创建一个ApiService接口,定义网络请求的方法。 ```java public interface ApiService { @GET("users") Observable<List<User>> getUsers(); } ``` 然后,创建一个DataManager类,用于管理网络请求。 ```java public class DataManager { private ApiService apiService; public DataManager() { apiService = RetrofitClient.getClient().create(ApiService.class); } public Observable<List<User>> getUsers() { return apiService.getUsers(); } } ``` 最后,在MVP的Presenter中调用DataManager类进行网络请求。 ```java public class UserPresenter { private UserView userView; private DataManager dataManager; public UserPresenter(UserView userView) { this.userView = userView; dataManager = new DataManager(); } public void getUsers() { dataManager.getUsers() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<List<User>>() { @Override public void onSubscribe(Disposable d) { // 在请求开始时的操作 } @Override public void onNext(List<User> users) { // 请求成功返回数据时的操作 userView.showUsers(users); } @Override public void onError(Throwable e) { // 请求失败时的操作 userView.showError(e.getMessage()); } @Override public void onComplete() { // 请求完成时的操作 } }); } } ``` 这样,就完成了一个简单的Android RxJava + Retrofit + MVP网络框架封装。你可以根据自己的需要,进行进一步的封装和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值