ViewBinding与MVVM框架

2024-06-05 12:08
文章标签 框架 mvvm viewbinding

本文主要是介绍ViewBinding与MVVM框架,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

MVVM框架主要的特点就是低耦合,对于不同的view,model可以复用。

目前android 的MVVM框架主要是使用 databinding实现双向数据绑定,来降低耦合度。

首先是用databinding来实现mvvm框架,下面是一个我自己总结的使用databinding来实现mvvm框架的简单示例。

之后是我使用Viewbinding实现的框架,可以说用起来更加的灵活便捷。

model类,这个类主要是一些与视图相关的业务逻辑的处理,对于一些需要复用并且实现不同逻辑的model类,可以使用回调的方式来执行不同的业务逻辑。例如下面代码中的titlemodel, 需要更新数据的时候,需要调用notifyPropertyChanged(BR.title)来刷新页面数据

public 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;}}
public  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);}@Bindablepublic 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);}@Bindablepublic 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);}
}
public 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() {@Overridepublic void onBack(View view) {Toast.makeText(activity,"按下返回键",Toast.LENGTH_SHORT).show();}@Overridepublic 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() {@Overridepublic void onClick(View view, TestEntity info, int position) {}@Overridepublic 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的形式。

public 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);}}}
public 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);}}
}
public abstract class BaseActivity<T extends ViewBinding,M extends  BaseModel> extends AppCompatActivity{protected T binding;protected M model;@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);onPrepare();binding=getBinding();setContentView(binding.getRoot());model=getModel();}@Overrideprotected void onDestroy() {super.onDestroy();model.onDestroy();}@Overrideprotected void onPause() {super.onPause();model.onPause();}@Overrideprotected void onResume() {super.onResume();model.onResume();}@Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);model.onActivityResult(requestCode, resultCode, data);}@Overrideprotected void onRestart() {super.onRestart();model.onRestart();}@Overridepublic 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的类型,对不同的视图进行不同的处理,也可以增加公共的回调接口进行处理

public 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);}@Overridepublic void onResume() {}@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {}@Overridepublic void onPause() {}@Overridepublic void onDestroy() {}@Overridepublic void onRestart() {}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,@NonNull int[] grantResults) {}@Overridepublic void onClick(View v) {}
}
public 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(){//需要重复的业务逻辑}@Overridepublic void onClick(View v) {}}
public 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(){//需要重复的业务逻辑}@Overridepublic void onClick(View v) {}}
public class MainActivity extends BaseActivity<ActivityMainBinding,MainModel> {@Overrideprotected void onPrepare() {}@Overrideprotected ActivityMainBinding getBinding() {return ActivityMainBinding.inflate(getLayoutInflater());}@Overrideprotected MainModel getModel() {return new MainModel(binding,this);}
}

最后贴出adapter和fragment的写法和用法,利用泛型可以节省大量的代码

public 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;}@Overridepublic 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;}@Overridepublic 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);@Overridepublic int getItemViewType(int position) {return position;}@Overridepublic long getItemId(int position) {return position;}protected abstract B setBinding(LayoutInflater inflater, ViewGroup parent);@Overridepublic 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);}}}@Overridepublic void onClick(View v) {onItemClick.onClick(v,getAdapterPosition());}}public static interface  OnItemClick{void onClick(View view, int position);}}
public class TestAdapter extends BaseAdapter<String,ItemTestBinding> {public TestAdapter(Context context, List <String>mDatas) {super(context, mDatas);}@Overrideprotected void onBindHolder(ViewHolder<ItemTestBinding> holder, int position) {holder.getBinding().tx.setText(mDatas.get(position));}@Overrideprotected ItemTestBinding setBinding(LayoutInflater inflater, ViewGroup parent) {return ItemTestBinding.inflate(inflater,parent,false);}
}
public abstract class BaseFragment<T extends ViewBinding,M extends  BaseModel> extends Fragment {protected T binding;protected M model;@Nullable@Overridepublic 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框架的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1033006

相关文章

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

基于Flask框架添加多个AI模型的API并进行交互

《基于Flask框架添加多个AI模型的API并进行交互》:本文主要介绍如何基于Flask框架开发AI模型API管理系统,允许用户添加、删除不同AI模型的API密钥,感兴趣的可以了解下... 目录1. 概述2. 后端代码说明2.1 依赖库导入2.2 应用初始化2.3 API 存储字典2.4 路由函数2.5 应

Python GUI框架中的PyQt详解

《PythonGUI框架中的PyQt详解》PyQt是Python语言中最强大且广泛应用的GUI框架之一,基于Qt库的Python绑定实现,本文将深入解析PyQt的核心模块,并通过代码示例展示其应用场... 目录一、PyQt核心模块概览二、核心模块详解与示例1. QtCore - 核心基础模块2. QtWid

最新Spring Security实战教程之Spring Security安全框架指南

《最新SpringSecurity实战教程之SpringSecurity安全框架指南》SpringSecurity是Spring生态系统中的核心组件,提供认证、授权和防护机制,以保护应用免受各种安... 目录前言什么是Spring Security?同类框架对比Spring Security典型应用场景传统

Python结合Flask框架构建一个简易的远程控制系统

《Python结合Flask框架构建一个简易的远程控制系统》这篇文章主要为大家详细介绍了如何使用Python与Flask框架构建一个简易的远程控制系统,能够远程执行操作命令(如关机、重启、锁屏等),还... 目录1.概述2.功能使用系统命令执行实时屏幕监控3. BUG修复过程1. Authorization

SpringBoot集成图片验证码框架easy-captcha的详细过程

《SpringBoot集成图片验证码框架easy-captcha的详细过程》本文介绍了如何将Easy-Captcha框架集成到SpringBoot项目中,实现图片验证码功能,Easy-Captcha是... 目录SpringBoot集成图片验证码框架easy-captcha一、引言二、依赖三、代码1. Ea

Gin框架中的GET和POST表单处理的实现

《Gin框架中的GET和POST表单处理的实现》Gin框架提供了简单而强大的机制来处理GET和POST表单提交的数据,通过c.Query、c.PostForm、c.Bind和c.Request.For... 目录一、GET表单处理二、POST表单处理1. 使用c.PostForm获取表单字段:2. 绑定到结

修改若依框架Token的过期时间问题

《修改若依框架Token的过期时间问题》本文介绍了如何修改若依框架中Token的过期时间,通过修改`application.yml`文件中的配置来实现,默认单位为分钟,希望此经验对大家有所帮助,也欢迎... 目录修改若依框架Token的过期时间修改Token的过期时间关闭Token的过期时js间总结修改若依

MyBatis框架实现一个简单的数据查询操作

《MyBatis框架实现一个简单的数据查询操作》本文介绍了MyBatis框架下进行数据查询操作的详细步骤,括创建实体类、编写SQL标签、配置Mapper、开启驼峰命名映射以及执行SQL语句等,感兴趣的... 基于在前面几章我们已经学习了对MyBATis进行环境配置,并利用SqlSessionFactory核

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte