Manoel Henrique
Manoel Henrique

Reputation: 45

RecyclerView Android Error: E/RecyclerView: No adapter attached; skipping layout

When trying to get JSON data from an API and show it on the RecyclerView I'm getting following error:

Error: No adapter attached; skipping layout

I already use RecyclerView sometimes and I never had this problem.

MainActivity:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(activity_main)
    overwriteOnPostInteractionListener()
    setupObservers()
}

private fun setupObservers(){
    mServiceRequest.searchPostsFromAPI().observe(this, Observer { posts ->
        if (posts != null){
            loadRecyclerView()
            mPostList = posts.toMutableList()
        }
    })
}

private fun loadRecyclerView() {
    recyclerView.adapter = PostListAdapter(mPostList, mOnPostListInteractionListener)
    recyclerView.layoutManager = LinearLayoutManager(this)
    recyclerView.setHasFixedSize(true)
}

Adapter:

class PostListAdapter(private val postList: List<PostModel>,
      private val onPostListInteractionListener: OnPostListInteractionListener):
      RecyclerView.Adapter<PostViewHolder>(){ 

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostViewHolder {
    val inflate = LayoutInflater.from(parent.context)
    val view = inflate.inflate(R.layout.posts , parent, false)
    return PostViewHolder(view, parent.context, onPostListInteractionListener)
}

override fun getItemCount(): Int {
    return postList.count()
}

override fun onBindViewHolder(holder: PostViewHolder, position: Int) {
    holder.bindTask(postList[position])
}}

ViewHolder:

class PostViewHolder(itemView: View, private val context: Context,
                 private val onPostListInteractionListener: OnPostListInteractionListener)
                : RecyclerView.ViewHolder(itemView) {

private val postTitle = itemView.findViewById<TextView>(R.id.titleTextViewMain)
private val postBody = itemView.findViewById<EditText>(R.id.bodyEditText)

fun bindTask(post: PostModel){
    postTitle.text = post.title
    postBody.setText(post.body)
    postTitle.setOnClickListener {
        onPostListInteractionListener.onListClick(post.id)
    }
}}

I searched a lot how to solve this error but I can't.

Upvotes: 1

Views: 515

Answers (1)

Zain
Zain

Reputation: 40898

You build your RecyclerView adapter before feeding the data to the list, so you need to call mPostList = posts.toMutableList() before instantiating your adapter.

So, change setupObservers() with:

private fun setupObservers(){
    mServiceRequest.searchPostsFromAPI().observe(this, Observer { posts ->
        if (posts != null){
            mPostList = posts.toMutableList()
            loadRecyclerView()

        }
    })
}

Also set your adapter after, you completely build the RecyckerView. So change the order of loadRecyclerView() as below.

private fun loadRecyclerView() {
    recyclerView.layoutManager = LinearLayoutManager(this)
    recyclerView.setHasFixedSize(true)
    recyclerView.adapter = PostListAdapter(mPostList, mOnPostListInteractionListener)
}

Setting RecyclerView adapter before layout can cause issues.

Side note:

You instantiate your adapter every time your list is changed, and that's not the right way, and it's better to create your stuff (including the adapter) only once in a lifecycle, and then make setters each time you want to change them instead of instantiating them over and over again.

So, you can instantiate your adapter only once in onCreate() method and create a method in your adapter that takes the posts setPosts(private val postList: List<PostModel>) and set them internally .. whenever you need to change adapter list, just call setPosts

Upvotes: 2

Related Questions