ViewModel+LiveData实现MVVM

一.简介

1.MVVM模式

Model:模型层 即数据模型,用于获取和存储数据。和MVP一致。

View:视图层 即Activity/Fragment 和MVP一致。

ViewModel:视图模型,负责业务逻辑。相当于MVP中的Presenter。

2.MVP缺点

MVP模式中Presenter层需要持有IView接口来回调结果给界面(Activity/Fargment)。而Presenter层常常调用Model层进行异步网络请求。因为网络请求时间不固定。所以可能Presenter层会保存很长一段时间,如果Presenter层持有View层(Activity/Fargment)的上下文对象。这样就可能导致View层(Activity/Fragment)已近销毁。但是还有Presenter层持有它,导致该Activity/Fragment不能被及时回收。造成内存泄漏。

3.LiveData&ViewModel

LiveData是一个具有生命周期感知的观察者,ViewModel是和Activity/Fragment生命周期相同的存储和管理界面相关的数据的组件。两者结合可以实现MVVM模式。

二.代码实现

1.截图

2.代码

Model层

package com.wjn.networkdemo.mvvm.model;

import com.wjn.networkdemo.mvvm.network.RetrofitManager;
import com.wjn.networkdemo.mvvm.viewmodel.FanYiViewModel;
import com.wjn.networkdemo.retrofit.rxjavarxandroid.CustomObservable;
import com.wjn.networkdemo.retrofit.rxjavarxandroid.PostService;

import java.io.IOException;
import java.util.HashMap;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class PostModel extends CustomObservable {

    private FanYiViewModel.ServiceCallback mServiceCallback;


    /**
     * Post请求
     */

    public void postServiceData(HashMap<String, String> map, String url, FanYiViewModel.ServiceCallback callback) {
        mServiceCallback = callback;
        PostService postService = RetrofitManager.getInstance(url).createService(PostService.class);
        if (null != postService) {
            Call<ResponseBody> getCall = postService.getFanYiByPost(map);
            getCall.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    if (response.isSuccessful()) {//响应成功
                        String result = null;//响应报文
                        if (null != response.body()) {//response.body()不为空
                            try {
                                result = response.body().string();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }

                        callBack(result);
                    }
                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    callBack("");
                }
            });
        }
    }

    /**
     * 回调
     */

    private void callBack(String result) {

        if (null != mServiceCallback) {
            mServiceCallback.getResult(result);
        }
    }

}

View层

package com.wjn.networkdemo.mvvm.view;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;

import com.wjn.networkdemo.R;
import com.wjn.networkdemo.mvvm.viewmodel.FanYiViewModel;
import com.wjn.networkdemo.mvvm.viewmodel.ViewModelFactory;

import java.util.HashMap;

public class MVVMActivity extends AppCompatActivity {

    private ProgressBar mProgressBar;
    private TextView mTextView;
    private FanYiViewModel mFanYiViewModel;
    private String mBaseUrl = "http://fanyi.youdao.com/";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvvm);

        initView();
    }

    /**
     * 初始化View
     */

    private void initView() {
        mProgressBar = findViewById(R.id.activity_viewmodel_pb);
        mTextView = findViewById(R.id.activity_viewmodel_tv);
        initViewModel();
        //请求接口
        findViewById(R.id.activity_viewmodel_textview).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                HashMap<String, String> map = new HashMap<>();
                map.put("keyfrom", "imoocdict123456");
                map.put("key", "324273592");
                map.put("type", "data");
                map.put("doctype", "json");
                map.put("version", "1.1");
                map.put("q", "red");
                mFanYiViewModel.getServiceData(map, mBaseUrl);
            }
        });
    }

    /**
     * 初始化ViewModel
     */

    private void initViewModel() {
        //获取ViewModelProvider实例
        ViewModelProvider viewModelProvider = new ViewModelProvider(this, new ViewModelFactory());
        //获取ViewModel实例
        mFanYiViewModel = viewModelProvider.get(FanYiViewModel.class);
        //观察接口请求
        mFanYiViewModel.getResultLiveData().observe(this, s -> {
            mTextView.setText(s);
            Log.d("MVVMActivity", "接口请求s----:" + s);
            Log.d("MVVMActivity", "接口请求线程----:" + Thread.currentThread().getName());
        });
        //观察接口请求中...
        mFanYiViewModel.getLoadingLiveData().observe(this, aBoolean -> {
            mProgressBar.setVisibility(aBoolean ? View.VISIBLE : View.GONE);
            Log.d("MVVMActivity", "观察接口请求aBoolean----:" + aBoolean);
            Log.d("MVVMActivity", "观察接口请求线程----:" + Thread.currentThread().getName());
        });
    }


}

VM层

package com.wjn.networkdemo.mvvm.viewmodel;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import com.wjn.networkdemo.mvvm.model.PostModel;

import java.util.HashMap;

public class FanYiViewModel extends ViewModel {

    private MutableLiveData<String> mResultLiveData;//报文
    private MutableLiveData<Boolean> mLoadingLiveData;//请求中

    /**
     * 构造方法
     */

    public FanYiViewModel() {
        mResultLiveData = new MutableLiveData<>();
        mLoadingLiveData = new MutableLiveData<>();
    }

    /**
     * 获取接口数据
     */

    public void getServiceData(HashMap<String, String> map, String url) {
        mLoadingLiveData.setValue(true);//进度条
        PostModel postModel = new PostModel();
        postModel.postServiceData(map, url, json -> {
            mLoadingLiveData.setValue(false);//进度条
            mResultLiveData.setValue(json);//接口报文
        });
    }

    /**
     * 获取报文的LiveData
     */

    public MutableLiveData<String> getResultLiveData() {
        return mResultLiveData;
    }

    /**
     * 获取请求中的LiveData
     */

    public MutableLiveData<Boolean> getLoadingLiveData() {
        return mLoadingLiveData;
    }


    public interface ServiceCallback {
        void getResult(String json);
    }

}

3.结果

D/MVVMActivity: 观察接口请求aBoolean----:true


D/MVVMActivity: 观察接口请求线程----:main


D/MVVMActivity: 观察接口请求aBoolean----:false


D/MVVMActivity: 观察接口请求线程----:main


D/MVVMActivity: 接口请求s----:{"translation":["红色的"],"basic":{"us-phonetic":"red","phonetic":"red","uk-phonetic":"red","explains":["adj. 红的,红色的;(毛发)红褐色的;(脸)涨红的;(眼睛)红肿的;革命的,激进的;(人)红种的;(纸牌中)红桃的,红方块的;(葡萄酒)红的;(表示停止)红(灯),红(旗);被禁止的,危险的;(滑雪道上用红色标志指示)第二高难度的;(物理)表示夸克三种颜色之一的红色;赤色的(尤指冷战期间用于指前苏联);沾有鲜血的;(古或诗\/文)流血的;(科萨人)来自传统部落文化的","n. 红色,红颜料;红衣;红葡萄酒;红色物(或人);赤字,亏空;激进分子","n. (Red) 雷德(人名)"]},"query":"red","errorCode":0,"web":[{"value":["红","红色","赤焰战场"],"key":"RED"},{"value":["红河","红河谷","天是红河岸","红江"],"key":"Red River"},{"value":["红葡萄酒","红酒","干红葡萄酒","酒红色"],"key":"Red Wine"}]}


D/MVVMActivity: 接口请求线程----:main

三.总结

ViewModel+LiveData实现MVVM。可以去除Presener 对View、context的引用。

VM层获取到数据后通过LiveData发送给View层。

View层通过观察LiveData观察方法监听结果。

而由于ViewModel的生命周期性,可以在屏幕旋转,Fragment共享数据等场景获取到ViewModel。

也可以完美匹配网络请求有可能时间比较长,需要原来的MVP中的Presenter层需要长期存在的问题。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值