#android #kotlin #android-recyclerview #android-adapter
#Android #kotlin #android-recyclerview #android-адаптер
Вопрос:
Как я могу обновить значение элемента в режиме реального времени? У меня есть список. К нему добавляются элементы. (список подключенных устройств через Bluetooth). Каждая ячейка содержит информацию: имя, дату. Как я могу изменить, например, имя в любой ячейке без обновления всего списка? Теперь, когда я вызываю update
метод, информация изменяется в первом элементе списка (в позиции 0), но мне нужно, чтобы я мог изменять значение любой позиции и любого элемента при вызове update
метода. Я читал о DiffUtil
классе. Но я не уверен, что это подходящий вариант для меня. Итак, у меня есть класс модели:
data class Device (
var name: String,
var date: String
)
адаптер:
class CustomRecyclerAdapter(private val values: MutableList<Device>) :
RecyclerView.Adapter<CustomRecyclerAdapter.MyViewHolder>() {
override fun getItemCount(): Int {
return values.size
}
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.list_item, viewGroup, false)
return MyViewHolder(view)
}
override fun onBindViewHolder(viewHolder: MyViewHolder, position: Int) {
var device: Device = values[position]
viewHolder.bin(device)
}
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var textName: TextView? = null
var textDate: TextView? = null
init {
textName = view.findViewById(R.id.name)
textDate = view.findViewById(R.id.date)
}
fun bin(device:Device) {
textName?.text = device.name
textDate?.text = device.date
}
}
class MyFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_upload_card, container, false)
var recyclerView = view.findViewById(R.id.recyclerView) as RecyclerView
recyclerView.layoutManager = LinearLayoutManager(activity)
adapter = CustomRecyclerAdapter(list)
recyclerView.adapter = adapter
return view
}
private fun addItem() {
var device = Device("DeviceName", "date")
list.add(0, device)
adapter?.notifyItemInserted(0)
}
fun update() {
list[0].run {
name = "newName"
date = "newDate"
}
adapter?.notifyDataSetChanged()
}
Может быть, мне нужно использовать RX здесь? Но я не понимаю, как в этом случае
Комментарии:
1. вам нужно будет следить за вашими изменениями (rx java, текущие данные и т. Д.), А Затем вызывать notifyItemChanged вместо notifyDataSetChanged
2. Поступают ли эти данные из базы данных, например, room?
3. @ TDIScott, да, эти данные поступают из базы данных
Ответ №1:
Предлагаемое решение для вашего сценария.
Здесь я рассмотрю несколько моментов.
- RecyclerView имеет множество методов, которые могут использоваться, например, добавлять, удалять, обновлять, обновлять диапазон и т. Д..
В вашем случае вы хотите обновить элемент / элементы:
- Один элемент / строка: если вы хотите обновить одну строку, у вас должна быть позиция для этой строки. Это ваша задача, как вам удается получить
позицию. Например, получив обновленные данные строки, вы можете
выполнить поиск в списке и получить оттуда позицию. Могут быть использованы следующие методы notifyItemChanged, notifyItemRangeChanged - Весь список: если у вас есть весь список, вы можете использовать DiffUtil для обновления этого списка.
Для данных в реальном времени вы можете использовать Livedata, RxJava, но описанная выше процедура останется прежней. Используя LiveData, вы можете наблюдать изменения в базе данных.
Дайте мне знать, если вы получили свое решение.
Комментарии:
1. спасибо за ваш комментарий. Смотрите: я могу одновременно читать и добавлять в список множество устройств. И каждый раз позиция элемента будет отличаться. поэтому я думаю, что мне нужно обновить значение элемента, не зная, в какой позиции он сейчас находится. вот почему я думаю, что класс DiffUtil здесь не подходит…
Ответ №2:
Если я правильно понял вопрос, вам нужно вызвать notifyItemChanged
вместо adapter?.notifyDataSetChanged()
, этот метод имеет два разных вызова, один с позицией, а другой с позицией и полезной нагрузкой для частичного изменения целевого элемента, пожалуйста, проверьте это здесь
Ответ №3:
Пожалуйста, оберните свой источник данных внутрь Live Data
. А затем передать эти текущие данные в адаптер просмотра Recycler.
например,
@Query("SELECT * FROM word_table ORDER BY word ASC")
fun getAlphabetizedWords(): LiveData<List<Word>>
Затем Recycler View позаботится об обновлении данных на экране при внесении изменений в базу данных.
Комментарии:
1.
Then Recycler View will take care of updating the data on screen when there are changes made to the Database.
как? на данный момент это только половина ответа, вы должны показать OP, как наблюдать за этими изменениями и вносить соответствующие изменения2. @SVK спасибо за ваш комментарий. Это необходимо? Чтобы обернуть источник данных внутри текущих данных?
3. @Julia: Нет необходимости переносить источник данных
Live Data
. Однако, если вы преобразуете свои данные в текущие данные, тогдаRecycler View
вы будете выполнять тяжелую работу по обновлению пользовательского интерфейса всякий раз, когда происходят какие-либо изменения в источнике данных, без необходимости вручную отслеживать изменения. RecyclerView с данными в реальном времени приводит к созданию высокопроизводительного приложения.