私はリストアイテムとしてCardViewを持つ単純なRecyclerViewを持っています。 Firebase Realtimeデータベースから取得したリストの各項目はnoteList
に保存されます。 Firebase sdkは、onChildAdded、onChildChangedなどのコールバックを提供します。今度は、リサイクラー・ビュー用のアダプターをArrayListで使用するように設計しました。 Realtimeデータベースのデータが変更されるたびに、コールバックを使用してnoteList
に項目を追加または削除します。 onChildChanged
メソッドは、特定の項目の値が変更されるたびに呼び出されます。この変更をnoteList
に反映させ、同じことをアダプターに通知したいと思います。 もちろん、変更された要素のキーと一致するList内の各要素を素早く検索して更新することができます。しかし、これはより効率的な方法で行うことができますか?Firebase Realtime DatabaseでAndroidのインデックスを知らずにArrayListの要素を更新するにはどうすればいいですか?
class NoteListAdapter(var data: MutableList<Note>, val onItemClick: (Note) -> Unit) : RecyclerView.Adapter<NoteListAdapter.ViewHolder>() {
override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
holder!!.bindNoteItem(data[position])
}
override fun getItemCount(): Int = data.size
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent?.context)
.inflate(R.layout.card_note, parent, false)
return ViewHolder(v, onItemClick)
}
class ViewHolder(v: View, val onItemClick: (Note) -> Unit): RecyclerView.ViewHolder(v) {
fun bindNoteItem(note: Note) {
...
}
}
}
HomeActivity.kt
class HomeActivity : AppCompatActivity() {
lateinit var mDb: DatabaseReference
val noteList: MutableList<Note> = ArrayList()
lateinit var adapter: NoteListAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
addNoteFAB.setOnClickListener { addNote() }
mDb = FirebaseDatabase.getInstance().reference
adapter = NoteListAdapter(noteList, this::editNote)
noteListRecycler.layoutManager = LinearLayoutManager(this)
noteListRecycler.adapter = adapter
loadNotes()
}
fun addNote() {
val intent = Intent(this, EditNoteActivity::class.java)
intent.putExtra(EditNoteActivity.EXTRA_NOTE, Note())
startActivity(intent)
}
fun loadNotes() {
val path = "users/" + FirebaseAuth.getInstance().currentUser?.uid + "/notes"
mDb.child(path).addChildListener({
// onChildAdded
dataSnapshot, prevChildName ->
val note = dataSnapshot?.getValue(Note::class.java)!!
note.id = dataSnapshot.key
noteList += note
adapter.notifyDataSetChanged()
}, {
// onChildRemoved
dataSnapshot ->
noteList.remove(dataSnapshot?.getValue(Note::class.java))
adapter.notifyDataSetChanged()
}, {
// onChildChanged, TODO: update the change in elements value in noteList
dataSnapshot, s ->
})
}
fun editNote(note: Note) {
val i = Intent(this, EditNoteActivity::class.java)
i.putExtra(EditNoteActivity.EXTRA_NOTE, note)
startActivity(i)
}
}
PS:addChildListenerは、拡張機能です。どのように私はのインデックスを知らなくてもnoteList
を更新する、(私はドキュメントから知っている限り)dataSnapshot
以来
は私たちだけ変更されたキーと値を伝えることができます(コールバックの名前をコード内のコメントをご確認ください)変更された要素?または、実際にインデックスを取得する方法はありますか?
ありがとうございました。私はFirebaseと一緒に行きます。 Btw、私はリストの項目を(タイムスタンプに基づいて)末尾に追加したので、onChildAddedのコードを追加したと思った。訂正してくれてありがとう。 –
'push()'メソッドは、タイムスタンプに基づいてキーを作成し、デフォルトのクエリの順序はアルファベット順ですが、あなたが最も賞賛された投稿などを取得したいとしましょう。 'query.orderByChild(" votes ")'と書いておけば、子はキーに関係なくどこにでも追加できます。私は将来の痛みからあなたを救うだけです。 – SUPERCILEX