FirebaseRecyclerAdapter mostra un elemento invece di un array
La mia visualizzazione riciclatore mostra solo l'ultimo elemento nei miei dati. Voglio invece mostrarvi tutto.
Struttura dati:
{
"messages" : {
"-MLLiVKuT5anOHM_6x8T" : {
"senderId" : "[email protected]",
"senderName" : "Rebecca",
"text" : "It happens to be where Josh lives",
"type" : "OUTGOING"
},
"-MLLiYGcGhPv3E8xdbyh" : {
"senderId" : "[email protected]",
"senderName" : "Rebecca",
"text" : "But that's not why I'm here",
"type" : "OUTGOING"
},
"-MLLm8JruMp_P99e2-SY" : {
"senderId" : "[email protected]",
"senderName" : "Rebecca",
"text" : "She's a crazy ex-girlfriend",
"type" : "OUTGOING"
}
}
}
Frammento:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// ...
val messageManager = LinearLayoutManager(context).apply {
stackFromEnd = true
}
message_list.layoutManager = messageManager
messageAdapter = MessageAdapter.create(chatViewModel.messagesQuery, viewLifecycleOwner, CURRENT_USER.id)
message_list.adapter = messageAdapter
}
Visualizza modello:
class ChatViewModel : ViewModel() {
private val database by lazy { Firebase.database.reference }
private val messagesRef by lazy { database.child(MESSAGES_CHILD) }
val messagesQuery: Query by lazy { messagesRef.limitToLast(MESSAGE_LIMIT) }
val messageTextInput: ObservableField<String> = ObservableField("")
fun sendMessage() {
val messageText = messageTextInput.get()
val message = Message(
senderId = CURRENT_USER.id,
senderName = CURRENT_USER.name,
text = messageText,
type = Message.Type.OUTGOING
)
messagesRef.push().setValue(message)
messageTextInput.set("")
}
}
Adattatore:
class MessageAdapter(options: FirebaseRecyclerOptions<Message>) :
FirebaseRecyclerAdapter<Message, MessageViewHolder>(options) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder =
when (Message.Type.values()[viewType]) {
Message.Type.INCOMING -> MessageViewHolder.Incoming.create(parent)
Message.Type.OUTGOING -> MessageViewHolder.Outgoing.create(parent)
}
override fun onBindViewHolder(viewHolder: MessageViewHolder, position: Int, message: Message) {
Log.d("MessageAdapter#onBindViewHolder", "message: $message") viewHolder.bind(message) } override fun getItemViewType(position: Int): Int = getItem(position).type!!.ordinal companion object { fun create(query: Query, lifecycleOwner: LifecycleOwner, currentUserId: String): MessageAdapter { val parser = SnapshotParser<Message> { val message = it.getValue(Message::class.java) Log.d("MessageAdapter#create", "message: $message")
message?.id = it.key
message?.type = if (message?.senderId == currentUserId) {
Message.Type.OUTGOING
} else {
Message.Type.INCOMING
}
message ?: Message()
}
val options =
FirebaseRecyclerOptions.Builder<Message>()
.setQuery(query, parser)
.setLifecycleOwner(lifecycleOwner)
.build()
return MessageAdapter(options)
}
}
}
Layout del frammento:
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable name="viewModel" type="ogbe.eva.bloomer.viewmodels.chat.ChatViewModel"/>
</data>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".views.chat.ChatFragment">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
style="@style/Widget.MaterialComponents.Toolbar.Primary"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/message_list"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/divider"
android:layout_margin="@dimen/spacing_md"
tools:listitem="@layout/item_message_outgoing"/>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/message_text_input"
android:background="@color/divider_color"/>
<EditText
android:id="@+id/message_text_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/send_message_button"
app:layout_constraintBottom_toBottomOf="parent"
android:hint="@string/message_text_hint"
android:importantForAutofill="no"
android:text="@={viewModel.messageTextInput}"
style="@style/MessageTextInput"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/send_message_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginEnd="@dimen/spacing_md"
android:enabled="@{viewModel.isSendButtonEnabled}"
android:onClick="@{(view) -> viewModel.sendMessage()}"
android:text="@string/send_message_button"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>
Layout articolo:
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<data>
<variable name="message" type="ogbe.eva.bloomer.domain.Message"/>
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:background="@drawable/outgoing_message_bg"
android:text="@{message.text}"
android:textIsSelectable="true"
style="@style/MessageItemText"
tools:text="It happens to be where Josh lives"/>
</FrameLayout>
</layout>
L'adattatore sembra elaborare tutti i messaggi nel onBindViewHoldere nel parser, ma viene visualizzato solo un messaggio.
Ho visto questa domanda che è simile ma NON un duplicato. La risposta accettata dice di utilizzare una matrice di valori nel database. Ho provato a importare l'array esatto dalla risposta accettata e ho detto che non era JSON non valido. Se dovrei usare un array, come ne inserisco uno nel database? In caso contrario, in quale altro modo potrei visualizzare l'intera struttura dei dati?
Risposte
Prova ad aggiornare il layout del tuo articolo come di seguito.
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<data>
<variable name="message" type="ogbe.eva.bloomer.domain.Message"/>
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:background="@drawable/outgoing_message_bg"
android:text="@{message.text}"
android:textIsSelectable="true"
style="@style/MessageItemText"
tools:text="It happens to be where Josh lives"/>
</FrameLayout>
</layout>
per:
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<data>
<variable name="message" type="ogbe.eva.bloomer.domain.Message"/>
</data>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:background="@drawable/outgoing_message_bg"
android:text="@{message.text}"
android:textIsSelectable="true"
style="@style/MessageItemText"
tools:text="It happens to be where Josh lives"/>
</FrameLayout>
</layout>
Buona programmazione!