0

I am trying to build a list with a recycler view. I created the recycler view, an adapter and set the adapter with default values in OnCreate and then later in that function I call a firebase async function that populates it correctly. Currently OnCreate is not even being called and I am getting the error "No adapter attached; skipping layout"

CHAT ADAPTER CLASS

class ChatAdapter(private val messages: List<MessageViewModel>, val conts: Context) : RecyclerView.Adapter<ChatAdapter.ChatViewHolder>() {

    val cont = conts

    class ChatViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val senderTextView: TextView = view.findViewById(R.id.textViewSender)
        val messageTextView: TextView = view.findViewById(R.id.textViewMessage)
        val dateTextView: TextView = view.findViewById(R.id.dateTextView)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChatViewHolder {
        val view = LayoutInflater.from(cont).inflate(R.layout.chat_view_design, parent, false)
        return ChatViewHolder(view)
    }

    @RequiresApi(Build.VERSION_CODES.O)
    override fun onBindViewHolder(holder: ChatViewHolder, position: Int) {
        val chatMessage = messages[position]
        val ref = Firebase.database.reference
        ref.child("users").child(chatMessage.fromId).get().addOnCompleteListener { task ->
            if (task.isSuccessful) {
                val snapshot = task.result
                val txt = snapshot.child("username").getValue(String::class.java)
                holder.senderTextView.text = txt
            }
        }
        holder.messageTextView.text = chatMessage.text

        val instant = Instant.ofEpochMilli((chatMessage.date * 1000).toLong())

        val formatter = DateTimeFormatter.ofPattern("MM/dd/yy")
        val newDate = Date.from(instant)

        val finalDate : LocalDate = newDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()

        holder.dateTextView.text = formatter.format(finalDate)

        if (messages[position].fromId != Firebase.auth.currentUser?.uid) {
            holder.senderTextView.setTextColor(Color.parseColor("#FFA500"))
        }
    }

    override fun getItemCount() = messages.size
}

Chat Activity adding adapter

And finally here is the code that sets the adapter after the api call

    val adapter = ChatAdapter(messages, this)
                                    chatAdapter = adapter
                                    recyclerView.adapter = chatAdapter
                                    recyclerView.scrollToPosition(messages.size - 1)
                                    chatAdapter.notifyDataSetChanged()
2
  • 1. No need to create and assign a new adapter to recyclerview after the api call. Just keep the list property inside the adapter and create a method there to update the list. 2. First notifyDataSetChanged() then call scrollToPosition with recyclerView.post { //here } Bonus: onBindViewHolder could be optimized. some computation is going on there. Commented Feb 11 at 22:17
  • You MainActivity's onCreate is never called?
    – Alex Mamo
    Commented Feb 16 at 5:13

1 Answer 1

0

If you provided the full error from Logcat, it would be easier to help.

You don’t need to create a new adapter after the API call. Instead, initialize the adapter once in onCreate() and assign it to the RecyclerView.

To update the list when new data arrives, modify the existing list inside the adapter rather than replacing the entire adapter.

Since the list is passed via the constructor, a better approach is to define a variable inside the adapter and update it whenever needed.

Additionally, you can implement a setter for the list that updates the data and automatically calls notifyDataSetChanged(), ensuring efficient updates to the RecyclerView.

Adapter:

class ChatAdapter(val conts: Context) : RecyclerView.Adapter<ChatAdapter.ChatViewHolder>() {

var list = mutableListOf<MessageViewModel>()
    set(value) {
        field = value
        notifyDataSetChanged()
    }

// ...

}

After setting the new list, you can also call recyclerView.scrollToPosition(messages.size - 1)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.