关于java:使用动态添加的元素进行数据绑定

Data-binding with dynamically added elements

我已经开始在我的新应用程序中实现Android数据绑定库。但是,我在数据动态添加元素方面遇到了一些困难。在我的POJO中,它包含的地图。这里,String是用户的id,Double是金额。我有一个用于显示单个条目的布局文件。因此,如果map包含2个元素,它将如下所示:

enter image description here

以前,我通过在循环内部扩展布局并为地图的每个项目添加LinearLayout来完成此操作。但是,现在我想用数据绑定来做这件事。

因为,Map中的元素数量可以是1到20之间的任何值,默认情况下我无法在布局文件中添加。我必须根据地图中的条目进行充气。我已经使用POJO成功实现了数据绑定而没有Map。但是,无法理解如何通过数据绑定轻松完成此操作。

那么,有没有办法直接在数据绑定(在布局文件中)或在Java代码中尽可能少的代码执行此操作?

编辑:
对于所有人来说,谁看到它是一个简单的RecyclerView,它不是。我同意RecyclerView是一个非常好的选择,当你有一个包含一些元素的列表并滚动时,这些视图将是性能优势。这里我在这个列表的上方和下方有不同类型的多个元素。我也使用了RecyclerView数据绑定,我知道它是如何工作的,但实际情况并非如此。我只想使用数据绑定来扩展布局(LinearLayout)中的多行。


由于您希望自己动态创建布局,我建议采用以下方法。目前这完全是理论上的,但我没有理由,为什么这不适合你。

考虑使用自定义属性设置Map进行绑定。

1
2
<LinearLayout ...
    app:inflateData="@{dataMap}" />

然后,您必须创建一个@BindingAdapter来处理适配器将为您执行的操作。

1
2
3
4
5
6
7
8
9
@BindingAdapter({"inflateData"})
public static void inflateData(LinearLayout layout, Map<String, Double> data) {
    LayoutInflater inflater = LayoutInflater.from(layout.getContext());
    for (Entry<String, Double> entry : data.entrySet()) {
        MyItem myItem = inflater.inflate(R.layout.my_item, layout, true);
        myItem.setKey(entry.getKey);
        myItem.setValue(entry.getValue);
    }
}

在这里,您可以扩展项目的布局并将其添加到父布局。您可以通过向布局和绑定适配器添加更多属性来进一步概括它。


这不是数据绑定的用途。这些是将数据绑定到静态定义的布局。创建或管理视图层次结构可能是可能的,但也比使用RecyclerView及其适配器更复杂。

如果您更喜欢从布局中设置数据,则可以为数据绑定库编写自定义设置器,并在此范围内创建适配器。

1
2
3
4
5
@BindingAdapter({"adapter"})
public static void bindAdapter(RecyclerView view, Map<String, Double> data) {
   RecyclerView.Adapter adapter = ...;
   view.setAdapter(adapter);
}


要以动态方式添加/删除数据,您应该使用Adapter而不是使用您的方式添加它。谷歌建议,RecycelerView在UI和内存控制方面有更好的表现。我已经制作了一些可能适合你的简单代码。

对于Adapter和绑定方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class MyOwnBindingUtil {
    public static class Holder extends RecyclerView.ViewHolder {
        private ItemBinding mItemBinding;
        public Holder(ItemBinding itemView) {
            super(itemView.getRoot());
            mItemBinding = itemView;
        }
    }
    public static class OwnAdapter extends RecyclerView.Adapter<Holder> {
        private Map<String, String> mMap;
        private List<String> keys;
        private List<Double> values;
        public OwnAdapter() {
            keys = new ArrayList<>();
            values = new ArrayList<>();
        }
        public void add(String key, Double value) {
            keys.add(key);
            values.add(value);
        }
        @Override
        public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
            ItemBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item, parent, false);
            return new MyOwnBindingUtil.Holder(binding);
        }
        @Override
        public void onBindViewHolder(Holder holder, int position) {
            holder.mItemBinding.setKey(keys.get(position));
            holder.mItemBinding.setValue(String.valueOf(values.get(position)));
        }
        @Override
        public int getItemCount() {
            return keys.size();
        }
    }
    @BindingAdapter("data:map")
    public static void bindMap(RecyclerView pRecyclerView, Map<String, Double> pStringStringMap) {
        pRecyclerView.setLayoutManager(new LinearLayoutManager(pRecyclerView.getContext()));
        OwnAdapter lAdapter = new OwnAdapter();
        for (Map.Entry<String, Double> lStringStringEntry : pStringStringMap.entrySet()) {
            lAdapter.add(lStringStringEntry.getKey(), lStringStringEntry.getValue());
        }
        pRecyclerView.setAdapter(lAdapter);
    }
}

如果您坚持使用Map而不是list来存储数据,则会出现一些问题,因为Map未编入索引但适配器会根据数据集的索引获取数据。

https://www.mkyong.com/java8/java-8-convert-map-to-list/

如何在Java中将Map转换为List?

如何在Java中将HashMap转换为List?

在xml中,您可以将地图设置为recyclerview,并且可以在xml中设置数据集。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:data="http://schemas.android.com/tools"
    >


    <data>

        <import type="java.lang.String"/>

        <import type="java.util.Map"/>

        <variable
            name="map"
            type="Map&lt;String, String&gt;"/>
    </data>

    <LinearLayout

        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        >

        <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            data:map="@{map}"/>

    </LinearLayout>
</layout>

在您的活动代码中

1
2
3
4
5
    Map<String, String> lStringStringMap = new HashMap<>();
    lStringStringMap.put("A","A1");
    lStringStringMap.put("B","B1");
    lStringStringMap.put("C","C1");
    mBinding.setMap(lStringStringMap);