Проблемы с вложенным переработчиком - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть вложенное представление переработчика, которое должно выглядеть так: picture.

Я реализовал его в соответствии с этим полезным сайтом .

Проблема в том, что у меня иногда есть пользователь с сотнями элементов, и в этом случае это занимает половинуминута, чтобы открыть действие.

У меня есть база данных комнаты в бэкэнде с двумя связанными таблицами с внешними ключами (пользователи и элементы), и я выбираю всех пользователей, чтобы получить список пользователей / элементов, где элементы являются спискомв пользовательской таблице.

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

и я создаю внутреннее представление рециркулятора со списком элементов вАдаптер.

Было бы лучше сделать один список UserItems (идентификатор пользователя: Int, имя пользователя: String, ... itemid: Int, itemList) и сгруппировать их для внешнего rv.

ИлиЕсть ли возможность избавиться от вложенного rv и сделать дизайн с помощью всего одного списка просмотрщиков?

Или есть другое решение, чтобы заставить работать вложенный просмотр, даже если у пользователя много элементов?

код для адаптеров:

// 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

)

Класс данных Items (val id: Int, val itemtext: String, val itemlocation: String, val image: String // ...)

// UserAdapter (снаружи)

класс Внутренний конструктор 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 голосов
/ 30 ноября 2018

Большое спасибо за ваш ответ.Я думаю, что пейджинг действительно хороший подход.Но я не могу добавить страницу непосредственно, так как я получаю свои данные из базы данных, например:

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

, и фактические элементы добавляются по комнате из-за связи между пользователем и элементами, мне придется изменить этоповедение.

Я попробую что-то наподобие

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

, а затем попытаюсь добавить наблюдатель LiveData во внешнее представление переработчика, чтобы получить элементы в отдельном запросе, использующем подкачку.

0 голосов
/ 30 ноября 2018

Я решил проблему.Когда я подумал о разбиении на страницы, мне пришло в голову, что проблема может заключаться в том, что внутреннее представление переработчика имеет высоту wrap_content, поэтому ему нужно собрать все элементы и сделать rv бесполезным.Когда я делаю высоту внутреннего rv 250dp, он работает даже с 2000 элементами.

Так что теперь мне просто нужно найти способ всегда найти оптимальную высоту для внутреннего rv и решить проблему с прокруткойно оригинальная проблема решена.

Отдельное спасибо Aman B!

0 голосов
/ 28 ноября 2018

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>
...