Android 嵌套recyclerview的问题

Android 嵌套recyclerview的问题,android,performance,android-recyclerview,kotlin,nested,Android,Performance,Android Recyclerview,Kotlin,Nested,我有一个嵌套的recyclerview,它应该与中的类似 我是根据我的想法来实现的 问题是,有时我有一个用户有数百个项目,在这种情况下,打开活动需要半分钟 我在后端有一个房间数据库,有两个链接表,其中包含外键用户和项目,我选择所有用户以获得一个用户/项目列表,其中项目是用户表中的一个列表 类userWithItems:id:Int,name:String,名单 我用适配器中的项目列表创建内部回收器视图 最好列出一个UserItems userid:Int,username:String。。。it

我有一个嵌套的recyclerview,它应该与中的类似

我是根据我的想法来实现的

问题是,有时我有一个用户有数百个项目,在这种情况下,打开活动需要半分钟

我在后端有一个房间数据库,有两个链接表,其中包含外键用户和项目,我选择所有用户以获得一个用户/项目列表,其中项目是用户表中的一个列表

类userWithItems:id:Int,name:String,名单

我用适配器中的项目列表创建内部回收器视图

最好列出一个UserItems userid:Int,username:String。。。itemid:Int,itemList,并为外部rv对其进行分组

或者,是否有可能摆脱嵌套rv,只使用一个recyclerview列表进行设计

或者,即使一个用户有许多项,是否还有其他解决方案可以使嵌套的recyclerview工作

适配器的代码:

// Code in Activity: (oncreate)

val recyclerView = findViewById<RecyclerView>(R.id.rv_users)
val adapter = UserAdapter(this)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this)

mainViewModel = ViewModelProviders.of(this, PassIntViewModelFactory(this.application, online_id)).get(MainViewModel::class.java!!)
mainViewModel.userList.observe(this, Observer {
    it?.let {
        adapter.setUserList(it)
    }
})
数据类UsersWithItems

    val id:Int, val username: String, val address, // fields from user table
    val items: List<Items>   // list of items for current user

数据类项目 val id:Int,val itemtext:String,val itemlocation:String,val image:String/。。。

//外部用户适配器

类UserAdapter内部构造函数 上下文:上下文 :RecyclerView.适配器{

private val inflater: LayoutInflater = LayoutInflater.from(context)
private var userList = emptyList<UsersWithItems>()

inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    val username: TextView = itemView.findViewById(R.id.user_name)
    val num_pos: TextView = itemView.findViewById(R.id.user_num_pos)
    val address: TextView = itemView.findViewById(R.id.user_addr)
    val rv:RecyclerView = itemView.findViewById(R.id.rv_user_items)
}


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
    val myItemView = inflater.inflate(R.layout.rv_row_user, parent, false)
    return MyViewHolder(myItemView)
}

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    val current = userList[position]
    holder.username.text="${current.user?.username}"
    holder.num_pos.text="${current.items?.size}"
    holder.address.text = "${current.user?.address}"

    val adapter = UserItemAdapter(holder.rv.context)
    adapter.setItems(current.items!!)
    holder.rv.adapter = adapter
    holder.rv.layoutManager = LinearLayoutManager(holder.rv.context,LinearLayout.VERTICAL,false)

}
internal fun setUserList(userList: List<UsersWithItems>){
    this.userList=userList
    notifyDataSetChanged()
}
override fun getItemCount() = userList.size
private val inflater: LayoutInflater = LayoutInflater.from(context)
private var itemList = emptyList<Items>()

inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    val itemtext: TextView = itemView.findViewById(R.id.item_text)
    val itemlocation:TextView = itemView.findViewById(R.id.item_location)
    val image: ImageView = itemView.findViewById(R.id.item_image)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
    val myItemView = inflater.inflate(R.layout.rv_row_user_items, parent, false)
    return MyViewHolder(myItemView)
}

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    val current = itemList[position]
    holder.itemtext.text="${current.itemtext}"
    holder.itemlocation.text = current.itemlocation
    if (current.image.length>0) {
        val image = Base64.decode(current.image, 0)
        val bitmap = BitmapFactory.decodeByteArray(image, 0, image.size)
        holder.image.setImageBitmap(bitmap)
    }
}
internal fun setItems(items: List<Items>){
    this.itemList=items
    notifyDataSetChanged()
}

override fun getItemCount() = itemList.size
}

类UserItemAdapter内部构造函数 上下文:上下文 :RecyclerView.适配器{

private val inflater: LayoutInflater = LayoutInflater.from(context)
private var userList = emptyList<UsersWithItems>()

inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    val username: TextView = itemView.findViewById(R.id.user_name)
    val num_pos: TextView = itemView.findViewById(R.id.user_num_pos)
    val address: TextView = itemView.findViewById(R.id.user_addr)
    val rv:RecyclerView = itemView.findViewById(R.id.rv_user_items)
}


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
    val myItemView = inflater.inflate(R.layout.rv_row_user, parent, false)
    return MyViewHolder(myItemView)
}

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    val current = userList[position]
    holder.username.text="${current.user?.username}"
    holder.num_pos.text="${current.items?.size}"
    holder.address.text = "${current.user?.address}"

    val adapter = UserItemAdapter(holder.rv.context)
    adapter.setItems(current.items!!)
    holder.rv.adapter = adapter
    holder.rv.layoutManager = LinearLayoutManager(holder.rv.context,LinearLayout.VERTICAL,false)

}
internal fun setUserList(userList: List<UsersWithItems>){
    this.userList=userList
    notifyDataSetChanged()
}
override fun getItemCount() = userList.size
private val inflater: LayoutInflater = LayoutInflater.from(context)
private var itemList = emptyList<Items>()

inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    val itemtext: TextView = itemView.findViewById(R.id.item_text)
    val itemlocation:TextView = itemView.findViewById(R.id.item_location)
    val image: ImageView = itemView.findViewById(R.id.item_image)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
    val myItemView = inflater.inflate(R.layout.rv_row_user_items, parent, false)
    return MyViewHolder(myItemView)
}

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    val current = itemList[position]
    holder.itemtext.text="${current.itemtext}"
    holder.itemlocation.text = current.itemlocation
    if (current.image.length>0) {
        val image = Base64.decode(current.image, 0)
        val bitmap = BitmapFactory.decodeByteArray(image, 0, image.size)
        holder.image.setImageBitmap(bitmap)
    }
}
internal fun setItems(items: List<Items>){
    this.itemList=items
    notifyDataSetChanged()
}

override fun getItemCount() = itemList.size

}

E.路透社我经历过这种情况,问题是使用嵌套回收器视图的方法是非常正确的。你的代码看起来不错。但用于查询数据库的查询。我认为您应该在后台或其他区域使用查询,并在获得结果时显示结果,而不是从OnCreate或主线程查询结果。因为一次完成这么多项目可能会造成活动滞后,降低性能。如果你还没有试一下,请告诉我。发生了什么。谢谢

我正在编辑我的答案。你可以做的另一件事是,如果你有超过一定数量的项目,那么你应该使用诸如分页之类的方法一次加载一定数量的项目,以避免这种延迟

在这里,我附加的代码查询一定数量的数据每次加载

SApp.database!!.resultDao().loadAllUsersByPage(5, 10)
 @Query("SELECT * FROM Result LIMIT :limit OFFSET :offset")
 fun loadAllUsersByPage(limit: Int, offset: Int): List<Result>

非常感谢你的回答。我认为分页确实是一种很好的方法。但我无法直接添加页面,因为我从roomdatabase获取数据,如下所示:

@Query(SELECT * FROM users)
fun getData(): LiveData<List<userWithItems>>
而实际的项目是按房间添加的,因为用户和项目之间存在关系,我将不得不更改此行为

我想试试这样的

@Query(SELECT * FROM users)
fun getUserData(): LiveData<List<Users>>

然后尝试在外部recyclerview中添加一个LiveData观察者,以在使用分页的单独查询中获取项目。

我解决了这个问题。当我想到分页时,我想到问题可能是内部recyclerview有一个包裹内容的高度,因此它需要构建所有项目,并使rv无用。当我制作内部rv 250dp的高度时,它可以与2000件物品配合使用

所以现在我只需要找出一种方法,总是找到内部rv的最佳高度,并解决滚动问题,但原来的问题已经解决了


特别感谢阿曼B

抱歉-我不认为代码会是一个大问题,但这是一个概念,因为它只适用于内部适配器中的几个项目。我认为问题是,在内部recyclerview中,即使有1000个项目,并且只能在显示屏上看到5或6个项目,也会立即创建每个项目,这需要时间。