我发现很难发现android.databinding.ObservableList
作为数据绑定功能的真正存在理由。
首先,通过data binding通过xml
将列表添加到RecyclerView
,它看起来像是一个很酷的工具来显示列表。
为此,我做了BindingAdapter这样:
@BindingAdapter(value = {"items"}, requireAll = false)
public static void setMyAdapterItems(RecyclerView view, ObservableList <T> items) {
if(items != null && (view.getAdapter() instanceof MyAdapter)) {
((GenericAdapter<T>) view.getAdapter()).setItems(items);
}
}
这样,我可以在设置了app:items
的{{1}}中使用属性RecyclerView
来更新其项目。
现在MyAdapter
的最佳功能是你可以添加ObservableList
,它可以处理OnListChangedCallback
中可用的相同事件,以添加/移动/删除/更改其中的项目没有实际重新加载整个列表。
所以我认为实施的逻辑是休假:
RecyclerView
MyAdapter
包装它们并将其传递给ObservableArrayList
binding
将项目传递给BindingAdapter
MyAdapter
收到新项目时,会清除旧项目,并为收到的MyAdapter
添加OnListChangedCallback
以处理微更改ObservableList
发生任何变化,ObservableList
会相应更改而不会完全刷新MyAdapter
变量,以便再次调用binding
和BindingAdapter
项将完全改变。例如,如果我想要显示MyAdapter
类型的项目,我有两个不同的列表:“拥有游戏”和“愿望清单游戏”,我可以调用Game
来完全刷新显示的项目,但是,例如,如果我在列表周围移动“愿望清单游戏”以按相关性组织它们,则只会在每个列表中执行微更改而不刷新整个事物。
事实证明这个想法是不可行的,因为每次对binding.setItems(whateverItems)
进行一次更改时,数据绑定都会重新执行BindingAdapter
,所以例如我观察到了以下行为:
ObservableList
MyAdapter
包装它们并将其传递给ObservableArrayList
binding
将项目传递给BindingAdapter
MyAdapter
收到新项目时,会清除旧项目,并为收到的MyAdapter
添加OnListChangedCallback
以处理微更改ObservableList
发生任何变化,则会再次调用ObservableList
,因此BindingAdapter
会再次收到整个列表并完全刷新。这种行为对我来说似乎很不妥,因为阻止MyAdapter
在数据绑定ObservableList
中可用。我无法认真地找出这种行为是合情合理的案例。
我查了一些例子:here和this other SO question
在第一个链接中,所有示例都将xml
直接用于ObservableList
,甚至没有传递形式Adapter
和实际数据绑定,而在SO答案中链接的代码中,开发人员基本上做了我尝试做的事情,添加:
xml
在他if (this.items == items){
return;
}
的开头,放弃因Adapter.setItems(ObservableList<T> items)
中的简单更改而调用该方法的所有情况。
这种行为有什么需要?可能在某些情况下这种行为是可取的?我觉得ObservableList
是一个添加了数据绑定的功能,除非与实际数据绑定一起使用时非常有用,在这种情况下它会强制您防范其行为。
如果我在ObservableList
数据标记和List
签名中将其声明为简单xml
,那么我可以将其转发回BindingAdapter
内的ObservableList
工作得很好,但这是一个非常糟糕的黑客。
如果它只是数据绑定的一个单独功能,在每次更改时都不会触发绑定,那么在我看来它会好得多。
答案 0 :(得分:1)
根据文档https://developer.android.com/topic/libraries/data-binding/index.html#observable_collections中提供的示例,ObservableList用于使用键整数访问它的项目,即:
<data>
<import type="android.databinding.ObservableList"/>
<import type="com.example.my.app.Fields"/>
<variable name="user" type="ObservableList<Object>"/>
</data>
…
<TextView
android:text='@{user[Fields.LAST_NAME]}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
因此,当在ObservableList
内部更改某些内容时,它会触发BindingAdapter来更新UI。我认为这是当前使用ObservableList
而DataBinding处于开发状态时的主要目的。也许在将来,DataBinding将使用新的SomeObservableList
进行更新,该if (this.items == items){return;}
将用于RecyclerView。
同时,如果ObservableList
适用于您,您可以使用 $inherited1 = '1';
$inherited2 = '2';
$example = function($arg) use (&$inherited1, &$inherited2){
// access the $inherited1 and $inherited2 variables directly
var_dump($arg . $inherited1 . $inherited2);
}
$example('arg');
,或者重新考虑使用<script>
window.result = [
{
"title": "What You Need To Know About CSS Variables",
},
{
"title": "Freebie: 4 Great Looking Pricing Tables",
},
{
"title": "20 Interesting JavaScript and CSS Libraries for February 2016",
},
{
"title": "Quick Tip: The Easiest Way To Make Responsive Headers",
},
{
"title": "Learn SQL In 20 Minutes",
},
{
"title": "Creating Your First Desktop App With HTML, JS and Electron",
}
];
</script>
<form id="main" v-cloak>
<div class="bar">
<!-- Create a binding between the searchString model and the text field -->
<input type="text" v-model="searchString" placeholder="Enter your search terms" />
</div>
<ul>
<!-- Render a li element for every entry in the computed filteredArticles array. -->
<li v-for="article in filteredArticles">
<p>{{article.title}}</p>
</li>
</ul>
</form>
<script>
window.result(2) = [
{
"title": "What You Need To Know About CSS Variables",
}
];
</script>
<form id="main2">
<div class="bar">
<!-- Create a binding between the searchString model and the text field -->
<input type="text" v-model="searchString" placeholder="Enter your search terms" />
</div>
<ul>
<!-- Render a li element for every entry in the computed filteredArticles array. -->
<li v-for="article in filteredArticles">
<p>{{article.title}}</p>
</li>
</ul>
</form>
<script>
window.result(3) = [
{
"title": "What You Need To Know About CSS Variables",
}
];
</script>
<form id="main3">
<div class="bar">
<!-- Create a binding between the searchString model and the text field -->
<input type="text" v-model="searchString" placeholder="Enter your search terms" />
</div>
<ul>
<!-- Render a li element for every entry in the computed filteredArticles array. -->
<li v-for="article in filteredArticles">
<p>{{article.title}}</p>
</li>
</ul>
</form>
var results = window.result;
var demo = new Vue({
el: '#main',
data: {
searchString: "",
articles:results
},
computed: {
// A computed property that holds only those articles that match the searchString.
filteredArticles: function () {
var articles_array = this.articles,
searchString = this.searchString;
if(!searchString){
return articles_array;
}
searchString = searchString.trim().toLowerCase();
articles_array = articles_array.filter(function(item){
if(item.title.toLowerCase().indexOf(searchString) !== -1){
return item;
}
})
return articles_array;;
}
}
的逻辑。