Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/192.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
数据绑定Android回收器视图_Android_Android Databinding - Fatal编程技术网

数据绑定Android回收器视图

数据绑定Android回收器视图,android,android-databinding,Android,Android Databinding,我使用android数据绑定,下面是我用来设置变量的类 public class DayTemp extends BaseObservable implements Serializable { @SerializedName("dt") long date; @SerializedName("pressure") double pressure; @SerializedName("humidity") long humidity; @S

我使用android数据绑定,下面是我用来设置变量的类

public class DayTemp extends BaseObservable implements Serializable {

    @SerializedName("dt")
    long date;
    @SerializedName("pressure")
    double pressure;
    @SerializedName("humidity")
    long humidity;
    @SerializedName("temp")
    Temp temp;
    @SerializedName("weather")
    ArrayList<Weather> weathers;
    @SerializedName("speed")
    double speed;
    @SerializedName("deg")
    double deg;
    @SerializedName("clouds")
    double clouds;

    @Bindable
    public long getDate() {
        return date;
    }

    public void setDate(long date) {
        this.date = date;
        notifyPropertyChanged(BR.date);
    }

    @Bindable
    public double getPressure() {
        return pressure;
    }

    public void setPressure(double pressure) {
        this.pressure = pressure;
        notifyPropertyChanged(BR.pressure);
    }

    @Bindable
    public long getHumidity() {
        return humidity;
    }

    public void setHumidity(long humidity) {
        this.humidity = humidity;
        notifyPropertyChanged(BR.humidity);
    }

    @Bindable
    public Temp getTemp() {
        return temp;
    }

    public void setTemp(Temp temp) {
        this.temp = temp;
        notifyPropertyChanged(BR.temp);
    }

    @Bindable
    public ArrayList<Weather> getWeathers() {
        return weathers;
    }

    public void setWeathers(ArrayList<Weather> weathers) {
        this.weathers = weathers;
        notifyPropertyChanged(BR.weathers);
    }

    @Bindable
    public double getSpeed() {
        return speed;
    }

    public void setSpeed(double speed) {
        this.speed = speed;
        notifyPropertyChanged(BR.speed);
    }

    @Bindable
    public double getDeg() {
        return deg;
    }

    public void setDeg(double deg) {
        this.deg = deg;
        notifyPropertyChanged(BR.deg);
    }

    @Bindable
    public double getClouds() {
        return clouds;
    }

    public void setClouds(double clouds) {
        this.clouds = clouds;
        notifyPropertyChanged(BR.clouds);
    }
}
布局文件:

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

    <data>

        <import  type="com.weatherappforleftshift.currentlocation.DateUtils"/>

        <variable
            name="daytemp" type="com.weatherappforleftshift.currentlocation.model.DayTemp"/>


    </data>

           <TextView
                    android:id="@+id/weather_status"
                    android:layout_width="wrap_content"
                    android:layout_marginLeft="10dp"
                    android:layout_marginStart="10dp"
                    android:text="@{HOW TO SET TEXT HERE FROM weathers list}"
                    android:layout_height="wrap_content" />


</layout>

我想将天气类的图标和描述设置到我的recyclerview


如何在项目布局中实现这一点???

您可以查看这个github项目

我已经为recyclerview处理了数据绑定

更具体地说,以下2个文件将是感兴趣的

在虚拟机中添加:

@Bindable
public String getWeathersText() {
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < weathers.size(); i++) {
        builder.append(weathers.get(i).getText);
    }
    return builder.toString();
}
@Bindable
公共字符串getWeathersText(){
StringBuilder=新的StringBuilder();
对于(int i=0;i
在布局xml中:

<TextView
      android:id="@+id/weather_status"
      android:layout_width="wrap_content"
      android:layout_marginLeft="10dp"
      android:layout_marginStart="10dp"
      app:weathersText="@{daytemp.weathersText}"
      android:layout_height="wrap_content" />


我没有检查它,但我认为它应该有帮助…

首先,您需要在布局xml中创建“Weather”类的变量/实例

<variable
        name="weatherData" type="<packageName>.Weather"/>

有很多方法可以剥这只猫的皮。但是您特别提到绑定,那么让我们用正确的方法来做:)

您将需要一些东西,但不要担心,其中大部分是一次性锅炉板,您可以在每个recyclerview上反复使用。这就是它的美妙之处

1) 布局中的RecyclerView

2) RecyclerView的通用绑定适配器

3) 用于转换类型和设置的JMVStatic适配器

4) 用于与RecyclerView适配器通信的接口

差不多就这么多了,让我们进入代码。 顺便说一句,如果你不想理解它,你几乎可以复制和粘贴,虽然它可以做更多的事情,然后你需要。还有其他处理单击事件的方法。您可以将它们嵌套到行布局文件中,而不会产生任何问题

步骤1: 接口类

    interface IBindingRecyclerView<T> {

    /////////////////////////////////////////////////////////////////
    // EXTERNAL METHODS
    /////////////////////////////////////////////////////////////////
    fun getRowLayoutResourceId(): Int
    fun getBindingModelId(): Int
    fun getActionButtonResourceId(): Int
    fun onItemClick(model: T, position: Int)
    fun onItemLongClick(model: T, position: Int)
    fun onActionItemClick(model: T, position: Int, holder: BindingRecyclerViewAdapter.BindingHolder)

}
}

可重复使用的物品包括:

  • 接口
  • jvm静态适配器
  • 回收器视图适配器
  • 垂直装饰器
实际上,您只是在实现接口,以可观察列表的形式提供列表,在onCreate中设置变量,并将这两行放在xml中,然后重复:)


快乐编码。希望这有帮助。

@pskink我会处理好的。。。thnx@tynn仅要求数据绑定,无法从类访问arraylist如何在此处从weathers列表设置文本是无效的信息。至少提供代码,说明如何将
天气
列表转换为
字符序列
。一个实用程序方法或其他东西…天气列表是带有文本和图标的自定义arraylist,它位于DayTemp类中,这是我的recyclerview项的根类。我尝试像这样访问该列表@{DayTemp.weathers.get(),但不能访问天气中的精确元素。考虑使用它。首先输入THNX,但我想访问它。现在我正在做这个@ { TayTim.WeeSt.GET()},但是我想得到与Weikes相关的数据,WeeStices是一个ARARYLIST。我通过使用两个数据变量THNX来解决它。
bindind.setWeatherData(whetherList.get(position));
    interface IBindingRecyclerView<T> {

    /////////////////////////////////////////////////////////////////
    // EXTERNAL METHODS
    /////////////////////////////////////////////////////////////////
    fun getRowLayoutResourceId(): Int
    fun getBindingModelId(): Int
    fun getActionButtonResourceId(): Int
    fun onItemClick(model: T, position: Int)
    fun onItemLongClick(model: T, position: Int)
    fun onActionItemClick(model: T, position: Int, holder: BindingRecyclerViewAdapter.BindingHolder)

}
   object BindingAdapterMethods {

    /////////////////////////////////////////////////////////////////
    // MEMBERS
    /////////////////////////////////////////////////////////////////
    private var TAG: String = SSGlobals.SEARCH_STRING + "BindingAdapterMethods"



    /////////////////////////////////////////////////////////////////
    // METHODS
    /////////////////////////////////////////////////////////////////
    /**
     * This makes sure that the interface and observable list is set in the recyclerView's adapter. If the adapter is null,
     * then a new one is created.
     * @param view
     * @param iBindingRecyclerView
     * @param list
     */
    @JvmStatic
    @BindingAdapter(value = ["bindRcvInterface", "bindRcvList", "bindRcvPlusInterface"], requireAll = false)
    fun setBindingRecyclerViewProperties(view: RecyclerView, iBindingRecyclerView: IBindingRecyclerView<*>, list: ObservableArrayList<*>?, iBindingRecyclerViewPlus: IBindingRecyclerViewPlus<*>? = null) {
        if (view.adapter == null) {
            val layoutManager = LinearLayoutManager(view.context)
            view.layoutManager = layoutManager
            view.invalidateItemDecorations()
            view.addItemDecoration(VerticalItemDecoration(0))
            view.adapter = BindingRecyclerViewAdapter<Any?>()
        }

        val adapter = view.adapter as BindingRecyclerViewAdapter<*>
        adapter.setIBindingRecyclerView(iBindingRecyclerView, iBindingRecyclerViewPlus)
        if(list != null) {
            adapter.setList(list)
        }
    }
}
class MyListFragment : BaseFragment(), IBindingRecyclerView<YourListModelType> {
   /////////////////////////////////////////////////////////////////
   // MEMBERS
   /////////////////////////////////////////////////////////////////
   private lateinit var mBinding: FragmentYourItemListBinding
   private var mYourItemModelList : ObservableArrayList<YourListModelType> = ObservableArrayList()


   /////////////////////////////////////////////////////////////////
   // LIFE CYCLE OVERRIDES
   /////////////////////////////////////////////////////////////////
   override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
       mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_your_item_list, container, false)
       mBinding.fragment = this
       mBinding.iBindingRecyclerView = this
       return mBinding.root
   }
   override fun onResume() {
       super.onResume()
       fillYourListOfItems()
   }

    /////////////////////////////////////////////////////////////////
    // PROPERTIES
    /////////////////////////////////////////////////////////////////
    fun getYourListItemModelList() : ObservableArrayList<YourListItemModelType> {
        return mYourItemModelList
    }


    /////////////////////////////////////////////////////////////////
    // IBINDINGRECYCLERVIEW OVERRIDES
    /////////////////////////////////////////////////////////////////
    override fun getRowLayoutResourceId(): Int {
        return R.layout.row_your_layout_file
    }
    override fun getBindingModelId(): Int {
        return BR.YourListModelType //defined in the xml coming up next
    }
    override fun getActionButtonResourceId(): Int {
        return -1 //if you aren't using, just return -1 or remove from interface
    }
    override fun onItemClick(model: YourListModelType, position: Int) {
        //handle the click of your item, launch a detail activity, whatever you need
    }
    override fun onItemLongClick(model: YourListModelType, position: Int) {
        //same as above, but if not using, you can remove from interface
    }
    override fun onActionItemClick(model: YourListModelType, position: Int, holder: BindingRecyclerViewAdapter.BindingHolder) {
        //if not using, you can remove from interface
    }


}
    <data>
        <variable name="fragment" type="com.yourpath.fragments.MyListFragment" />
        <variable name="iBindingRecyclerView" type="com.yourpath.interfaces.IBindingRecyclerView"/>
    </data>
class BindingRecyclerViewAdapter<T> : RecyclerView.Adapter<BindingRecyclerViewAdapter.BindingHolder>(), View.OnClickListener, View.OnLongClickListener {

    /////////////////////////////////////////////////////////////////
    // MEMBERS
    /////////////////////////////////////////////////////////////////
    private val MODEL_TAG = -124
    private val MODEL_POSITION_TAG = -125
    private var mRowLayoutResourceId: Int = 0
    private var mBindingModelId: Int = 0
    private var mActionButtonId: Int = 0
    private var mHasActionButton: Boolean = false
    private var mList: ObservableArrayList<*>? = null
    private lateinit var mIBindingRecyclerView: IBindingRecyclerView<T>
    private var mIBindingRecyclerViewPlus: IBindingRecyclerViewPlus<T>? = null


    /////////////////////////////////////////////////////////////////
    // PROPERTIES
    /////////////////////////////////////////////////////////////////
    /**
     * This is now how the interface needs to be set. This is taken care of in the @BindingAdapter
     * method "bind:rcvInterface" (BindingAdapterMethods). I also decided to take care of setting the
     * rowLayoutResourceId here, more as a "might as well" sort of thing, but also preventing the chance
     * of a null ref exception if we were to use mIBindingRecyclerView.getRowLayoutResourceId() and
     * mIBindingRecyclerView was null. Same goes for bindingModelId.
     * @param iBindingRecyclerView
     */
    fun setIBindingRecyclerView(iBindingRecyclerView: IBindingRecyclerView<*>, iBindingRecyclerViewPlus: IBindingRecyclerViewPlus<*>? = null) {
        mIBindingRecyclerView = iBindingRecyclerView as IBindingRecyclerView<T>
        mRowLayoutResourceId = iBindingRecyclerView.getRowLayoutResourceId()
        mBindingModelId = iBindingRecyclerView.getBindingModelId()
        mActionButtonId = iBindingRecyclerView.getActionButtonResourceId()
        mHasActionButton = mActionButtonId > 0
        mIBindingRecyclerViewPlus = iBindingRecyclerViewPlus as IBindingRecyclerViewPlus<T>?
    }
    /**
     * This is how the list is set and any changes made will be notified here. If notifyDataSetChanged()
     * is not called here, then the view will not be updated with the list changes. Setting the list gets
     * taken care of in the @BindingAdapter method "bind:rcvList" (BindingAdapterMethods). Anytime the list
     * changes in the activity/fragment, it will trigger the "bind:rcvList" method, and that will call
     * setList(), thus updating the list and notifying data set changed which updates the view properly.
     * @param list
     */
    fun setList(list: ObservableArrayList<*>) {
        mList = list
        notifyDataSetChanged()
    }


    /////////////////////////////////////////////////////////////////
    // BASE CLASS OVERRIDES
    /////////////////////////////////////////////////////////////////
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingHolder {
        val inflater = LayoutInflater.from(parent.context)
        val viewDataBinding = DataBindingUtil.inflate<ViewDataBinding>(inflater, mRowLayoutResourceId, parent, false)
        return BindingHolder(viewDataBinding)
    }
    override fun onBindViewHolder(holder: BindingHolder, position: Int) {
        val model = mList!![position]
        holder.binding.setVariable(mBindingModelId, model)
        holder.binding.root.setTag(MODEL_TAG, model)
        holder.binding.root.setTag(MODEL_POSITION_TAG, position)
        holder.binding.root.setOnClickListener(this)
        holder.binding.root.setOnLongClickListener(this)

        if(mIBindingRecyclerViewPlus != null){
            mIBindingRecyclerViewPlus?.onRowBinding(model as T, position, holder)
        }

        if (mHasActionButton) {
            val btnAction = holder.binding.root.findViewById<View>(mActionButtonId)
            btnAction.setTag(MODEL_TAG, model)
            btnAction.setTag(MODEL_POSITION_TAG, position)
            onActionClick(btnAction, holder)
        }

        holder.binding.executePendingBindings()
    }
    override fun getItemCount(): Int {
        return if (mList == null) 0 else mList!!.size
    }


    ////////////////////////////////////////////////////////////////
    // CLICK LISTENERS
    ////////////////////////////////////////////////////////////////
    override fun onClick(v: View) {
        val model = v.getTag(MODEL_TAG) as T
        val position = v.getTag(MODEL_POSITION_TAG) as Int
        mIBindingRecyclerView.onItemClick(model, position)
    }
    override fun onLongClick(v: View): Boolean {
        val model = v.getTag(MODEL_TAG) as T
        val position = v.getTag(MODEL_POSITION_TAG) as Int
        mIBindingRecyclerView.onItemLongClick(model, position)
        return true
    }
    fun onActionClick(btnAction: View, holder: BindingHolder) {
        btnAction.setOnClickListener {
            val model = btnAction.getTag(MODEL_TAG) as T
            val position = btnAction.getTag(MODEL_POSITION_TAG) as Int
            mIBindingRecyclerView.onActionItemClick(model, position, holder)
        }
    }


    ////////////////////////////////////////////////////////////////
    // SCOPED CLASSES
    ////////////////////////////////////////////////////////////////
    class BindingHolder(var binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root)

}
    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:paddingStart="@dimen/dp_20"
        android:paddingEnd="@dimen/dp_20"
        app:bindRcvInterface="@{iBindingRecyclerView}"
        app:bindRcvList="@{fragment.getYourListItemModelList}"/>
class VerticalItemDecoration (private var spacingInPx: Int) : RecyclerView.ItemDecoration() {

/*///////////////////////////////////////////////////////////////
// ITEM DECORATION OVERRIDES
*////////////////////////////////////////////////////////////////
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
    outRect.bottom = spacingInPx
}