MVVM框架

简述

MVVM(Model-View-ViewModel)架构是用于构建用户界面的架构模式,它将UI和业务逻辑分离。

  • Model:数据模型,用于存储和操作数据
  • View:用户页面,用于展示数据和接收用户输入
  • ViewModel:负责连接View与Model,负责数据的双向绑定与转换(核心思想

MVVM衍生于MVC(Model-View-Controller)架构,但是MVC存在以下问题:

  1. 所有业务逻辑都在Controller中操作,复杂且不易维护
  2. DOM(Document Object Model)操作使性能降低
  3. Model发生变化时,需要主动更新View;用户操作使Model发生变化时,需要将数据更新到Model中,不易于维护。

由此,MVVM基于上述缺点,提出ViewModel以将View与Model直接通讯。即用户操作View时,ViewModel会感知到变化,同步给Model,反之同理。

然而没有事物是完美的,需要在特定的场景下确定到底是使用MVC架构还是MVVM架构:

  • MVVM:大型或复杂的项目、项目周期长、需要跨平台、对性能要求不高等
  • MVC:小型或简单的项目、项目周期短、不需要跨平台、性能要求高等

Model(模型)

负责处理数据和业务逻辑。独立于界面,可以在多个界面中共享,用于提供数据和处理数据的方法,封装业务逻辑。例如:

java public class User {     
    private String name;     
    private int age;       
    // getter and setter methods       
    // 数据获取的方法     
    public LiveData getUser() {       
        // 从网络或数据库获取用户数据       
        return userRepository.getUser();     
    }       
    // 数据更新的方法     
    public void updateUser(User user) {       
        // 更新用户数据       
        userRepository.updateUser(user);     
    }       
    // ...   
}   

View(视图)

负责展示数据并与用户交互。可以是Activity、Fragment、View等。例如:

java public class MainActivity extends AppCompatActivity {        
    private UserViewModel userViewModel;        
    private TextView nameTextView;        
    private TextView ageTextView;            
    @Override        
    protected void onCreate(Bundle savedInstanceState) {            
        super.onCreate(savedInstanceState);            
        setContentView(R.layout.activity_main);                
        nameTextView = findViewById(R.id.nameTextView);            
        ageTextView = findViewById(R.id.ageTextView);                
        userViewModel = new ViewModelProvider(this).get(UserViewModel.class);           userViewModel.getUser().observe(this, user -> {                
            // 更新UI显示 
            nameTextView.setText(user.getName());                
            ageTextView.setText(String.valueOf(user.getAge()));            
        });        
    }            
    // 处理用户输入的方法 
    public void onUpdateUserClick(View view) {            // 从UI获取用户输入 
        String name = nameEditText.getText().toString();            
        int age = Integer.parseInt(ageEditText.getText().toString());                
        // 更新ViewModel中的数据 
        User user = new User(name, age);            
        userViewModel.updateUser(user);        
    }            
    // ...    
}   

ViewModel(视图模型)

负责连接View和Model。从Model中获取数据,转化为View可以直接使用的形式;监听Model的数据变化,通知View进行更新。Model与View通常一一对应,每个View都有一个对应的ViewModel。例如:

public class UserViewModel extends ViewModel {
    private User user;
    private UserRepository userRepository;
    public UserViewModel() {
      userRepository = new UserRepository();
      user = new User();
    }
    // 获取数据的方法
    public LiveData<User> getUser() {
      return user.getUser();
    }
    // 更新数据的方法
    public void updateUser(User user) {
      user.updateUser(user);
    }
    // ...
}

如例所示,在ViewModel中可以使用LiveData实现将View与Model绑定的功能。

LiveData

LiveData是AndroidX中JetPack提供的一种响应式编程组件,可以包含任何数据,并在数据变化的时候通知观察者,以便实现View与Model的数据相绑定。

使用方式:

在过去方法中,一直都是在Activity中手动获取ViewModel中的数据。但是ViewModel无法将数据的变化同步给Activity中。并且ViewModel的生命周期长于Activity,因此不能将Activity的实例传递给ViewModel中(否则会造成内存泄漏),由此使用LiveData。如例:

public class MainViewModel extends ViewModel {

    // MutableLiveData是一种可变的LiveData
    public MutableLiveData<Integer> count = new MutableLiveData<>();

    public MainViewModel(int count) {
        this.count.setValue(count);
    }

    public void plusOne() {
        if (count.getValue() == null) {
            return;
        }
        count.setValue(count.getValue() + 1);
    }

    public void clean() {
        count.setValue(0);
    }
}

如上所示,count为一个MutableLiveData对象(可变的LiveData),其对应有三个读写数据方法,getValue、SetValue和PostValue,其中SetValue必须在主线程中使用。

在MainActivity中,示例如下:

private static final String TAG = "MainActivity";
private TextView textView;
private Button plusOneBtn;
private Button cleanBtn;
private MainViewModel viewModel;
private SharedPreferences sp;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    sp = getPreferences(Context.MODE_PRIVATE);
    int count = sp.getInt("count_reserved", 1);
    textView = findViewById(R.id.info_text);
    plusOneBtn = findViewById(R.id.plus_one_btn);
    cleanBtn = findViewById(R.id.clean_btn);
    viewModel =new ViewModelProvider(this, new MainViewModelFactory(count)).get(MainViewModel.class);
    plusOneBtn.setOnClickListener(v -> {
        viewModel.plusOne();
    });
    cleanBtn.setOnClickListener( v -> {
        viewModel.clean();
    });

    // 用来观察数据的变化,任何LiveData都可以调用它进行
    viewModel.count.observe(this, new Observer<Integer>() {
        @Override
        public void onChanged(Integer integer) {
            textView.setText(String.valueOf(integer));
        }
    });
}

@Override
protected void onPause() {
    super.onPause();
    Log.d(TAG, "onPause: viewModel.counter = " + viewModel.count);
    SharedPreferences.Editor editor = sp.edit();
    if (viewModel.count.getValue() == null) {
        Log.d(TAG, "onPause: viewModel.count.getValue() is null");
        editor.putInt("count_reserved", 0);
        return;
    }
    editor.putInt("count_reserved", viewModel.count.getValue());
    editor.apply();
}

如上所示,其中,点击事件内的逻辑处理换到了ViewModel内,添加了count的observe()方法,这个方法就是用来观察数据的变化。任何LiveData对象都可以调用它的observe()方法来观察数据的变化。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值