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

相关文章

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

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

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

数据治理框架-ISO数据治理标准

引言 "数据治理"并不是一个新的概念,国内外有很多组织专注于数据治理理论和实践的研究。目前国际上,主要的数据治理框架有ISO数据治理标准、GDI数据治理框架、DAMA数据治理管理框架等。 ISO数据治理标准 改标准阐述了数据治理的标准、基本原则和数据治理模型,是一套完整的数据治理方法论。 ISO/IEC 38505标准的数据治理方法论的核心内容如下: 数据治理的目标:促进组织高效、合理地

ZooKeeper 中的 Curator 框架解析

Apache ZooKeeper 是一个为分布式应用提供一致性服务的软件。它提供了诸如配置管理、分布式同步、组服务等功能。在使用 ZooKeeper 时,Curator 是一个非常流行的客户端库,它简化了 ZooKeeper 的使用,提供了高级的抽象和丰富的工具。本文将详细介绍 Curator 框架,包括它的设计哲学、核心组件以及如何使用 Curator 来简化 ZooKeeper 的操作。 1

【Kubernetes】K8s 的安全框架和用户认证

K8s 的安全框架和用户认证 1.Kubernetes 的安全框架1.1 认证:Authentication1.2 鉴权:Authorization1.3 准入控制:Admission Control 2.Kubernetes 的用户认证2.1 Kubernetes 的用户认证方式2.2 配置 Kubernetes 集群使用密码认证 Kubernetes 作为一个分布式的虚拟

Spring Framework系统框架

序号表示的是学习顺序 IoC(控制反转)/DI(依赖注入): ioc:思想上是控制反转,spring提供了一个容器,称为IOC容器,用它来充当IOC思想中的外部。 我的理解就是spring把这些对象集中管理,放在容器中,这个容器就叫Ioc这些对象统称为Bean 用对象的时候不用new,直接外部提供(bean) 当外部的对象有关系的时候,IOC给它俩绑好(DI) DI和IO

Sentinel 高可用流量管理框架

Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。 Sentinel 具有以下特性: 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应

利用Django框架快速构建Web应用:从零到上线

随着互联网的发展,Web应用的需求日益增长,而Django作为一个高级的Python Web框架,以其强大的功能和灵活的架构,成为了众多开发者的选择。本文将指导你如何从零开始使用Django框架构建一个简单的Web应用,并将其部署到线上,让世界看到你的作品。 Django简介 Django是由Adrian Holovaty和Simon Willison于2005年开发的一个开源框架,旨在简

MVC(Model-View-Controller)和MVVM(Model-View-ViewModel)

1、MVC MVC(Model-View-Controller) 是一种常用的架构模式,用于分离应用程序的逻辑、数据和展示。它通过三个核心组件(模型、视图和控制器)将应用程序的业务逻辑与用户界面隔离,促进代码的可维护性、可扩展性和模块化。在 MVC 模式中,各组件可以与多种设计模式结合使用,以增强灵活性和可维护性。以下是 MVC 各组件与常见设计模式的关系和作用: 1. Model(模型)

Yii框架relations的使用

通过在 relations() 中声明这些相关对象,我们就可以利用强大的 Relational ActiveRecord (RAR) 功能来访问资讯的相关对象,例如它的作者和评论。不需要自己写复杂的 SQL JOIN 语句。 前提条件 在组织数据库时,需要使用主键与外键约束才能使用ActiveReocrd的关系操作; 场景 申明关系 两张表之间的关系无非三种:一对多;一对一;多对多; 在