我正试图进入android中的数据绑定。 因为我对WPF中的数据绑定更有经验,所以我非常困惑。
在WPF中,使用自定义项将对象列表绑定到列表视图是很容易的。以下是私人项目的示例:
就是这样。不需要胶水代码或适配器。
我的问题:
因为我很困惑,关于适配器/充气东西等 有一个很好的关于绑定到列表的教程,但是我仍然需要为绑定编写代码。
http://blog.trsquarelab.com/2016/01/data-binding-in-android-listview.html
答案 0 :(得分:1)
Android中的东西是不同的
是否可以在后台没有任何代码的情况下将项目绑定到列表视图?
您必须在适配器类中使用数据绑定代码作为列表视图。
我可以在列表视图的布局中定义“列表视图项”吗?
不,你不能!列表视图项必须具有自己的布局。
由于您对适配器感到困惑,因此以下几点可以使其更清晰:
将适配器视为管理数据模型的管理器,并使其适应列表视图的各个条目。适配器将填充每行的布局,并将数据分配给行中的单个视图。
如果没有数据绑定,适配器类可以包含很多代码,具体取决于行UI的复杂程度。因此,使用数据绑定将有助于仅使用几行绑定代码从适配器类中删除所有不必要的代码。
您发布的链接已足够开始,但我建议您使用 Recycler view 。以下是您可以查看的其他链接
答案 1 :(得分:0)
Android DataBinding需要一些代码即可完成
您的所有项目都可以重用前面的步骤1,接下来的步骤2和3都是布局资源文件,就像WPF一样
步骤1.为所有AbsListView定义BindingAdapter类,您的其他项目AbsListView可以重用该类
public class AbsListViewBindingAdapter {
@BindingAdapter(value = {"android:items", "android:itemTemplate", "android:dropDownItemTemplate"}, requireAll = false)
public static <T> void setListAdapter(AbsListView view, List<T> items, @LayoutRes int itemTemplateLayout, @LayoutRes int dropDownItemTemplateLayout) {
final ListAdapter oldAdapter = view.getAdapter();
if (oldAdapter instanceof ObservableListAdapter) {
((ObservableListAdapter<T>) oldAdapter).setParams(items, itemTemplateLayout, dropDownItemTemplateLayout);
} else {
view.setAdapter(new ObservableListAdapter<>(view.getContext(), items, itemTemplateLayout, dropDownItemTemplateLayout));
}
}
@BindingAdapter(value = {"android:items", "android:itemTemplate", "android:dropDownItemTemplate"}, requireAll = false)
public static <T> void setListAdapter(AbsListView view, T[] items, @LayoutRes int itemTemplateLayout, @LayoutRes int dropDownItemTemplateLayout) {
setListAdapter(view, items != null ? Arrays.asList(items) : null, itemTemplateLayout, dropDownItemTemplateLayout);
}
@BindingAdapter(value = {"android:items", "android:itemTemplate", "android:dropDownItemTemplate"}, requireAll = false)
public static <T> void setListAdapter(AbsListView view, int[] items, @LayoutRes int itemTemplateLayout, @LayoutRes int dropDownItemTemplateLayout) {
setListAdapter(view, items != null ? IntStream.of(items).boxed().collect(Collectors.toList()) : null, itemTemplateLayout, dropDownItemTemplateLayout);
}
static class ObservableListAdapter<T> extends BaseAdapter {
private List<T> mList;
private int mDropDownResourceId = 0;
private int mResourceId = 0;
private final LayoutInflater mLayoutInflater;
final ObservableList.OnListChangedCallback mListChangedCallback = new ObservableList.OnListChangedCallback() {
@Override
public void onChanged(ObservableList observableList) {
notifyDataSetChanged();
}
@Override
public void onItemRangeChanged(ObservableList observableList, int i, int i1) {
notifyDataSetChanged();
}
@Override
public void onItemRangeInserted(ObservableList observableList, int i, int i1) {
notifyDataSetChanged();
}
@Override
public void onItemRangeMoved(ObservableList observableList, int i, int i1, int i2) {
notifyDataSetChanged();
}
@Override
public void onItemRangeRemoved(ObservableList observableList, int i, int i1) {
notifyDataSetChanged();
}
};
public ObservableListAdapter(Context context, List<T> list, @LayoutRes int itemTemplate, @LayoutRes int dropDownItemTemplate) {
mLayoutInflater = LayoutInflater.from(context);
setParams(list, itemTemplate, dropDownItemTemplate);
}
public void setParams(List<T> list, @LayoutRes int itemTemplate, @LayoutRes int dropDownItemTemplate) {
boolean requireNotifyChange = mResourceId != itemTemplate || mDropDownResourceId != dropDownItemTemplate || !Objects.equals(list, mList);
mResourceId = itemTemplate;
mDropDownResourceId = dropDownItemTemplate;
if (!Objects.equals(list, mList)) {
if (mList instanceof ObservableList) {
((ObservableList) mList).removeOnListChangedCallback(mListChangedCallback);
}
mList = list;
if (mList instanceof ObservableList) {
((ObservableList) mList).addOnListChangedCallback(mListChangedCallback);
}
}
if (requireNotifyChange) {
notifyDataSetChanged();
}
}
@Override
public int getCount() {
return (mList != null) ? mList.size() : 0;
}
@Override
public T getItem(int position) {
return mList != null ? mList.get(position) : null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return getViewForResource(mResourceId, position, convertView, parent);
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return getViewForResource(mDropDownResourceId, position, convertView, parent);
}
public View getViewForResource(int resourceId, int position, View convertView, ViewGroup parent) {
final ViewDataBinding binding = (convertView != null)
? DataBindingUtil.getBinding(convertView)
: DataBindingUtil.inflate(mLayoutInflater, resourceId, parent, false);
binding.setVariable(BR.viewModel, getItem(position));
return binding.getRoot();
}
}
}
第2步。声明自己的项目模板(例如WPF),并且必须声明viewModel数据类型,因为Android始终使用静态类型绑定,而WPF使用动态/反射类型绑定,请确保变量 viewModel (= WPF的DataContext)为方便起见在数据部分中声明
例如:java.io.File
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="viewModel"
type="java.io.File" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="0.2"
android:text='@{viewModel.directory ? "Folder" : "File"}'
android:textSize="20sp" />
<TextView
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@{viewModel.name}"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{viewModel.length()+ ""}'
android:textSize="20sp" />
</LinearLayout>
</layout>
第3步。将项目模板添加到ListView布局文件中,此示例列出了外部存储目录中的所有文件
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.os.Environment" />
<variable
name="viewModel"
type="com.mycompany.databindingtest.MainActivity.ViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:dropDownItemTemplate="@{@layout/file_list_item_template}"
android:itemTemplate="@{@layout/file_list_item_template}"
android:items="@{Environment.externalStorageDirectory.listFiles()}" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>