Android mvvm使用流程
Android mvvm使用流程
一.几种常见架构模式对比
1.MVC(Model-View-Controller)
MVC模式的优点在于模块化、可扩展性和可维护性,但缺点是控制器和视图之间的耦合度较高。
2.MVP(Model-View-Presenter)模式
Presenter同时持有Model和View对象,缺点是V层与P层还是有一定的耦合度
3.MVVM(Model-View-ViewModel)
ViewModel作为中间层,将数据从Model传递给View,
ViewModel 可以将数据与 UI 组件的生命周期进行绑定。
ViewModel 类提供了一种保存和管理界面相关数据的机制,并确保这些数据在配置更改(如设备旋转)时不会丢失或重新创建。
二.使用方法
1.model 层
getTestLiveData 返回LiveData提供 数据给ViewModel,ViewModel 及view层获取到LiveData即监听数据的变化。
创建model类

public class TestLiveDataRepositoryImpl { private static final String TAG = AppConstants.APP_TAG + "TestLiveDataRepositoryImpl"; private static volatile TestLiveDataRepositoryImpl mInstance; private MutableLiveData<String> mTestLiveData1 = new MutableLiveData<>(); private MutableLiveData<String> mTestLiveData2 = new MutableLiveData<>(); //在创建一个聚合类MediatorLiveData private MediatorLiveData<String> mMediatorLiveData = new MediatorLiveData<>(); private Handler mHandler = new Handler(); public TestLiveDataRepositoryImpl() { //分别把mTestLiveData1和mTestLiveData2合并到mediatorLiveData中,只要有一个变化都会触发mMediatorLiveData变化 mMediatorLiveData.addSource(mTestLiveData1, new Observer<String>() { @Override public void onChanged(String testLiveData1Str) { Log.i(TAG, "mMediatorLiveData.onChanged mTestLiveData1 testLiveData1Str:" + testLiveData1Str); mMediatorLiveData.postValue(testLiveData1Str); } }); mMediatorLiveData.addSource(mTestLiveData2, new Observer<String>() { @Override public void onChanged(String testLiveData2Str) { Log.i(TAG, "mMediatorLiveData.onChanged mTestLiveData2 testLiveData2Str:" + testLiveData2Str); mMediatorLiveData.postValue(testLiveData2Str); } }); } public static TestLiveDataRepositoryImpl getInstance() { if (mInstance == null) { synchronized (TestLiveDataRepositoryImpl.class) { if (mInstance == null) { mInstance = new TestLiveDataRepositoryImpl(); } } } return mInstance; } public LiveData<String> getTestLiveData() { // testDelaySendLiveData1(3); // testDelaySendLiveData2(6); return mMediatorLiveData; } //模拟数据1变化 private void testDelaySendLiveData1(int second) { Log.i(TAG, "testDelaySendLiveData1 11 second:" + second); mHandler.postDelayed(() -> { Log.i(TAG, "testDelaySendLiveData1 22 call setValue second:" + second); //如果当前在子线程中必须使用postValue mTestLiveData1.setValue("delay " + second + " seconds"); }, 1000 * second); } //模拟数据2变化 private void testDelaySendLiveData2(int second) { Log.i(TAG, "testDelaySendLiveData2 11 second:" + second); mHandler.postDelayed(() -> { Log.i(TAG, "testDelaySendLiveData2 22 call setValue second:" + second); //如果当前在子线程中必须使用postValue mTestLiveData2.setValue("delay " + second + " seconds"); }, 1000 * second); } /** * 模拟数据变化调用,可以通过点击按钮调用模拟触发 */ public void delaySetValue() { Log.i(TAG, "delaySetValue "); testDelaySendLiveData1(3); testDelaySendLiveData2(6); } }
2.ViewModel 层
2.1 创建ViewModel 类MyViewModel
public class MyViewModel extends ViewModel { private static final String TAG = "MyViewModel "; public int count = 0; public MyViewModel() { count = 0; Log.i(TAG, "MyViewModel() "); } public LiveData<String> getTestLiveData() { return TestLiveDataRepositoryImpl.getInstance().getTestLiveData(); } public void delaySetValue() { Log.i(TAG, "delaySetValue "); TestLiveDataRepositoryImpl.getInstance().delaySetValue(); } }
2.2 创建 ViewModelProvider.Factory 类
public class MyViewModelFactory implements ViewModelProvider.Factory { private static final String TAG = "MyViewModelFactory "; public MyViewModelFactory() { } @NonNull @Override public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { Log.i(TAG, "create() modelClass:" + modelClass); if (modelClass == MyViewModel.class) { return (T) new MyViewModel(); } return null; } }
3.创建view类UiTestActivity
ViewModelProvider初始化时如果不传递 ViewModelProvider.Factory,则ViewModelProvider内部会使用默认的 Factory,
如果配置修改比如修改语言,activity 被销毁,再次打开activity获取的还是销毁前mMyViewModel对象。
即销毁前count被设置了3,重新打开activity打印mMyViewModel.count还是3。

1 public class UiTestActivity extends AppCompatActivity implements View.OnClickListener { 2 private static final String TAG = AppConstants.APP_TAG + "UiTestActivity "; 3 private Button mBtnOne; 4 private final Handler mHandler = new Handler(); 5 private MyViewModel mMyViewModel; 6 7 @Override 8 protected void onCreate(Bundle savedInstanceState) { 9 super.onCreate(savedInstanceState); 10 setContentView(R.layout.test_activity); 11 12 //如果不传递 ViewModelProvider.Factory,则内部会使用默认的 Factory, 13 //如果配置修改比如修改语言,activity 被销毁,再次打开activity获取的还是销毁前mMyViewModel对象。 14 //即销毁前count被设置了3,重新打开activity打印mMyViewModel.count还是3。 15 //mMyViewModel = new ViewModelProvider(this).get(MyViewModel.class); 16 17 mMyViewModel = new ViewModelProvider(this, new MyViewModelFactory()).get(MyViewModel.class); 18 19 final Observer<String> testObserver = new Observer<String>() { 20 @Override 21 public void onChanged(String testStr) { 22 //更新ui 23 Log.d(TAG, "testObserver.onChanged testStr:" + testStr); 24 } 25 }; 26 Log.d(TAG, "onCreate ** UiTestActivity is mMyViewModel.count:" + mMyViewModel.count 27 + " mMyViewModel:" + mMyViewModel); 28 mMyViewModel.getTestLiveData().observe(this, testObserver); 29 } 30 31 @Override 32 protected void onStop() { 33 super.onStop(); 34 Log.d(TAG, "onStop"); 35 } 36 @Override 37 protected void onDestroy() { 38 super.onDestroy(); 39 Log.d(TAG, "onDestroy"); 40 } 41 42 @Override 43 public void onClick(View v) { 44 switch (v.getId()) { 45 case R.id.test_btn1: 46 mMyViewModel.count++; 47 Log.d(TAG, "test_btn1.onClick() mMyViewModel.count:" + mMyViewModel.count); 48 //通过点击按钮模拟model数据变化 49 mMyViewModel.delaySetValue(); 50 break; 51 default: 52 break; 53 } 54 } 55 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术