Android MVVM学习笔记

Android MVVM

1.MVVM概述

Model-View-ViewModel模式。将View的状态和行为完全抽象化,把逻辑与界面的控制交给ViewModel进行处理。

在这里插入图片描述

1.1 三部分组成:
  • View
    • 进行视图控件的初始化设置,不具有任何的数据逻辑处理。
  • Model
    • 定义实体类以及获取业务数据模型
  • ViewModel
    • 连接View和Model的桥梁,ViewModel与Model进行交互,处理完业务逻辑后,通过DataBinding将数据变化反应到View上。
1.2 优点:
  1. 低耦合度,当UI发生变化时,ViewModel不需要太多的改动。
  2. 数据驱动,数据的变化会引发UI的变化,UI的改变也会使得数据Model进行对应的更新。
  3. 异步线程更新Model,数据绑定框架会将异步线程中的数据变化通知到UI线程中交给View去更新。
  4. 方便协作,View层和数据处理完全解耦合,可以并发进行。
  5. 易于单元测试,ViewModel只负责处理数据,View层只负责输入指定格式的数据即可进行测试。
  6. 数据复用,ViewModel层对数据的获取和处理逻辑,其实是Repository模式时,获取的数据是可复用的。

2.DataBinding

MVVM是一种思想,一种架构模式。
MVVM 相对于 MVP,其实就是将 Presenter 层替换成了 ViewModel 层。

DataBinding是Google推出的实现MVVM的工具。 是实现视图和数据双向绑定的工具,用声明式布局文件来减少粘结业务逻辑和布局文件的胶水代码。

DataBinding 能够省去我们一直以来的 findViewById() 步骤,大量减少 Activity 内的代码,数据能够单向或双向绑定到 layout 文件中,有助于防止内存泄漏,而且能自动进行空检测以避免空指针异常

2.1 配置方式
android {
   dataBinding {
     enabled = true
   }
}
2.2 使用方式

1.布局文件的根标签是layout标签,内部包含一个data元素和一个view元素。view为没有使用DataBinding时候的布局文件。

<layout xmlns=android="http://schemas.android.com/apk/res/android">
	<data>
		<variable
			name="user"  
			type="com.example.mvvmdemo.UserBean"/>
	</data>
	
	<LinearLayout 
		android:orientation="vertical"
		android:layout_width="match_parent"
		android:layout_height="match_parent">
		<TextView 
			android:layout_width="match_parent"
			android:layout_height="wrap_content"
			android:text="@{user.name}"/>
			
		<TextView
			android:layout_width="match_parent"
			android:layout_height="wrap_content"
			android:text="@{user.sex}"/>
	</LinearLayout>
</layout>

2.data中的user就是定义的user实体类,当向DataBinding中设置好user类后,textView会自动设置text的取值。

public class UserBean{
	public ObservableField<String> name = new ObservableField<>();//当实体类中的值发生变化时,会自动通知View刷新
	public ObservableField<String> sex = new ObservableField<>();
  
  public UserBean(){
    name.set("王小明");
    sex.set("男");
  }
}

3.在Activity中绑定layout

ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

UserBean user = new UserBean();
activityMainBinding.setUser(user);
2.3 核心优势

解决了将数据分解映射到各个view的问题。

  1. 在编译阶段,会生成一个ViewDataBinding对象,该对象持有Activity要展示的数据和布局中的view的引用。
  2. 数据分解到各个view,在UI线程上更新数据、监听数据变化,实时更新,实现了数据和布局的紧紧绑定在一起
2.4 实现数据变化自动驱动UI刷新的方式_单向绑定

有三种

  • BaseObservable
  • ObservableField
  • ObservableCollection
2.4.1 BaseObservable

提供了notifyChange()和notifyPropertyChanged(),前者刷新所有值,后者只更新对应的BR的flag,该BR的生成通过@Bindable生成。

public class Goods extends BaseObservable{
	@Bindable
	public String name;//如果是public修饰符,则在成员变量上添加@Bindable注解
  
	private String details;//private变量,则在Get方法是@Bindable注解
	
	@Bindable
	public String getDetails(){
	   return details;
	}
	
	public void setName(String name){
		this.name = name;
		notifyPropertyChanged(com.demo.databindingsamples.BR.name);//仅更新name取值
	}
	
	public void setDetails(String details){
		this.details = details;
		notifyChange();//更新所有值
	}
}

实现BaseObservable接口的类,允许注册一个监听器。观察对象属性更改时会通知这个监听器。onPropertyChanged()

2.4.2 ObservableField
public class ObservableGoods{
	private ObservableField<String> name;
}

对ObservableGoods属性值的改变,都会立刻触发UI刷新。

2.4.3 ObservableCollection

DataBinding提供了包装类用于替代原生的List和Map,分别是ObservableList和ObservableMap

使用方式

<data>
	<variable name="list"
	type="ObservableList&lt;String&gt;"/>
	<variable name="map"
	type="ObservableMap&lt;String,Strinng&gt;"/>
	
	<variable name="index" type="int"/>
	<variable name="key" type="String"/>
</data>


<TextView 
	android:text="@{list[index]}"
/>

<TextView 
	android:text="@{map[key]}"
private ObservaleMap<String, String> map;

@Override
protected void onCreate(Bundle savedInstanceState){
	super.onCreate(savedInstanceState);
	ActivityMain5Binding binding = DataBindingUtil.setContentView(this, R.layout.activity_new);
	
	map = new ObservableMap<>();
	map.put("name","zhangsan");
	map.put("age","23");
	binding.setMap(map);
	
	ObservableList<String> list = new ObservableArrayList<>();
	list.add("ye");
	list.add("ee");
	binding.setList(list);
	binding.setIndex(0);
	binding.setKey("name");
}
2.5 双向绑定

当数据改变时,视图会刷新。视图改变时,也会改变数据。

<TextView android:text="@={goods.name}"
2.6 事件绑定

可以用于以下回调事件

  • android:onClick
  • android:onLongClick
  • android:afterTextChanged
  • android:onTextChanged
  • ……
<TextView 
	android:onClick="@{)->userPresenter.onUserNameClick(userInfo)}"/>
	
<EditText
	android:onClick="@{userPresenter.afterTextChanegd}"/>

3.MVVM实例

3.1 项目目录
demo
	model
		Feed
		News
	view
		MainActivity
	viewmodel
		MainViewModel
3.2 View的实现
public class MainActivity extends AppCompatActivity {
	public ActivityMainBinding mActivityMainBinding;
	private MainViewModel mViewModel;
	
	public NewsAdapter mNewsAdapter;
	public List<News> mNewsList = new ArrayList<>();
	
	@Override
	protected void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
    //设置dataBinding、viewModel
    mActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    mViewModel = new MainViewModel();
    mActivityMainBinding.setViewModel(mViewModel);
    
    //初始化RecycleView
    LinearLayoutManager layoutManager = new LinearLayoutManager();
    mActivityMainBinding.recycleView.setLayoutManager(layoutManager);
    mNewsAdapter = new NewsAdapter(this, mNewsList);
    mActivityMainBinding.recycleView.setAdapter(mNewsAdapter);
    //加载数据
    mViewModel.loadNews();
	}
}

3.3 ViewModel

public class MainViewModel {
	private MainActivity mActivity;
  
  public MainViewModel(MainActivity activity){
    mActivity = activity;
  }
  
  public void loadNews(){
    String feedUrl = "";
    Feed feed = new Feed();
    feed.loadData(feedUrl, new LoadListener<News>(){
      @Override
      public void loadSucess(List<News> list){
        //数据加载成功
        mActivity.mNewsList.addAll(list);//数据更新
        mActivity.mNewAdapter.notifyDataSetChanged();
      }
      
      @Override 
      public void loadFailure(String message){
        //数据加载失败
      }
    });
    
  }
}
public interface INews{
	@GET(".")
	Call<Feed> getFeed();
}
3.4 Model
public class Feed {
  private List<News> data;
  
  public void loadData()	{
    ...
      
      INews inews = retrofit.create(INews.class);//???
      Call<Feed> feed = iNews.getFeed();
    	feed.enqueue(new Calback<Feed>() {
        @Override
        public void onResponse(Call<Feed> call, Response<Feed> response){
          //数据获取成功
          List<News> newsList = new ArrayList<>();
          ...
          loadListener.loadSuccess(newsList);
        }
      });
      data
  }
}

4. 参考文档

Android MVVM入门教程

DataBinding

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值