2016-09-05 5 views
3

Я начал внедрять библиотеку привязки данных Android к моему новому приложению. Но у меня возникают некоторые трудности с динамически добавленными данными. В моем POJO он содержит карту <String,Double>. Здесь String - это идентификатор пользователя, а Double - это сумма. У меня есть файл макета для отображения отдельной записи. Таким образом, если карта содержит 2 элемента, то это будет выглядеть следующим образом:Связывание данных с динамически добавленными элементами

enter image description here

Раньше я делал это надувание макетов внутри цикла и добавления к LinearLayout для каждого элемента карты. Но теперь я хочу сделать это с привязкой данных.

Как, количество элементов в Map может быть от 1 до 20, я не могу добавить в файл макета по умолчанию. Я должен раздуваться в соответствии с записями на карте. Я успешно применил привязку данных к POJO без Map. Но, неспособный понять, как это можно сделать с привязкой данных легко.

Итак, есть ли способ сделать это непосредственно в привязке данных (в файле макета) или с минимальным кодом в Java-коде?

Edit: Для всех, кто видит, что это просто RecyclerView, это не так. Я согласен RecyclerView - очень хороший выбор, когда у вас есть список с некоторыми элементами и прокрутка, которые будут полезны для производительности. Здесь у меня есть несколько элементов разных типов выше и ниже этого списка. Я также использовал RecyclerView с привязкой данных, и я знаю, как это работает, но здесь это не так. Я просто хочу раздуть несколько строк внутри макета (LinearLayout), используя привязку данных.

+0

Вы попробовали 'RecyclerView'? –

+0

Мне не нужен RecyclerView, в большинстве случаев будет до 5-7 элементов. RecyclerView будет полезен, когда есть много элементов с прокруткой – kirtan403

+0

В вопросе вы сказали от 1 до 20. И если в случае, число элементов увеличилось до> 7, чтобы быть в безопасности, я предлагаю использовать 'RecyclerView'. И ваша проблема с привязкой будет решена. Если вы добавили все элементы в «LinearLayout» программно и на поворот экрана, вам нужно прокрутить, чтобы увидеть все элементы, которые могут вызвать проблемы с памятью. –

ответ

5

Поскольку вы предпочитаете создавать макет динамически себя, я бы предложить следующий подход. В настоящий момент это полностью теоретический, но я не вижу причины, почему это не должно работать для вас.

Учитывая, что вы установили Map с настраиваемым атрибутом для привязки.

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

Затем вы должны создать @BindingAdapter для обработки, что адаптер будет делать для вас.

@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); 
    } 
} 

Здесь вы раздуваете макет для элемента и добавляете его в родительский макет. Вы можете обобщить его еще больше, добавив больше атрибутов в макет и адаптер привязки.

+0

Отлично! Это должно сработать. Я собираюсь отдать это. Благодаря! – kirtan403

1

Это не то, для чего используются привязки данных. Они предназначены для привязки данных к статически определенной компоновке. Возможно создание или управление иерархиями представлений, но также намного сложнее, чем просто использование RecyclerView с его адаптерами.

Если вам нравится просто установить данные из макета, вы можете написать Custom Setters для библиотеки привязки данных и вместо этого создать адаптер в этой области.

@BindingAdapter({"adapter"}) 
public static void bindAdapter(RecyclerView view, Map<String, Double> data) { 
    RecyclerView.Adapter adapter = ...; 
    view.setAdapter(adapter); 
} 
+0

Да, я знаю, что он используется для статически заданного макета. В моем макете я связываю много свойств выше и ниже этого небольшого списка, используя привязку данных. Но, только для этой части я застрял. И ничего не нашел, как это сделать. Но, я думаю, здесь нет необходимости в просмотре ресайклера. – kirtan403

1

Для того, чтобы данные, которые должны быть добавлены/удалены в динамическом пути, вы должны использовать Adapter вместо ее нужно добавить свой путь. Как было предложено google, RecycelerView имеют лучшую производительность в пользовательском интерфейсе и управлении памятью. Я сделал простой код, который может подойти вам.

Для Адаптер и метод связывания.

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); 
    } 
} 

Существует некоторая проблема, если вы настаиваете, чтобы использовать карту вместо списка для данных, так как Карта не индексируется но адаптер получает данные на основе индекса набора данных.

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

How to convert a Map to List in Java?

How does one convert a HashMap to a List in Java?

В вашем XML, вы можете установить карту в recyclerview и ваш набор данных может быть установлен в XML.

<?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> 

В коде активности,

Map<String, String> lStringStringMap = new HashMap<>(); 
    lStringStringMap.put("A", "A1"); 
    lStringStringMap.put("B", "B1"); 
    lStringStringMap.put("C", "C1"); 
    mBinding.setMap(lStringStringMap); 
+0

Спасибо за предложения. Я согласен, что RecyclerView очень хороший выбор, когда у вас есть список с некоторыми элементами и прокрутка этих представлений будет преимуществом производительности. Но использование RecyclerView здесь не будет хорошим выбором, так как я хочу, чтобы некоторые представления (обычно около 5-7) были встроены с множеством разных представлений выше и ниже этого списка. Я использовал привязку данных к представлениям recycler, и она просто отлично работает. Но здесь это не требуется. – kirtan403

+0

Это означает, что у вас есть binding1, binding2, binding3 ... но не более 7. И 7 привязок (если это s 7) - совершенно разные макеты. Вы хотите добавить его в один контейнер (возможно, это LinearLayout). И теперь вы хотите найти более простой способ добавить 7 разных макетов внутри одного контейнера, а не добавлять их один за другим, используя привязку данных? –

+0

Nop, не так. Позволь мне объяснить. Скажем, у меня есть POJO с такими многочисленными элементами: название, описание, владелец, created_at, created_by, modified_at, modified_by, значок, категория, тег, местоположение, ** участники **. Таким образом, с этим POJO и привязкой данных я могу легко установить все. Но эта часть «участников» - сложная карта. Для этой карты я хочу отобразить строку для каждой из них, которая довольно мала по размеру. – kirtan403

Смежные вопросы