Ron Jones Jr
Ron Jones Jr

Reputation: 23

Activity with RecyclerView not calling OnCreate

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()

Upvotes: 0

Views: 46

Answers (1)

HamidReza
HamidReza

Reputation: 33

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)

Upvotes: 0

Related Questions