【问题标题】:How to do latest jetpack "View binding" in adapter, bind the views?如何在适配器中进行最新的jetpack“视图绑定”,绑定视图?
【发布时间】:2020-06-14 22:23:54
【问题描述】:

如何在适配器中进行最新的jetpack“视图绑定”,以自动绑定视图。我没有使用 findVeiwById 或 Butterknife 或 Kotlin 合成?我已经使用了新的视图绑定,并且对于 Activity 和 Fragment 都可以正常工作。在 build.gradle 文件中启用 viewBinding 后,我可以看到 ActivityHomeBinding 和 FragmentHomeBinding 文件。此外,我看到使用的项目 xml 的类 ItemListBinding,即 item_list.xml。但是如何在recyclerview的适配器中使用这个文件

viewBinding {
        enabled = true
}

首页活动文件

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityHomeBinding.inflate(layoutInflater)
        setContentView(binding.root)
}

片段

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        binding = FragmentHomeBinding.inflate(inflater, container, false)
        val view = binding.root
        return view
}

基础适配器:想在这里使用视图绑定。我可以看到 ItemListBinding,但不知道如何使用它。

class BaseAdapter @Inject constructor(
    private val context: Context,
    private val picasso: Picasso
) :
    RecyclerView.Adapter<BaseAdapter.ViewHolder>() {

    private var data = ArrayList<Data>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            LayoutInflater.from(context).inflate(R.layout.item_list, parent, false)
        )
    }

    override fun getItemCount() = data.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        with(holder) {
              // TODO
        }
    }

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {

        @BindView(R.id.tvMovieName)
        lateinit var nameTV: TextView

        @BindView(R.id.imageView)
        lateinit var bannerImage: ImageView

        init {
            ButterKnife.bind(this@ViewHolder, view)
        }
    }

    fun setData(serverData: ArrayList<Data>) {
        data = serverData
        notifyDataSetChanged()
    }
}

【问题讨论】:

  • 嗨@DevAnuragGarg 一直希望你做得好,我创建了一篇博客文章,深入介绍了所有可能的用例的视图绑定,也包括适配器类,从这里结帐??? ?Androidbites|ViewBinding

标签: android kotlin android-jetpack android-viewbinding


【解决方案1】:

您可以使用 ViewBinding 的静态 bind 方法从现有布局创建绑定。将其作为属性添加到 viewholder:

class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
   val binding = ItemListBinding.bind(view)
}

那么就可以通过binding字段访问所有视图,例如:

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    with(holder) {
          // TODO
          binding.tvMovieName.text = data[position].title
          binding.imageView.setDrawableImage(data[position].image)
    }
}

【讨论】:

  • 是的@Pawel,方法之一。好兄弟
  • onBindViewHolder 方法中我找不到binding 知道为什么吗?
  • @MaulikDodia 仔细检查适配器的泛型类型参数
  • 我们应该在某个地方解绑吗
  • @Nikola 不需要明确的绑定。只有在 Fragments 中需要它的地方,因为它们具有复杂(且令人困惑)的生命周期,这使它们能够比自己的视图寿命更长,甚至可以经历多个视图的创建/销毁。
【解决方案2】:

找到另一个解决它

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = ItemListBinding.inflate(LayoutInflater.from(context), parent, false)
        return MovieViewHolder(binding)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        with(holder) {

            with(moviesData[position]) {
                binding.tvMovieName.text = title
            }
        }
    }
}

class MovieViewHolder(val binding: ItemMovieBinding) : RecyclerView.ViewHolder(binding.root)

【讨论】:

    【解决方案3】:

    与您通常的做法相比,没有什么真正改变。

    class DataAdapter(
        private val context: Context,
        private val picasso: Picasso
    ) : RecyclerView.Adapter<DataAdapter.ViewHolder>() {
        private var dataList: List<Data> = Collections.emptyList()
    
        override fun getItemCount() = dataList.size
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder = ViewHolder(
            LayoutInflater.from(context).inflate(R.layout.item_list, parent, false)
        )
    
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            holder.bind(dataList[position])
        }
    
        fun setData(dataList: List<Data>) {
            this.dataList = dataList
            notifyDataSetChanged()
        }
    
        class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
            private val binding = ItemListBinding.bind(view)   
    
            fun bind(data: Data) {
                with(binding) {
                    // TODO
                    nameTV.text = data.name
                    bannerImage.loadWithPicasso(picasso, data.imageUrl)
                }
            }
        }
    }
    

    【讨论】:

    • 嗨戈巴尔!我看到你在视图持有者实例的范围内做了绑定,这意味着绑定变量只有在视图持有者实例被销毁时才会被释放? (这会发生在 isRecycled 回调上吗?我不知道视图持有者何时被销毁..),如果我们确实在onCreateViewHolder 中膨胀并将绑定传递给视图持有者,我们就不必被同样的困扰?我想知道应该首选哪一个,我在我的文章中所做的对吗? chetangupta.net/viewbinding
    • 你可以直接传递view: View并使用.bind,只要它存储为val,或者你也可以直接传递ItemListBinding,它们的行为是等效的。这里的示例主要是为了“最小化入侵”,您也可以在适配器中使用.inflate 绑定。在大多数情况下,我更喜欢.bind(),但这只是我,我不会说这是“反模式”
    • 所以我们只添加了private val binding = ItemListBinding.bind(containerView)with(binding){ // code } .btw 我的代码fun bindItem(item: DatasItem, listener: (DatasItem) -&gt; Unit) { } 使用LayoutContainer 我同意你的观点,我们有相似/相同的代码,很好。
    【解决方案4】:

    我在RecyclerView适配器类中找到了使用View Binding的最简单方法

    class MediaRecyclerViewAdapter: RecyclerView.Adapter<MediaRecyclerViewAdapter.MediaViewHolder>() {
    
    
    lateinit var list: List<String>
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MediaViewHolder {
        val binding = CardviewItemsRecyclerviewBinding.inflate(LayoutInflater.from(parent.context),parent,false)
        return MediaViewHolder(binding)
    }
    
    override fun onBindViewHolder(holder: MediaViewHolder, position: Int) {
    
        holder.binding.mediaHeadingTextView.text = "Hello"
    
    }
    
    override fun getItemCount(): Int {
        return list.size
    }
    
    class MediaViewHolder(val binding: CardviewItemsRecyclerviewBinding) : RecyclerView.ViewHolder(binding.root) {
    
       }
    
    }
    

    【讨论】:

      【解决方案5】:

      我发现这是最简单的:

      class RvAdapter() :
          RecyclerView.Adapter<RvAdapter.RvViewHolder>() {
              
          inner class RvViewHolder(val binding: OtherRvItemBinding) :
          RecyclerView.ViewHolder(binding.root)
              
          // Initialise view binding here.
          override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RvViewHolder {
              val binding =
                  OtherRvItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
              return RvViewHolder(binding)
          }
          
          override fun getItemCount(): Int {
              // TODO: Implement logic to return list size.
              return 0
          }
          
          // Bind view holder.
          override fun onBindViewHolder(holder: RvViewHolder, position: Int) {
              holder.binding.apply {
                      // Reference your views from here.
                      awesomeTv.text = "Hello World!"
              }
          }    
      }
      

      【讨论】:

        猜你喜欢
        • 2021-09-09
        • 1970-01-01
        • 2020-06-01
        • 2021-10-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-11
        相关资源
        最近更新 更多