需求場(chǎng)景 :
在viewmodel中需要改變一個(gè)自定義view的自定義屬性(比如 smartrefashlayout的下拉刷新去請(qǐng)求數(shù)據(jù),以及加載完成或者刷新完成關(guān)閉加載動(dòng)畫)
思路:
1.mvvmlight 提供的command 方式(只適合自定義view中存在暴露給外部監(jiān)聽的方式,或者自
己通過(guò)bindadapter監(jiān)聽某個(gè)狀態(tài)達(dá)到目的的場(chǎng)景,后面會(huì)講具體實(shí)現(xiàn))
command 的解決問(wèn)題的方式是利用了bindadapter 和 java8的函數(shù)式編程(當(dāng)然你用rxjava
也ok)。
2.通過(guò)bindadapter 和 InverseBindingAdapter (http://www.itdecent.cn/p/a05c9735f595)/(https://yq.aliyun.com/articles/615840)
方式1 實(shí)現(xiàn)步驟:
a. 定義command (jdk8的函數(shù)接口)
@FunctionalInterface
public interface ReplyCommand {
void exectue();
}
b.BindingAdapter
public class BindingAdapters {
@BindingAdapter({"onRefreshCommand"})
public static void setonRefreshCommand(SmartRefreshLayout smartRefreshLayout, final ReplyCommand onRefreshCommand) {
smartRefreshLayout.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh(RefreshLayout refreshLayout) {
onRefreshCommand.exectue();
}
});
}
@BindingAdapter({"onloadmoreCommand"})
public static void setonloadmoreCommand(SmartRefreshLayout smartRefreshLayout, final ReplyCommand onloadmoreCommand) {
smartRefreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() {
@Override
public void onLoadMore(RefreshLayout refreshLayout) {
onloadmoreCommand.exectue();
}
});
}
@BindingAdapter({"oncompleteCommand"})
public static void setoncompleteCommand(SmartRefreshLayout smartRefreshLayout, final ReplyCommandParam oncompleteCommand) {
oncompleteCommand.exectue(smartRefreshLayout);
}
}
c. xml 中引用
<com.scwang.smartrefresh.layout.SmartRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
bind:onRefreshCommand="@{viewModel.onrefreshCommand}"
bind:onloadmoreCommand="@{viewModel.onloadmoreCommand}">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycle"
android:layout_width="match_parent"
android:layout_height="match_parent"
bind:itemView="@{viewModel.KnowitemBinding}"
bind:items="@{viewModel.knowItems}"
bind:layoutManager="@{LayoutManager.linear()}" />
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
d.viewmodel 中使用
public final ReplyCommand onrefreshCommand = ()->{ getKnowledgeHierarchyData();};
public final ReplyCommand onloadmoreCommand = ()->{ getKnowledgeHierarchyData();};
結(jié)果: 發(fā)現(xiàn)下拉刷新絲滑了,數(shù)據(jù)驅(qū)動(dòng),但是你會(huì)發(fā)現(xiàn)數(shù)據(jù)獲取成功后加載的動(dòng)畫并沒有關(guān)閉 so 方式二就需要出場(chǎng)救急了
方式二實(shí)現(xiàn)步驟
1. 下載smartrefashlayout 的源碼,使用導(dǎo)入module的方式引入項(xiàng)目(因?yàn)閷?duì)反向綁定的InverseBindingMethods使用的不多,接下來(lái)會(huì)研究,等第二篇)
-
增加view的自定義屬性 <attr name="refreshcomplete" format="boolean"/> 3. initview的時(shí)候獲取屬性并提供setter getter,
refreshcomplete =
ta.getBoolean(R.styleable.SmartRefreshLayout_refreshcomplete,false);public boolean getRefreshcomplete() { return refreshcomplete; } public void setRefreshcomplete(boolean refreshcomplete) { this.refreshcomplete = refreshcomplete; }- 自己領(lǐng)會(huì)下,等后邊步驟看完就知道為嘛要這樣了
@BindingAdapter("refreshcompleteAttrChanged")
public static void setRefreshcompleteAttrChanged(SmartRefreshLayout view, InverseBindingListener inverseBindingListener) {
if (inverseBindingListener == null) {
view.setListener(null);
} else {
view.setListener(inverseBindingListener::onChange);
}
}
@BindingAdapter(value = "refreshcomplete")
public static void setcomplete(SmartRefreshLayout view, boolean refreshcomplete) {
view.setRefreshcomplete(refreshcomplete);
if(refreshcomplete){
view.finishRefresh();
view.finishLoadMore();
}
}
@InverseBindingAdapter(attribute = "refreshcomplete", event = "refreshcompleteAttrChanged")
public static boolean getcomplete(SmartRefreshLayout view) {
return view.getRefreshcomplete();
}
private OnValueChangedListener listener;
public interface OnValueChangedListener {
void onValueChanged();
}public void setListener(OnValueChangedListener listener) {
this.listener = listener;
}- 定義 實(shí)體類,xml中使用
public class Testvo extends BaseObservable implements Serializable {
- 自己領(lǐng)會(huì)下,等后邊步驟看完就知道為嘛要這樣了
public boolean complete;
@Bindable
public boolean getComplete() {
return complete;
}
public void setComplete(boolean complete) {
this.complete = complete;
notifyPropertyChanged(BR.complete);
}
}
注意規(guī)范,類的首字母必須大寫,書寫規(guī)范能避免很多大坑
<variable
name="data"
type="com.docker.moduleplayer.vo.Testvo"/>
<import type="com.docker.commonlibrary.bind.recycleviewbind.LayoutManager" />
</data>
<com.scwang.smartrefresh.layout.SmartRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
bind:refreshcomplete="@={data.complete}"
bind:onRefreshCommand="@{viewModel.onrefreshCommand}"
bind:onloadmoreCommand="@{viewModel.onloadmoreCommand}">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycle"
android:layout_width="match_parent"
android:layout_height="match_parent"
bind:itemView="@{viewModel.KnowitemBinding}"
bind:items="@{viewModel.knowItems}"
bind:layoutManager="@{LayoutManager.linear()}" />
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
- viewmodel 中實(shí)例化
public Testvo vo = new Testvo();
activity 中setData
7.完成,再回頭看步驟4,有沒有明白呢?