В настоящее время не существует реализации RecyclerView.Adapter по умолчанию.
Может с официальным релизом гугл добавит.
Поскольку не существует никакой поддержки CursorAdapter
с в RecyclerView
настоящее время, как мы можем использовать RecyclerView
с базой данных? Какие-либо предложения ?
setHasStableIds(true)
Мое решение заключалось в том, чтобы сохранить член CursorAdapter в моей реализации recyclerView.Adapter. Затем передайте всю обработку создания нового представления и привязки его к адаптеру курсора, примерно так:
источник
public void changeCursor(Cursor cursor){ mCursorAdapter.changeCursor(cursor); notifyDataSetChanged(); }
Поскольку в вашем вопросе говорится «Как использовать
RecyclerView
с базой данных», и вы не уточняете, хотите ли вы SQLite или что-то еще с нимRecyclerView
, я дам вам решение, которое является оптимальным. Я буду использовать Realm в качестве базы данных и позволю вам отображать все данные внутри вашегоRecyclerView
. Он также поддерживает асинхронные запросы без использованияLoaders
илиAsyncTask
.Почему царство?
Шаг 1
Добавьте зависимость Gradle для Realm, зависимость для последней версии находится здесь
Шаг 2
Например, создайте свой класс модели, скажем что-то простое, например, у
Data
которого есть 2 поля, строка, которая будет отображаться внутриRecyclerView
строки, и отметка времени, которая будет использоваться как itemId для разрешенияRecyclerView
анимации элементов. Обратите внимание, что я расширяюRealmObject
ниже, из-за чего вашData
класс будет храниться как таблица, а все ваши свойства будут храниться как столбцы этой таблицыData
. В моем случае я пометил текст данных как первичный ключ, так как не хочу, чтобы строка добавлялась более одного раза. Но если вы предпочитаете иметь дубликаты, сделайте отметку времени как @PrimaryKey. У вас может быть таблица без первичного ключа, но это вызовет проблемы, если вы попытаетесь обновить строку после ее создания. Составной первичный ключ на момент написания этого ответа Realm не поддерживает.Шаг 3
Создайте свой макет для того, как одна строка должна отображаться внутри
RecyclerView
. Макет для элемента с одной строкой внутри нашегоAdapter
выглядит следующим образомОбратите внимание, что я сохранил
FrameLayout
корневую папку, хотя у меня естьTextView
внутренняя. Я планирую добавить больше элементов в этот макет и, следовательно, пока сделал его гибким :)Для любопытных вот как сейчас выглядит отдельный предмет.
Шаг 4
Создайте свою
RecyclerView.Adapter
реализацию. В этом случае объект источника данных - это специальный вызываемый объект,RealmResults
который по сути является LIVEArrayList
, другими словами, когда элементы добавляются или удаляются из вашей таблицы, этотRealmResults
объект обновляется автоматически.Обратите внимание, что я звоню
notifyItemRemoved
с позиции, в которой произошло удаление, но Я НЕ звоню,notifyItemInserted
илиnotifyItemRangeChanged
потому что нет прямого способа узнать, в какую позицию элемент был вставлен в базу данных, поскольку записи Realm не хранятся в упорядоченном виде.RealmResults
Объект автоматически обновляется каждый раз , когда новый элемент добавляется, изменен или удален из базы данных , поэтому мы называем вnotifyDataSetChanged
то время как добавление и вставкой записей сыпучими. На этом этапе вас, вероятно, беспокоят анимации, которые не будут запускаться из-за того, что вы вызываетеnotifyDataSetChanged
вместоnotifyXXX
методов. Именно поэтому у меняgetItemId
метод возвращает временную метку для каждой строки из объекта результатов. Анимация достигается в 2 этапа,notifyDataSetChanged
если вы вызываете,setHasStableIds(true)
а затем отменяетеgetItemId
предоставить что-то иное, чем просто должность.Шаг 5
Давайте добавим
RecyclerView
к нашемуActivity
илиFragment
. В моем случае я используюActivity
. Файл макета, содержащийRecyclerView
элемент, довольно тривиален и будет выглядеть примерно так.Я добавил,
app:layout_behavior
так как яRecyclerView
перешел внутрь,CoordinatorLayout
который я не публиковал в этом ответе для краткости.Шаг 6
Создайте
RecyclerView
код и предоставьте необходимые данные. Создайте и инициализируйте объект Realm внутриonCreate
и закройте его внутриonDestroy
почти так же, как закрытиеSQLiteOpenHelper
экземпляра. В самом простом случае вашаonCreate
внутренняя частьActivity
будет выглядеть так. ВinitUi
методе происходит все волшебство. Я открываю экземпляр Realm внутриonCreate
.Обратите внимание, что на первом этапе я запрашиваю Realm, чтобы предоставить мне все объекты из
Data
класса, отсортированные по имени их переменной, называемой данными, асинхронным образом. Это дает мнеRealmResults
объект с 0 элементами в основном потоке, который я устанавливаю вAdapter
. Я добавил,RealmChangeListener
чтобы получать уведомления о завершении загрузки данных из фонового потока, в который я вызываюnotifyDataSetChanged
свойAdapter
. Я также вызвалsetHasStableIds
значение true, чтобы позволитьRecyclerView.Adapter
реализации отслеживать элементы, которые добавляются, удаляются или изменяются. TheonDestroy
for myActivity
закрывает экземпляр RealmЭтот метод
initUi
можно вызвать внутриonCreate
вашегоActivity
илиonCreateView
илиonViewCreated
вашегоFragment
. Обратите внимание на следующие вещи.Шаг 7
BAM! Существуют данные из базы данных внутри вашей
RecyclerView
asynchonously загружены безCursorLoader
,CursorAdapter
,SQLiteOpenHelper
с анимацией. Показанное здесь изображение в формате GIF немного тормозит, но анимация появляется, когда вы добавляете или удаляете элементы.источник
Вы можете реализовать все необходимые методы самостоятельно. Недавно я сделал свою собственную реализацию, просто скопировав код из CursorAdapter.
источник
Я сделал RecyclerViewCursorAdapter, используя SortedList в качестве бэкэнда, расширяя RecyclerView.Adapter
Может использоваться с SQLiteCursor и загрузчиками
источник
Еще один ответ, так как мне не понравился принятый (который imo не имеет интуитивного использования).
Ниже представлена моя собственная реализация, которая очень похожа на (и частично вдохновлена)
SimpleCursorAdapter
:Вы можете изменить его для других целей, но при наличии курсора он работает точно так
SimpleCursorAdapter
же, только с расширениемRecyclerView
.источник
После извлечения данных из БД и сохранения в списке, возможно, должно получиться что-то вроде этого:
добавить данные в recyclerview
источник
Ниже моя реализация cursoradapter для recyclerview. Он поддерживает OnItemClickListener, OnLongItemClickListener, OnfooterClickListener, разделы и нижний колонтитул. Не поддерживает , Header, onHeaderClickListner, быструю прокрутку, липкий заголовок или липкие разделы.
Просто удлините этот адаптер и создайте свой собственный. Переопределите предоставленные методы. и передайте курсор из метода OnCursorLoadFinished. если адаптер уже создан, то swapCursor ()
источник
Простейшая реализация - использовать объект курсора в адаптере и передать курсор конструктору держателя просмотра для изменения представлений и изменения положения курсора в onBindViewholder.
Если вы используете загрузчик курсора, вызовите метод setCursor
onLoadfinished()
и передайте null вonLoadReset()
}
источник
Наконец, у нас есть реализация RecyclerView.Adapter для базы данных / сети.
Он реализован с помощью компонентов архитектуры Android :
База данных комнаты: уровень базы данных поверх базы данных SQLite, который заботится о рутинных задачах, которые вы использовали для обработки с помощью
SQLiteOpenHelper
. Держатель базы данных, который служит точкой доступа к базовой базе данных SQLite. База данных Room использует DAO для отправки запросов к базе данных SQLite.ViewModel: предоставляет данные пользовательскому интерфейсу. Выступает в качестве коммуникационного центра между репозиторием и пользовательским интерфейсом. Скрывает источник данных из пользовательского интерфейса. Экземпляры ViewModel выживают при воссоздании действия / фрагмента.
LiveData: класс держателя данных, который можно наблюдать. Всегда хранит / кеширует последнюю версию данных. Уведомляет своих наблюдателей об изменении данных. LiveData учитывает жизненный цикл. Компоненты пользовательского интерфейса просто наблюдают за соответствующими данными и не останавливают и не возобновляют наблюдение. LiveData автоматически управляет всем этим, поскольку во время наблюдения знает о соответствующих изменениях статуса жизненного цикла.
источник
Вы можете использовать базу данных SQLite для хранения деталей. Получить доступ к данным легко. Вы можете проверить мой код на github. https://github.com/thiru-wta/ToDo
Методы базы данных:
получить метод:
источник
Вам просто нужно выполнить следующие шаги:
view.adapter
создайте ArrayList или Iterator, инициализированный нулевым значением.swapdata(Arraylist<T> data)
. Внутри вы задаете новые значения списку массивов, итератору или любой структуре, которую система может перебирать, используя целочисленную позицию в bindview. Значения этого метода передаются вonloaderfinished()
. Затем позвоните сразу после назначенияnotifydatachange()
; они попросятRecyclerView
перерисовать весь список новыми данными ArrayList.В действии или фрагменте, где вы используете loadercalback, создайте метод, который преобразует курсор в arrayylist или итератор, в зависимости от структуры данных, выбранной в адаптере.
Таким образом, вы всегда можете использовать loadercalback без блокировки основного потока.
источник