MVVM框架主要的特点就是低耦合,对于不同的view,model可以复用。
目前android 的MVVM框架主要是使用 databinding实现双向数据绑定,来降低耦合度。
首先是用databinding来实现mvvm框架,下面是一个我自己总结的使用databinding来实现mvvm框架的简单示例。
之后是我使用Viewbinding实现的框架,可以说用起来更加的灵活便捷。
model类,这个类主要是一些与视图相关的业务逻辑的处理,对于一些需要复用并且实现不同逻辑的model类,可以使用回调的方式来执行不同的业务逻辑。例如下面代码中的titlemodel, 需要更新数据的时候,需要调用notifyPropertyChanged(BR.title)来刷新页面数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14public abstract class BaseModel<T> extends BaseObservable { protected ProgressDialog mProgressDialog; protected T binding; protected Activity context; public BaseModel(T binding, Activity context){ this.binding=binding; this.context=context; } public BaseModel(T binding){ this.binding=binding; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46public class TitleModel extends BaseModel<LayoutTextTitleBinding> { private String title; private OnClick onClick; private int actionIcon; public void setOnClick(OnClick onClick) { this.onClick = onClick; } public TitleModel(LayoutTextTitleBinding binding) { super(binding); } @Bindable public int getActionIcon() { return actionIcon; } public void setActionIcon(int actionIcon) { this.actionIcon = actionIcon; // notifyPropertyChanged(BR.titleModel); } public void onBack(View view) { onClick.onBack(view); } public void onAction(View view) { onClick.onAction(view); } @Bindable public String getTitle() { return title; } public void setTitle(String title) { this.title = title; // notifyPropertyChanged(BR.titleModel); } public static interface OnClick{ void onBack(View view); void onAction(View view); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61public class TestActivityModel extends BaseModel<LayoutTestActivityBinding> { private TestAdapter testAdapter; public TitleModel titleModel; public TestActivityModel(LayoutTestActivityBinding binding) { super(binding); } public TestActivityModel(LayoutTestActivityBinding binding, final Activity activity) { super(binding, activity); titleModel=new TitleModel(binding.title); titleModel.setActionIcon(R.mipmap.ic_launcher); titleModel.setOnClick(new TitleModel.OnClick() { @Override public void onBack(View view) { Toast.makeText(activity,"按下返回键",Toast.LENGTH_SHORT).show(); } @Override public void onAction(View view) { Toast.makeText(activity,"按下动作键",Toast.LENGTH_SHORT).show(); } }); binding.title.setTitleModel(titleModel); LinearLayoutManager layoutManager =new LinearLayoutManager(activity,LinearLayoutManager.VERTICAL,false); testAdapter = new TestAdapter(activity); testAdapter.setOnClick(new TestAdapter.OnClick() { @Override public void onClick(View view, TestEntity info, int position) { } @Override public void onLongClick(View view, TestEntity info, int pos) { } }); binding.list.setLayoutManager(layoutManager); binding.list.setAdapter(testAdapter); getData(); } int count; private void getData(){ ArrayList<TestEntity> data=new ArrayList<>(); for(int i=count;i<count+10;i++){ TestEntity entity=new TestEntity(); entity.setContent("context"+i); entity.setName("item"+i); data.add(entity); } count+=10; testAdapter.setmDatas(data); testAdapter.notifyDataSetChanged(); } public void onRefresh(View view){ getData(); } }
关于Viewbinding。viewbinding会比databinding更加简单。并且不需要在xml文件中进行修改。下面是一个关于viewbinding的示例。同样是mvvm框架,使用viewbinding改进以后可以更加灵活的使用。比如两个完全不同的布局,也可以使用同一个model。不仅仅是相同视图情况下代码重用。下面是两种model的写法,一种指定了viewbinding的具体类型,一种没有。对于需要复用的model类,如果布局不复用也可以不指定具体的model类型,可以通过代码回调或者类型判断来执行不同的业务逻辑处理。需要复用的model不和activity关联,所以提供下面SimpleBaseModel的形式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30public abstract class BaseModel<T extends ViewBinding> implements View.OnClickListener { protected T binding; protected Activity context; public BaseModel(T binding,Activity context){ this.binding=binding; this.context=context; } public BaseModel(T binding){ this.binding=binding; } public abstract void onResume(); public abstract void onActivityResult(int requestCode, int resultCode, Intent data); public abstract void onPause(); public abstract void onDestroy(); public abstract void onRestart(); public abstract void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults); protected void bindListener(View... views){ for (View view: views) { view.setOnClickListener(this); } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public abstract class SimpleBaseModel <T extends ViewBinding> implements View.OnClickListener { protected T binding; protected Activity context; public SimpleBaseModel(T binding, Activity context){ this.binding=binding; this.context=context; } public SimpleBaseModel(T binding){ this.binding=binding; } protected void bindListener(View... views){ for (View view: views) { view.setOnClickListener(this); } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54public abstract class BaseActivity<T extends ViewBinding,M extends BaseModel> extends AppCompatActivity{ protected T binding; protected M model; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); onPrepare(); binding=getBinding(); setContentView(binding.getRoot()); model=getModel(); } @Override protected void onDestroy() { super.onDestroy(); model.onDestroy(); } @Override protected void onPause() { super.onPause(); model.onPause(); } @Override protected void onResume() { super.onResume(); model.onResume(); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); model.onActivityResult(requestCode, resultCode, data); } @Override protected void onRestart() { super.onRestart(); model.onRestart(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); model.onRequestPermissionsResult(requestCode, permissions, grantResults); } protected abstract void onPrepare(); protected abstract T getBinding(); protected abstract M getModel(); }
下面是使用的例子,viewbinding可以灵活的引用include导入的布局,这里只是做一个范例,如果只是修改标题这种简单的逻辑,可以直接使用第三种写法。 其他两种model的形式,可以用于业务逻辑比较多的代码逻辑。对于model1的写法,是有重复布局的情况。model2的写法,是应用于业务逻辑大量重复,但布局不同的情况。可以在代码判断传入的binding的类型,对不同的视图进行不同的处理,也可以增加公共的回调接口进行处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52public class MainModel extends BaseModel<ActivityMainBinding> { TitleModel titleModel; TitleModel2 titleModel2; public MainModel(ActivityMainBinding binding, Activity context) { super(binding, context); titleModel=new TitleModel(binding.title,context); titleModel.setTitle("标题"); titleModel2=new TitleModel2(binding.title,context); titleModel2.setTitle(); binding.title.tx.setText("标题");//第三种写法 } public MainModel(ActivityMainBinding binding) { super(binding); } @Override public void onResume() { } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { } @Override public void onPause() { } @Override public void onDestroy() { } @Override public void onRestart() { } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { } @Override public void onClick(View v) { } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class TitleModel extends SimpleBaseModel<LayoutTitleBinding>{ public TitleModel(LayoutTitleBinding binding, Activity context) { super(binding, context); } public void setTitle(String str){ binding.tx.setText(str); } private void func(){ //需要重复的业务逻辑 } @Override public void onClick(View v) { } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public class TitleModel2 extends SimpleBaseModel{ public TitleModel2(ViewBinding binding, Activity context) { super(binding, context); } public void setTitle(){ if(binding instanceof LayoutTitleBinding) { ((LayoutTitleBinding) binding).tx.setText("test"); } } private void func(){ //需要重复的业务逻辑 } @Override public void onClick(View v) { } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class MainActivity extends BaseActivity<ActivityMainBinding,MainModel> { @Override protected void onPrepare() { } @Override protected ActivityMainBinding getBinding() { return ActivityMainBinding.inflate(getLayoutInflater()); } @Override protected MainModel getModel() { return new MainModel(binding,this); } }
最后贴出adapter和fragment的写法和用法,利用泛型可以节省大量的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109public abstract class BaseAdapter<T, B extends ViewBinding> extends RecyclerView.Adapter<BaseAdapter.ViewHolder> { protected OnItemClick onItemClick; protected List<T> mDatas; protected Context context; public List<T> getmDatas() { return mDatas; } public void setmDatas(List<T> mDatas) { this.mDatas = mDatas; } public BaseAdapter(Context context) { this.context = context; } public BaseAdapter(Context context, List<T> mDatas) { this.mDatas = mDatas; this.context = context; } public OnItemClick getOnItemClick() { return onItemClick; } public void setOnItemClick(OnItemClick onItemClick) { this.onItemClick = onItemClick; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(context); B binding = setBinding(inflater, parent); ViewHolder<B> viewHolder = new ViewHolder<B>(binding.getRoot()); viewHolder.setBinding(binding); if(onItemClick!=null){ viewHolder.setOnItemClick(onItemClick); } return viewHolder; } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { ViewHolder<B> myholder=(ViewHolder<B>) holder; onBindHolder(myholder,position); } protected abstract void onBindHolder(ViewHolder<B> holder, int position); @Override public int getItemViewType(int position) { return position; } @Override public long getItemId(int position) { return position; } protected abstract B setBinding(LayoutInflater inflater, ViewGroup parent); @Override public int getItemCount() { return mDatas == null ? 0 : mDatas.size(); } public static class ViewHolder<B extends ViewBinding> extends RecyclerView.ViewHolder implements View.OnClickListener { protected OnItemClick onItemClick; public B binding; public OnItemClick getOnItemClick() { return onItemClick; } public void setOnItemClick(OnItemClick onItemClick) { this.onItemClick = onItemClick; } public B getBinding() { return binding; } public void setBinding(B binding) { this.binding = binding; } public ViewHolder(View itemView) { super(itemView); } public void setClick(View... views){ if(onItemClick!=null) { for (View view : views) { view.setOnClickListener(this); } } } @Override public void onClick(View v) { onItemClick.onClick(v,getAdapterPosition()); } } public static interface OnItemClick{ void onClick(View view, int position); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class TestAdapter extends BaseAdapter<String,ItemTestBinding> { public TestAdapter(Context context, List <String>mDatas) { super(context, mDatas); } @Override protected void onBindHolder(ViewHolder<ItemTestBinding> holder, int position) { holder.getBinding().tx.setText(mDatas.get(position)); } @Override protected ItemTestBinding setBinding(LayoutInflater inflater, ViewGroup parent) { return ItemTestBinding.inflate(inflater,parent,false); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public abstract class BaseFragment<T extends ViewBinding,M extends BaseModel> extends Fragment { protected T binding; protected M model; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { onPrepare(); binding=getBinding(inflater,container,savedInstanceState); model=getModel(); return binding.getRoot(); } protected abstract void onPrepare(); protected abstract T getBinding(LayoutInflater inflater, @Nullable ViewGroup container,@Nullable Bundle savedInstanceState); protected abstract M getModel(); }
源码已经上传github
地址:https://github.com/roofroot/test_view_binding
最后
以上就是英俊太阳最近收集整理的关于ViewBinding与MVVM框架的全部内容,更多相关ViewBinding与MVVM框架内容请搜索靠谱客的其他文章。
发表评论 取消回复