嵌套的recyclerview问题

时间:2018-11-27 10:28:52

标签: android performance android-recyclerview kotlin nested

我有一个嵌套的recyclerview,看起来应该像picture中的样子。

我根据this helpful site实现了它。

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

我在后端有一个会议室数据库,带有两个带有外键(用户和项目)的链接表,我选择所有用户以获取用户/项目列表,其中项目是用户表中的列表。

class userWithItems:(id:Int,name:String,...,List)

然后用适配器中的项目列表创建内部回收站视图。

最好制作一个列表UserItems(userid:Int,username:String,... itemid:Int,itemList)并将它们分组为外部rv。

或者是否有可能摆脱嵌套的rv,仅用一个recyclerview-list进行设计?

还是有另一种解决方案,即使用户有很多物品也可以使嵌套的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:字符串,val itemlocation:字符串,val image:字符串// ... )

// UserAdapter(外部)

class UserAdapter内部构造函数(         上下文:上下文 ):RecyclerView.Adapter(){

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

}

class UserItemAdapter内部构造函数(         上下文:上下文 ):RecyclerView.Adapter(){

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

}

3 个答案:

答案 0 :(得分:0)

E。 Reuter我已经经历过这种情况,问题是使用嵌套的Recycler View方法是非常正确的。您的代码似乎不错。但是您要用来查询数据库的查询。我认为您应该在后台或其他威胁中使用查询,并在获得查询时显示结果,而不是从OnCreate或主线程中查询。因为一次性获得这么多项目可能会导致活动滞后并降低性能。如果您还没有尝试,请告诉我。怎么了。谢谢...

我正在编辑我的答案。您可以做的另一件事是,如果您有超过一定数量的物品,那么您不应该首先使用分页之类的方法一次加载一定数量的物品,以免出现这种情况。

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

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

答案 1 :(得分:0)

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

@Query(SELECT * FROM users)
fun getData(): LiveData<List<userWithItems>>

由于用户和项目之间的关系,实际项目是按房间添加的,我将不得不更改此行为。

我会尝试类似的东西

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

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

答案 2 :(得分:0)

我解决了这个问题。当我想到分页时,我想到的问题可能是内部recyclerview的高度为wrap_content,因此需要构建所有项目并使rv无效。当我将内部rv的高度设为250dp时,它甚至可以处理2000个项目。

因此,现在我只需要找出一种始终为内部rv找到最佳高度并解决滚动问题的方法,但是原来的问题就解决了。

特别感谢Aman B!