使用android中的数据绑定检测回收器视图中的onClick

Dev*_*ath 10 android android-recyclerview android-databinding

  1. 我正在参考用于数据绑定的vogella-tutorial
  2. 我想做的是:使用dataBinding检测每个Item的回收器视图行中的onClick的最佳方法是什么

activity_second.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="temp"
            type="com.vogella.android.databinding.TemperatureData" />
        <variable
            name="presenter"
            type="com.vogella.android.databinding.MainActivityPresenter"/>
    </data>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical" />
</layout>
Run Code Online (Sandbox Code Playgroud)

rowlayout.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="obj"
            type="com.vogella.android.databinding.TemperatureData"
            />
    </data>

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="?android:attr/listPreferredItemHeight"
        android:padding="6dip"
        >

        <ImageView
            android:id="@+id/icon"
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:layout_alignParentBottom="true"
            android:layout_alignParentTop="true"
            android:layout_marginRight="6dip"
            android:contentDescription="TODO"
            android:src="@drawable/ic_listentry"
            />

        <TextView
            android:id="@+id/secondLine"
            android:layout_width="fill_parent"
            android:layout_height="26dip"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_toRightOf="@id/icon"
            android:ellipsize="marquee"
            android:text="@{obj.location}"
            android:textSize="12sp"
            android:maxLines="1"
        />

        <TextView
            android:id="@+id/firstLine"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_above="@id/secondLine"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_alignWithParentIfMissing="true"
            android:layout_toRightOf="@id/icon"
            android:gravity="center_vertical"
            android:text="@{obj.celsius}"
            android:textSize="16sp"
            />

    </RelativeLayout>

</layout>
Run Code Online (Sandbox Code Playgroud)

MyAdapter.java

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
        private List<TemperatureData> data;

        // Provide a reference to the views for each data item
        // Complex data items may need more than one view per item, and
        // you provide access to all the views for a data item in a view holder
        public class MyViewHolder extends RecyclerView.ViewHolder {
                // each data item is just a string in this case
                private final ViewDataBinding binding;

                public MyViewHolder(ViewDataBinding binding) {
                        super(binding.getRoot());
                        this.binding = binding;
                }
                public void bind(Object obj) {
                       binding.setVariable(BR.obj,obj);
                       binding.executePendingBindings();
                }
        }

        // Provide a suitable constructor (depends on the kind of dataset)
        public MyAdapter(List<TemperatureData> myDataset) {
                data = myDataset;
        }

        // Create new views (invoked by the layout manager)
        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                // create a new view
                LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
                ViewDataBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.rowlayout, parent, false);
                // set the view's size, margins, paddings and layout parameters
                return new MyViewHolder(binding);
        }

        // Replace the contents of a view (invoked by the layout manager)
        @Override
        public void onBindViewHolder(MyViewHolder holder, int position) {
                final TemperatureData temperatureData = data.get(position);
                holder.bind(temperatureData);

        }

        // Return the size of your dataset (invoked by the layout manager)
        @Override
        public int getItemCount() {
            return data.size();
        }

}
Run Code Online (Sandbox Code Playgroud)

MyAdapter.java

public class MyAdapter extends MyBaseAdapter {

    List<TemperatureData> data;

    // Provide a suitable constructor (depends on the kind of dataset)
    public MyAdapter(List<TemperatureData> myDataset) {
        data = myDataset;
    }
    @Override
    public Object getDataAtPosition(int position) {
        return data.get(position);
    }

    @Override
    public int getLayoutIdForType(int viewType) {
        return R.layout.rowlayout;
    }

    @Override
    public int getItemCount() {
        return data.size();
    }
}
Run Code Online (Sandbox Code Playgroud)

Rob*_* J. 8

不知道您是否已经找到解决方案,但是我设法很容易地做到了。

1)修改onCreateViewHolder方法如下:

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    // create a new view
    LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
    ViewDataBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.rowlayout, parent, false);

    MainActivityPresenter presenter = new MainActivityPresenter(this, parent.getContext());
    binding.setVariable(BR.presenter,presenter);

    // set the view's size, margins, paddings and layout parameters
    return new MyViewHolder(binding);
}
Run Code Online (Sandbox Code Playgroud)

2)使MyAdapter得以实现,MainActivityContract.View因此最终如下所示:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> implements MainActivityContract.View

3)在内部实施必要的方法MyAdapter;例如:

@Override
public void showData(TemperatureData data) {
    String clickedItemCelsius = data.getCelsius();
}
Run Code Online (Sandbox Code Playgroud)

4)将Presenter变量添加到您的行布局文件中:

    <variable
        name="presenter"
        type="com.mvvm.ViewModels.MainActivityPresenter"/>
Run Code Online (Sandbox Code Playgroud)

5)最后,将您的onClick事件挂在RelativeLayout下:

<RelativeLayout
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:padding="6dip"
    android:onClick="@{() -> presenter.onShowData(obj)}"
    >
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你!

  • 这是造成内存泄漏的好方法,viewHolder 应尽可能保持轻量级,因为它将在用户滚动时重新创建。应该只在 viewholder 的构造函数中传递 onClickListener (5认同)
  • MainActivityPresenter是什么? (2认同)