在 Kotlin 中使用 Android 数据绑定初始化 RecyclerView 会引发错误。我究竟做错了什么?

Zel*_*mec 2 android android-fragments kotlin android-recyclerview android-databinding

描述

我正在尝试使用 android 数据绑定在 Kotlin 中设置一个带有 RecyclerView 的 Android 屏幕。我有一个包含片段的活动,该片段包含我使用数据绑定初始化的 RecyclerView。

问题是,当我尝试设置我的回收器视图的布局管理器时,应用程序抛出一个 IllegalStateException 抱怨指定的孩子(我假设这意味着 RecyclerView 或 LayoutManager)已经有一个父级,我需要运行 removeView( )。我尝试从 RecyclerView 中删除所有视图,但无济于事。

这是我的活动:

class HomeActivity : BaseActivity() {

    private lateinit var mBinding: ActivityHomeBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_home)

        if(savedInstanceState != null){
            return
        }

        val fragment = HomeFragment.newInstance()
        supportFragmentManager.beginTransaction().add(R.id.home_fragment_container, fragment).commit()
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的片段:

class HomeFragment : BaseFragment() {

    private lateinit var mBinding: FragmentHomeBinding
    private lateinit var mRecyclerView: RecyclerView

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val testList = listOf("TEST TITLE")
        mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_home, container, false)
        mRecyclerView = mBinding.homeRecyclerview
        mRecyclerView.adapter = HomeOptionsAdapter(testList, View.OnClickListener { Log.d("[onCreateView]:", "I've been clicked") })
        mRecyclerView.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
        return mBinding.root
    }

    companion object {
        fun newInstance(): HomeFragment {
            val fragment = HomeFragment()
            return fragment
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的片段布局:

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="joseph.kinler.mtgutility.fragments.HomeFragment">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/home_recyclerview"
            android:scrollbars="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

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

当我尝试运行它时,当我尝试设置 LayoutManager 时,我的 recyclerview 出现错误:

java.lang.IllegalStateException: 指定的孩子已经有一个父母。您必须首先在孩子的父级上调用 removeView()。

所以我的问题是:我做错了什么?我是否错误地使用了数据绑定?Kotlin 是不是在数据绑定方面表现不佳?任何帮助或反馈将不胜感激。

编辑:

这是错误的完整堆栈跟踪:

06-14 21:34:44.876 3631-3631/com.kinler.mtgutility E/AndroidRuntime:致命异常:主进程:com.kinler.mtgutility,PID:3631 java.lang.IllegalStateException:指定的孩子已经有父母了。您必须首先在孩子的父级上调用 removeView()。在 android.view.ViewGroup.addViewInner(ViewGroup.java:4885) 在 android.view.ViewGroup.addView(ViewGroup.java:4716) 在 android.view.ViewGroup.addView(ViewGroup.java:

编辑2:

昨晚我用日志做了更多的调试,看起来我的 recyclerView 正在正确初始化,适配器正在运行,它将创建一个 ViewHolder 并在抛出错误之前绑定它。我仍然不确定确切的错误发生在哪里,但我计划将日志语句添加到我的应用程序流中的更多位置,以找出问题发生的位置。

编辑3:

这是我的适配器代码:

class HomeOptionsAdapter(val items:List<String>, val itemListener: View.OnClickListener): RecyclerView.Adapter<HomeCardViewHolder>() {

    private val TAG = HomeOptionsAdapter::class.java.simpleName

    override fun onBindViewHolder(viewHolder: HomeCardViewHolder, position: Int) = viewHolder.bind(items[position], itemListener)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeCardViewHolder {
        Log.d(TAG, "[onCreateViewHolder]")
        val inflater = LayoutInflater.from(parent.context)
        val binding = HomeCardBinding.inflate(inflater, parent, false)
        return HomeCardViewHolder(binding.homeCardTitle, binding)
    }

    override fun getItemCount(): Int = items.size
}
Run Code Online (Sandbox Code Playgroud)

还有我的视图持有者代码:

class HomeCardViewHolder constructor(itemView: View, binding: HomeCardBinding): RecyclerView.ViewHolder(itemView) {

    private val TAG = HomeCardViewHolder::class.java.simpleName
    private var mBinding: HomeCardBinding

    init {
        mBinding = binding
    }

    fun bind(title: String, listener: View.OnClickListener) {
        Log.d(TAG, "[bind]")
        mBinding.homeCardTitle.text = title
        Log.d(TAG, title)
        mBinding.homeCardTitle.setOnClickListener(listener)
    }
}
Run Code Online (Sandbox Code Playgroud)

tyn*_*ynn 5

您正在使用HomeCardViewHolder(binding.homeCardTitle, binding). 该itemView参数应该是根视图。从名字来看,homeCardTitle可能是绑定本身层次结构中的一个视图。因此它已经有一个父级并且不能被添加到回收者视图中。

因此,改为使用HomeCardViewHolder(binding.root, binding).

或者只为视图持有者提供绑定。

class HomeCardViewHolder constructor(val binding: HomeCardBinding): RecyclerView.ViewHolder(binding.root) {

    private val TAG = HomeCardViewHolder::class.java.simpleName

    fun bind(title: String, listener: View.OnClickListener) {
        Log.d(TAG, "[bind]")
        binding.homeCardTitle.text = title
        Log.d(TAG, title)
        binding.homeCardTitle.setOnClickListener(listener)
    }
}
Run Code Online (Sandbox Code Playgroud)