Android MVVM架构浅析封装

MVVM 架构相对于MVP来说其实思想上是一致的,只是MVP中的P层在MVVM中换成了ViewModel,所以MVVM的模块结构如下图(截图出自https://developer.android.google.cn/jetpack/guide)
在这里插入图片描述
这里面的LiveData 和Room 其实都是Google一直在推的JetPack 中的组件,更多的组件大家可以去https://developer.android.google.cn/jetpack 中查看

回到MVVM 在MVVM中使用ViewModel 和LiveData 要引入依赖,因为现在我们的项目一般都迁移到了AndroidX,所以就不需要单独进行引入了,而且AndroidX还引入了LifeCycle,可以很方便进行生命周期的管理,防止内存泄漏(如果要单独引入,可以这样)

dependencies {
    def lifecycle_version = "2.2.0"

    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    ...
}

依赖好了,我们最好再启用DataBinding ,这里我只使用DataBinding 的findViewById 功能,这也是官方一直推荐的,而且Butterknife现在已经停更了,官方说明中是这样说的This tool is now deprecated. Please switch to view binding. 所以我们没有理由不使用DataBinding
首先在build.gradle中的android{}启用

dataBinding {
        enabled = true
    }

然后将我们的布局最外层套一层layout,像这样

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <com.scwang.smart.refresh.layout.SmartRefreshLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/home_smartRl"
        tools:context=".ui.fragment.HomeFragment">
        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/home_article_rv" />
    </com.scwang.smart.refresh.layout.SmartRefreshLayout>
</layout>

接下来我们开始封装MVVM,它其实是MVP的封装思想是一样的,所以这里我们如果熟知MVP,是非常好理解的,先贴下代码

public abstract  class BaseActivity<VM extends BaseViewModel,V extends ViewDataBinding> extends AppCompatActivity implements IBaseView {
    protected VM viewModel;
    protected V viewBinding;
    protected LoadingUtils loadingUtil;
    protected ToastUtils customToastUtils;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewBinding = DataBindingUtil.setContentView(this,setLayoutRes());

        initParam();
        //初始化ViewModel
        initViewModel();
        initView();
        initToolBar();

        initData();
        initViewObservable();

    }


    protected abstract void initView();

    protected abstract int setLayoutRes();


    private void initViewModel() {
        viewBinding.setLifecycleOwner(this);

        //获取ViewModel实例
        ViewModelProvider viewModelProvider = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication()));
        //获取返回直接继承的父类(包含泛型参数)
        ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();
        if (parameterizedType != null){
            //
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();

            Class<VM> tClass = (Class<VM>) actualTypeArguments[0];

            viewModel = viewModelProvider.get(tClass);

            getLifecycle().addObserver(viewModel);

        }


    }
    private void initToolBar() {

    }

    @Override
    public void initParam() {
        loadingUtil = new LoadingUtils(this);
        customToastUtils = ToastUtils.getDefaultMaker().setGravity(Gravity.CENTER,0,0)
                .setDurationIsLong(true).setMode(ToastUtils.MODE.DARK);
    }

    @Override
    public void initData() {

    }

    @Override
    public void initViewObservable() {

    }

    @Override
    public void onContentReload() {

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

    }


}

在基类中,通过泛型,来将一些重复的代码进行封装,对于BaseModel,StateLiveData大家可以不用关心,这里主要针对一些Rxjava 发送的一些请求,在具体的ViewModel 中添加进来,并且在ViewModel 生命周期结束的时候进行清空,可以避免内存泄漏

public class BaseViewModel extends AndroidViewModel implements IBaseViewModel, Consumer<Disposable> {
    protected StateLiveData<Object> stateLiveData;

    private CompositeDisposable compositeDisposable;
    public BaseViewModel(@NonNull Application application) {
        super(application);
        compositeDisposable = new CompositeDisposable();
        stateLiveData = new StateLiveData<Object>();

    }



    public StateLiveData<Object> getStateLiveData() {
        return stateLiveData;
    }

    @Override
    public void onAny() {

    }

    @Override
    public void onCreate() {

    }

    @Override
    public void onDestroy() {

    }

    @Override
    public void onStart() {

    }

    @Override
    public void onStop() {

    }

    @Override
    public void onResume() {

    }

    @Override
    public void onPause() {

    }

    @Override
    public void accept(Disposable disposable) throws Exception {
        compositeDisposable.add(disposable);
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        if (compositeDisposable != null && compositeDisposable.size() > 0){
            compositeDisposable.clear();
            compositeDisposable = null;
        }
    }
}

具体的ViewModel 中,就是进行网络请求和简单的数据处理,将结果通过LiveData型的数据传递给Activity或Fragment,

class HomeViewModel(application: Application) : BaseViewModel(application) {
    val liveData = MutableLiveData<HomeArticleListResponse>()
    val errorLiveData = MutableLiveData<String>()



    fun getHomeArticle(pageNum: Int) {
        stateLiveData.postLoading()
        AppRequest.get().getHomeArticalList(pageNum)
            .compose(RxUtils.observableToMain())
            //绑定当前VIewModel 的生命周期  ViewModel
            .doOnSubscribe(this)
            .subscribe(object : BaseObserver<HomeArticleListResponse>() {
                override fun onSuccess(baseResponse: BaseResponse<HomeArticleListResponse>) {
                    if (baseResponse.data == null) {
                        errorLiveData.postValue(ViewModelConst.SUCCESSNODATA)
                    } else {
                        liveData.postValue(baseResponse.data)
                    }
                    stateLiveData.postSuccess()
                }

                override fun onCodeError(baseResponse: BaseResponse<*>) {
                    errorLiveData.postValue(baseResponse.errorMsg)
                    stateLiveData.postError()
                }

                override fun onFailure(exception: ResponseCustomException) {
                    errorLiveData.postValue(exception.message)
                    stateLiveData.postError()
                }
            })

    }
}

在Activity中获取结果也很方便,从viewModel中拿到对应的LiveData,作数据的监听就可以了,LiveData 获取到数据会自动进行数据的填充,

 viewModel.liveData.observe(this,
            androidx.lifecycle.Observer<HomeArticleListResponse> {
                val datas = it.datas
                val curPage = it.curPage
                if (pageNum == 0) {
                    articleListAdapter!!.setNewData(datas)
                } else {
                    if (curPage >= it.pageCount) {
                        //没有页了
                        viewBinding.homeSmartRl.finishLoadMoreWithNoMoreData()
                    } else {
                        if (datas != null && datas.isNotEmpty()) {

                            articleListAdapter!!.addData(datas)
                        } else {
                            viewBinding.homeSmartRl.finishLoadMore(false)
                        }
                    }
                }
            })

以上就是MVVM的一些简单封装使用,大家可以结合项目实际再做加工,毕竟封装的习惯每个人都不一样,只要了解了思想,都只是一种形式。

  • 0
    点赞
  • 1
    收藏 更改收藏夹
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初心不负

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值