网站开发笔试题,wordpress js代码插件下载,网页优化公司,设计网名大全原文地址#xff1a; https://blog.csdn.net/ldld1717/article/details/77040077概述MVVM Light Toolkit是一个Android MVVM 轻量级工具库#xff0c;主要目的是更快捷方便的构建Android MVVM应用程序#xff0c;工具库添加了一些Data Binding 不支持的属性#xff0c;还有…原文地址 https://blog.csdn.net/ldld1717/article/details/77040077 概述 MVVM Light Toolkit是一个Android MVVM 轻量级工具库主要目的是更快捷方便的构建Android MVVM应用程序工具库添加了一些Data Binding 不支持的属性还有添加对控件事件的封装同时提个一个全局消息通道方便ViewModel 之间的通信Toolkit主要包括两部分Binding和Messenger,接下来我们分别说明下这两个模块的作用和使用方法。源码Github:https://github.com/Kelin-Hong/MVVMLightcompile com.kelin.mvvmlight:library:1.0.0BindingMVVM Binding Schematic Diagram由上图我们可以看到在View和ViewModel的绑定中包含两种绑定一种是数据的绑定比如TextViewtext另外一种命令绑定命令绑定我们可以理解为事件绑定比如Button:click但是目前Databinding 并不完全支持命令的绑定 而且对Data的绑定的支持也不完善比如说不支持AdapterView对DataSource的绑定那么在MVVM LightBinding我们添加了部分Data绑定支持和Command绑定的支持。Data 绑定我们添加了ImageViewuri、placeholderImageResListViewviews、itemView 等部分控件的一些属性这使得我们用起来就方便很多例如我们只要在xml布局ImageView标签中设置uri,那么这个图片就能自动去加载这个uri的图片,如下ImageView android:layout_widthmatch_parent android:layout_heightmatch_parent android:layout_alignParentRighttrue bind:uri{viewModel.imageUrl} bind:placeholderImageRes{R.drawable.ic_launcher}/当然ImageView还支持其他属性placeholderImageRes 图片还没有下载完成时的替换图片request_width 请求图片的宽度会自动帮你裁剪request_height请求图片的高度会自动帮你裁剪接下来看下示例image.gif对于ListView、RecyclerView 和 ViewPager 等AdapterView使用起来就更加简单了在布局文件添加bind:itemView(子布局模板)bind:items(数据源)还有bind:layoutManager就能ok了完全不需要写Adapter相关的东西。 android.support.v7.widget.RecyclerView android:layout_widthmatch_parent android:layout_heightmatch_parent bind:itemView{viewModel.itemView} bind:items{viewModel.itemViewModel} bind:layoutManager{LayoutManagers.linear()}然后Java 代码中在ViewModel定义itemView和itemViewModel就可以了列表就能展示出来了public final ObservableListViewModel itemViewModel new ObservableArrayList(); public final ItemView itemView ItemView.of(BR.viewModel, R.layout.layoutitem_list_view);动画示例:listview_databinding.gif关于AdapterView 数据源绑定问题主要还是Google的DataBinding框架还不够完善相信不久后肯定有更好的方案出来让我们更加方便把数据源和布局模板绑定到ListView上当然现在也有一些开源库帮我们把这个部分做好了我们也不重复造轮子就直接使用了关于AdapterView的一些数据绑定扩展https://github.com/evant/binding-collection-adapter 给了比较详细的描述基本能满足大部分AdapterView的需求。接下来列举目前MVVM Light 工具库支持的一些Data Binding的属性:ImageViewattr nameuri / !--width for ResizeOptions (use Fresco to load bitmap). -- attr namerequest_width formatinteger / !--height for ResizeOptions (use Fresco to load bitmap). -- attr namerequest_height formatinteger / attr nameplaceholderImageRes formatreference|color /ListView、ViewPager、RecyclerView !-- require ItemView or ItemViewSelector -- attr nameitemView / !-- require ListViewModel bind to ItemView to presentation.-- attr nameitems / !-- require a adapter which type of BindingRecyclerViewAdapterT to AdapterView-- attr nameadapter / attr namedropDownItemView formatreference / attr nameitemIds formatreference / attr nameitemIsEnabled formatreference / !-- require PageTitlesT-- attr namepageTitles formatreference /ViewGroup !-- require ItemView or ItemViewSelector -- attr nameitemView / !-- require ListViewModel bind to ItemView to presentation.-- attr nameviewModels formatreference /EditText !-- require boolean value to decide whether requestFocus for view. -- attr namerequestFocus formatboolean /SimpleDraweeView !-- require String to load Image-- attr nameuri /WebView !-- require String render to html show in webview-- attr namerender formatstring /目前整理的一些常用属性和控件可能不足我们也不太可能能把所有可用的控件和控件关联的属性全部做一些封装希望开发者自己可以在需要的时候去继承相应的类扩展更多的属性。Command 绑定Command 翻译为命令就是控件发号施令然后有人去回复处理这个命令比如Button 发出一个Click Command那么应该有个处理者来处理这个命令我们把这个处理者叫做ReplyCommand,我们把ReplyCommand绑定到相应的控件上如果控件发出Event的时候就会找到这个ReplyCommand让它来处理这个事件说得简单一些就是我们对控件一些事件做了简单的封装使得处理这些事件我们只有关注我们相应事件传递给我们想要的数据其他UI相关的逻辑并不需要我们去关心。接下来我们简要说明具体使用方法 android.support.v7.widget.RecyclerView android:idid/recyclerView android:layout_widthmatch_parent android:layout_heightmatch_parent bind:onLoadMoreCommand{viewModel.loadMoreCommand}/bind:onLoadMoreCommand: RecyclerView 在滑到最底部的时候自动触发这个事件这个事件的处理者是一个ReplyCommandInteger类型的变量接下来我们在ViewModel 里面的定义一个ReplyCommandInteger 变量 public final ReplyCommandInteger loadMoreCommand new ReplyCommand( (count) - { /*count 代表当前RecyclerView 有多少个Item,通过这个值我们可以 得到当前应该去加载第几页的数据*/ int pagecount / LIMIT; loadData(page) });对于处理RecyclerView 下拉加载更多我们之前的做法可能需要去写各种代码来判断是否滑动底部在OnScrollListener 里面做一些计算然后才知道滑到底部了但是如果用封装好的Command事件你的ViewModel里面的代码将非常简洁只要简要的声明一个 ReplyCommandInteger它就能自动传一个当前List中Item的总数给你你要做的只是专注你的业务处理比如 加载数据ViewModel 里面只处理数据不处理控件没有任何控件的引用所以UI的状态和变化都由数据来绑定控制的这样数据就成了主角我们在ViewModel 里面只要和数据打交道就可以了。动画示例listview load more同时对于我最常见的点击事件我们也做对了click事件的封装封装成一个clickCommand,接受的参数是一个无参的ReplyCommand动画示例clickCommand.gif关于下拉刷新控件SwipeRefreshLayout的下拉刷新事件也简单封装成另一个ReplyCommand动画示例refresh.gif接下来列举目前MVVM Light 工具库支持的一些Command Binding的属性:View!-- require ReplyCommand to deal with view click event. -- attr nameclickCommand formatreference / !-- require ReplyCommandBoolean to deal with view focus change event. ReplyCommand would has params which means if view hasFocus.-- attr nameonFocusChangeCommand formatreference / !-- require ReplyCommandMotionEvent -- attr nameonTouchCommand /ListView、RecyclerView!-- require ReplyCommandInteger -- attr nameonScrollStateChangedCommand / !-- require ReplyCommandListViewScrollDataWrapper -- attr nameonScrollChangeCommand / !-- require ReplyCommandInteger count of list items-- attr nameonLoadMoreCommand formatreference /ViewPager !--require ReplyCommandViewPagerDataWrapper -- attr nameonPageScrolledCommand formatreference / !--require ReplyCommandInteger -- attr nameonPageSelectedCommand formatreference / !--require ReplyCommandInteger -- attr nameonPageScrollStateChangedCommand formatreference /EditText!--require ReplyCommandTextChangeDataWrapper -- attr namebeforeTextChangedCommand formatreference / !--require ReplyCommandTextChangeDataWrapper -- attr nameonTextChangedCommand formatreference / !--require ReplyCommandString -- attr nameafterTextChangedCommand formatreference /ImageView !-- require ReplyCommandBitmap -- attr nameonSuccessCommand formatreference / !--require ReplyCommandCloseableReferenceCloseableImage -- attr nameonFailureCommand formatreference /ScrollView、NestedScrollView!-- require ReplyCommandScrollDataWrapper -- attr nameonScrollChangeCommand / !-- require ReplyCommandNestScrollDataWrapper -- attr nameonScrollChangeCommand /SwipeRefreshLayout!-- require RelayCommand -- attr nameonRefreshCommand formatreference /以上的Command有继承效应即ImageView、TextView是View的子类所以它们都拥有View 扩展的Data Binding和Command Binding 如clickCommand 等。注MVVMLight 目前只支持上面提及的部分的控件Data和Command绑定还有大部分的控件一些属性和事件并没有去封装我们希望您根据自己的需求去补充包括一些你用的自定义控件和第三方控件都可以简单封装成一个Command这样使得我们的ViewModel 更加简洁同时是我们更能专心处理数据和业务不关心控件和UI。上面涉及的属性和Command我们在attrs文件都已经声明您在xml文件使用中将可以自动提示相应的名称比如你在TextView中打bind的时候和TextView相关的属性都会提示如requestFocus、clickCommand、等相关的属性但是属性后面需要哪种ReplyCommandT,即T应该是什么类型就需要查一下相应的文档、或者查一下源码。由于没办法做到在xml输入属性如bind:clickCommand自动提示应该输入什么值接入什么参数所以这时候最简单的方式就是去查源码我们把每个控件都单独放到一个包里面方便查找源码。如果你没找到源码的位置你可以shiftcommando 然后输入ViewBindingAdapter也就是打开文件ViewBindingAdapter.class 或者 ViewBindingAdapter.java 然后选择相应的控件去查看该控件的支持哪些属性和Command同时可以查看需要的ReplyCommand的类型。虽然是ViewBindingAdapter 里面的方法是static但是是支持重写的,保持参数和BindingAdapter(value * 的值不变DataBinding 的找方法的时候就优先采用你写的方法而不是库里的方法也就是如果你对ViewBindingAdapter的里面的static方法的实现不满意的是可以重写的。Messenger引入messenger最主要的目的就实现ViewModel和ViewModel的通信也可以用做View和ViewModel的通信但是并不推荐这样做。ViewModel主要是用来处理业务和数据的每个ViewModel都有相应的业务职责但是在业务复杂的情况下可能存在交叉业务这时候就需要ViewModel和ViewModel交换数据和通信这时候一个全局的消息通道就很重要的。接下来我们简单看一下messenger的使用全局广播消息,没有参数 /* 全局发送一个消息但是不传任何参数给接收者 TOKEN: 相当于broadcast的Action,谁注册了这个令牌相当于准备接收这个消息*/ Messenger.Default().sendNoMsg(TOKEN); /* context: 一般是activity代表接收者用于在取消注册的时候使用unRegister(context)可快速取消这个context里面的所有注册 TOKEN: 相当于broadcast的Action,谁注册了这个令牌相当于准备接收这个消息 (data)-{ }: 处理消息的Action */ Messenger.Default().register(context, TOKEN, () - { });全局广播消息带有参数 /*发送消息传递参数data任何类型都可TOKEN 是一个令牌String类型相当于 broadcast的Action,谁注册了这个令牌相当于准备接收这个消息*/ Messenger.getDefault().send(data, TOKEN) /* context: 同上 * TOKEN: 相当于broadcast的Action,谁注册了这个令牌相当于准备接收这个消息 * Data.class: 传递过来参数的类型如 String.class,Model.class * (data)-{ }: 处理消息的function参数是传递过来的 */ Messenger.getDefault().register(context, TOKEN, Data.class, (data) - { });示例发送到指定的接收器(不常用) /*target 代表接收对象一般是ActivityViewModel 持有Activity的引 用直接将消息发到指定的目标而不是广播*/ Messenger.getDefault().sendToTarget(T message, R target) Messenger.getDefault().sendNoMsgToTargetWithToken(Object token,R target) Messenger.getDefault().sendNoMsgToTarget(Object target)取消注册/*一般在Activity的OnDestroy()方法中调用就可以 因为我们一般注册的时候 第一个参数 recipient就是传的当前的context所以只要取消注册这个Activity就再也收不到任何的消息了*/ Messenger.getDefault().unregister(Object recipient)Messenger在全局虽然传递数据和通知非常方便但是建议不要滥用消息通知太多也意味着耦合性太高代码框架设计不够友好同时影响代码的可读性ViewModel和View最好是用绑定的方式去处理UI和事件ViewModel 和ViewModel 一些数据的通信交互才用Messenger来传递会好一些。注1、Messenger 一定要取消注册不然会造成严重的内存泄露2、Messenger 的TOKEN在命名的时候要注意最好和相关的ViewModel结合起来避免在同一个App出现两个相同的Token这样会把消息发到其他你不知道的地方造成潜在的BUG 转载于:https://www.cnblogs.com/nimorl/p/9139250.html