美文网首页
简化你的列表Adapter

简化你的列表Adapter

作者: 码农明明 | 来源:发表于2017-09-10 19:51 被阅读1087次

    BindingCollectionAdapter

    最近看到了这个基于databing的开源库,简单翻译了一下。。。
    GitHub地址

    一 依赖安装

    compile 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter:2.2.0'
    compile 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter-recyclerview:2.2.0'

    gradle 版本需要在2.3.0以上

    二 使用

    2.1 单视图

    你需要提供items(数据list)和ItemBinding 去绑定数据,应使用ObserableList去自动更新View,当然,如果你不需要该功能也可以使用其他类型的List。
    示例ViewModel:

    public class ViewModel {
      public final ObservableList<String> items = new ObservableArrayList<>();
      public final ItemBinding<String> itemBinding = ItemBinding.of(BR.item, R.layout.item);
    }
    

    然后布局绑定viewModel的items和itemBinding,如果使用RecyclerView需要绑定一个layoutManager(看示例)

    <!-- 主布局 layout.xml -->
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <data>
          <import type="com.example.R" />
          <import type="me.tatarka.bindingcollectionadapter2.LayoutManagers" />
          <variable name="viewModel" type="com.example.ViewModel"/>
        </data>
    
        <ListView
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          app:items="@{viewModel.items}"
          app:itemBinding="@{viewModel.itemBinding}"/>
    
        <android.support.v7.widget.RecyclerView
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          app:layoutManager="@{LayoutManagers.linear()}"
          app:items="@{viewModel.items}"
          app:itemBinding="@{viewModel.itemBinding}"/>
    
        <android.support.v4.view.ViewPager
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          app:items="@{viewModel.items}"
          app:itemBinding="@{viewModel.itemBinding}"/>
    
        <Spinner
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          app:items="@{viewModel.items}"
          app:itemBinding="@{viewModel.itemBinding}"
          app:itemDropDownLayout="@{R.layout.item_dropdown}"/>
    </layout>
    

    集合中的item将会通过ItemBinding绑定到子布局中

    <!-- 子布局 item.xml -->
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <data>
          <variable name="item" type="String"/>
        </data>
    
        <TextView
          android:id="@+id/text"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:text="@{item}"/>
    </layout>
    

    2.2 多视图

    你可以重写onItemBind实现多视图布局,仍使用app:itemBinding绑定数据。

    public final OnItemBind<String> onItemBind = new OnItemBind<String>() {
      @Override
      public void onItemBind(ItemBinding itemBinding, int position, String item) {
        itemBinding.set(BR.item, position == 0 ? R.layout.item_header : R.layout.item);
      }
    };
    

    如果使用的是ListView,必须使用app:itemTypeCount="@{2}来指定视图类型数量。
    注意:如果你不做任何复杂的数据,onItemBind仍会被多次调用,如果你不需要绑定数据,应当使用ItemBinding.VAR_NONE 作为variable的id

    2.3 绑定其他变量

    可以使用itemBinding.bindExtra(BR.extra, value)来为列表的子布局添加额外的变量,示例为布局额外绑定一个点击事件

    public interface OnItemClickListener {
        void onItemClick(String item);
    }
    
    OnItemClickListener listener = ...;
    ItemBinding<Item> itemBinding = ItemBinding.<Item>of(BR.item, R.layout.item)
        .bindExtra(BR.listener, listener);
    
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <data>
          <variable name="item" type="String"/>
          <variable name="listener" type="OnItemClickListener"/>
        </data>
    
        <TextView
          android:id="@+id/text"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:onClick="@{() -> listener.onItemClick(item)}"
          android:text="@{item}"/>
    </layout>
    

    2.4 额外的Adapter配置

    2.4.1 ListView

    通过回调为每一个子布局添加id

    adapter.setItemIds(new BindingListViewAdapter.ItemIds<T>() {
      @Override
      public long getItemId(int position, T item) {
        return // Calculate item id.
      }
    });
    

    或者在布局中通过app:itemIds="@{itemIds}"来绑定。通过设置这个会使hasStableIds 返回true,从而加大内存消耗,
    可以通过回调来决定是否启用

    adapter.setItemEnabled(new BindingListViewAdapter.ItemEnabled<T>() {
      @Override
      public boolean isEnabled(int position, T item) {
        return // Calculate if item is enabled.
      }
    });
    

    或者通过app:itemEnabled="@{itemEnabled}"在布局文件中绑定

    2.4.2 ViewPager

    通过回调为子页面添加标题

    adapter.setPageTitles(new PageTitles<T>() {
      @Override
      public CharSequence getPageTitle(int position, T item) {
        return "Page Title";
      }
    });
    

    或者通过 app:pageTitles="@{pageTitles}"为ViewPage绑定标题

    2.4.3 RecyclerView

    自定义view holders

    adapter.setViewHolderFactory(new ViewHolderFactory() {
      @Override
      public RecyclerView.ViewHolder createViewHolder(ViewDataBinding binding) {
        return new MyCustomViewHolder(binding.getRoot());
      }
    });
    

    或者通过app:viewHolder="@{viewHolderFactory}" 绑定

    2.5 直接操作View

    如果你需要直接操作View,你可以通过自定义Adapter来实现

    public class MyRecyclerViewAdapter<T> extends BindingRecyclerViewAdapter<T> {
    
      @Override
      public ViewDataBinding onCreateBinding(LayoutInflater inflater, @LayoutRes int layoutId, ViewGroup viewGroup) {
        ViewDataBinding binding = super.onCreateBinding(inflater, layoutId, viewGroup);
        Log.d(TAG, "created binding: " + binding);
        return binding;
      }
    
      @Override
      public void onBindBinding(ViewDataBinding binding, int bindingVariable, @LayoutRes int layoutId, int position, T item) {
        super.onBindBinding(binding, bindingVariable, layoutId, position, item);
        Log.d(TAG, "bound binding: " + binding + " at position: " + position);
      }
    }
    

    布局文件中绑定adapter

    <android.support.v7.widget.RecyclerView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:layoutManager="@{LayoutManagers.linear()}"
      app:items="@{viewModel.items}"
      app:itemBinding="@{viewModel.itemBinding}"
      app:adapter="@{viewModel.adapter}"/>
    

    2.6 OnItemBind 助手

    这儿有一些OnItemBind的常见的实现

    itemBind = new OnItemBindClass<>()
      .map(String.class, BR.name, R.layout.item_name)
      .map(Footer.class, ItemBinding.VAR_NONE, R.layout.item_footer)
      .map(Item.class, new OnItemBind<Item>() {
                           @Override
                           public void onItemBind(ItemBinding itemBinding, int position, Item item) {
                             itemBinding.clearExtras()
                                        .set(BR.item, position == 0 ? R.layout.item_header : R.layout.item)
                                        .bindExtra(BR.extra, (list.size() - 1) == position);
                           }
                         })
      .map(Object.class, ItemBinding.VAR_NONE, R.layout.item_other);
    

    OnItemBindModel 是子布局的binding

    itemBind = new OnItemBindModel<Model>();
    
    public class Model implements ItemBindingModel {
      @Override
      public void onItemBind(ItemBinding itemBinding) {
        itemBinding.set(BR.name, R.layout.item_name);
      }
    }
    

    2.7 MergeObservableList

    用于融合两个列表

    ObservableList<String> data = new ObservableArrayList<>();
    MergeObservableList<String> list = new MergeObservableList<>()
      .insertItem("Header")
      .insertList(data)
      .insertItem("Footer");
    
    data.addAll(Arrays.asList("One", "Two"));
    // list => ["Header", "One", "Two", "Footer"]
    data.remove("One");
    // list => ["Header", "Two", "Footer"]
    

    2.8 DiffObservableList

    用于列表的更新

    DiffObservableList<Item> list = new DiffObservableList(new DiffObservableList.Callback<Item>() {
        @Override
        public boolean areItemsTheSame(Item oldItem, Item newItem) {
            return oldItem.id.equals(newItem.id);
        }
    
        @Override
        public boolean areContentsTheSame(Item oldItem, Item newItem) {
            return oldItem.value.equals(newItem.value);
        }
    });
    
    list.update(Arrays.asList(new Item("1", "a"), new Item("2", "b1")));
    list.update(Arrays.asList(new Item("2", "b2"), new Item("3", "c"), new Item("4", "d"));
    

    线程切换

    DiffObservableList<Item> list = new DiffObservableList(...);
    
    // On background thread:
    DiffUtil.DiffResult diffResult = list.calculateDiff(newItems);
    
    // On main thread:
    list.update(newItems, diffResult);
    

    相关文章

      网友评论

          本文标题:简化你的列表Adapter

          本文链接:https://www.haomeiwen.com/subject/reytsxtx.html