Codist
Codist

Reputation: 769

NullPointerException: Attempt to invoke virtual method & RecyclerView: No adapter attached; skipping layout, errors, when fetching data from Firestore

I was trying to fetch data from the Firestore and show it in a RecyclerView. But, I am getting the following errors. I do not have much experience in coding, but I tried to add RecyclerView and fragments in my project.

I am using Kotlin as language.

I have been trying to figure out what went wrong and for a solution for the last three days but now I think I must seek help from experts like you.

Following is the error I get in the Logcat

16273-16273/com.example.quiz E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.quiz, PID: 16273
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.quiz/com.example.quiz.ui.activities.DashboardActivity}: android.view.InflateException: Binary XML file line #32 in com.example.quiz:layout/activity_dashboard: Binary XML file line #32 in com.example.quiz:layout/activity_dashboard: Error inflating class fragment
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3792)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3968)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:246)
        at android.app.ActivityThread.main(ActivityThread.java:8512)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
     Caused by: android.view.InflateException: Binary XML file line #32 in com.example.quiz:layout/activity_dashboard: Binary XML file line #32 in com.example.quiz:layout/activity_dashboard: Error inflating class fragment
     Caused by: android.view.InflateException: Binary XML file line #32 in com.example.quiz:layout/activity_dashboard: Error inflating class fragment
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView.setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager)' on a null object reference
        at com.example.quiz.ui.fragments.DashboardFragment.onCreateView(DashboardFragment.kt:28)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2963)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:518)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2106)
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3138)
        at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3065)
        at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2988)
        at androidx.fragment.app.FragmentStateManager.ensureInflatedView(FragmentStateManager.java:392)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:281)
        at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:140)
        at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
        at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:319)
        at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:298)
        at android.view.LayoutInflater.tryCreateView(LayoutInflater.java:1067)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:995)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:1121)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:680)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
        at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:699)
2021-05-27 07:25:09.097 16273-16273/com.example.quiz E/AndroidRuntime:     at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:195)
        at com.example.quiz.ui.activities.DashboardActivity.onCreate(DashboardActivity.kt:15)
        at android.app.Activity.performCreate(Activity.java:8198)
        at android.app.Activity.performCreate(Activity.java:8182)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3765)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3968)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:246)
        at android.app.ActivityThread.main(ActivityThread.java:8512)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
2021-05-27 07:25:09.166 16273-16273/com.example.quiz I/Process: Sending signal. PID: 16273 SIG: 9

Quiz.kt file

package com.example.quiz.models

import android.os.Parcelable
import kotlinx.android.parcel.Parcelize

@Parcelize
data class Quiz(
    val user_id: String = "",
    var quiz_id: String = "",
    val quiz_name: String = "",
    val num_participants: String = "",
    val num_questions: String = "",
    val duration: String = ""

) : Parcelable

DashboardActivity.kt

package com.example.quiz.ui.activities

import android.os.Bundle
import androidx.core.content.ContextCompat
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.example.quiz.R

class DashboardActivity : BaseActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_dashboard)
        
        supportActionBar!!.setBackgroundDrawable(
            ContextCompat.getDrawable(
                this@DashboardActivity,
                R.drawable.app_gradient_color_background
            )
        )

        val navView: BottomNavigationView = findViewById(R.id.nav_view)

        val navController = findNavController(R.id.nav_host_fragment)
        val appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.navigation_quizzes,
                R.id.navigation_dashboard
            )
        )
        setupActionBarWithNavController(navController, appBarConfiguration)

        navView.setupWithNavController(navController)
    }

    override fun onBackPressed() {
        doubleBackToExit()
    }
}

DashboardItemListAdapter.kt

package com.example.quiz.ui.adapters

import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.quiz.R
import com.example.quiz.models.Quiz
import kotlinx.android.synthetic.main.item_list_layout.view.*


open class DashboardItemsListAdapter(
    private val context: Context,
    private var list: ArrayList<Quiz>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {


    private var onClickListener: OnClickListener? = null

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return MyViewHolder(
            LayoutInflater.from(context).inflate(
                R.layout.item_dashboard_layout,
                parent,
                false
            )
        )
    }


    @SuppressLint("SetTextI18n")
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val model = list[position]

        if (holder is MyViewHolder) {

            holder.itemView.tv_quiz_name.text = model.quiz_name
            holder.itemView.tv_participants.text = model.num_participants
            holder.itemView.tv_questions.text = model.num_questions
            holder.itemView.tv_duration.text = model.duration

            holder.itemView.setOnClickListener {
                if (onClickListener != null) {
                    onClickListener!!.onClick(position, model)
                }
            }
        }
    }

    override fun getItemCount(): Int {
        return list.size
    }


    fun setOnClickListener(onClickListener: OnClickListener) {
        this.onClickListener = onClickListener
    }


    interface OnClickListener {

        fun onClick(position: Int, product: Quiz)
    }


    class MyViewHolder(view: View) : RecyclerView.ViewHolder(view)
}

QuizListAdapter.kt

package com.example.quiz.ui.adapters

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.quiz.R
import com.example.quiz.models.Quiz
//import com.example.Quiz.utils.GlideLoader
import kotlinx.android.synthetic.main.item_list_layout.view.*

open class QuizListAdapter(
    private val context: Context,
    private val list: ArrayList<Quiz>,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return MyViewHolder(
            LayoutInflater.from(context).inflate(
                R.layout.item_list_layout,
                parent,
                false
            )
        )
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {

        val model = list[position]

        if (holder is MyViewHolder) {

            holder.itemView.tv_quiz_name.text = model.quiz_name
            holder.itemView.tv_participants.text = model.num_participants
            holder.itemView.tv_questions.text = model.num_questions
            holder.itemView.tv_duration.text = model.duration

        }

    }

    override fun getItemCount(): Int {

        return list.size
    }

    class MyViewHolder(view: View) : RecyclerView.ViewHolder(view)
}

DashboardFragment.kt

package com.example.quiz.ui.fragments

import android.os.Bundle
import android.util.Log
import android.view.*
import androidx.recyclerview.widget.GridLayoutManager
import com.example.quiz.R
import com.example.quiz.firestore.FirestoreClass
import com.example.quiz.models.Quiz
import com.example.quiz.ui.adapters.DashboardItemsListAdapter
import kotlinx.android.synthetic.main.fragment_dashboard.*

class DashboardFragment : BaseFragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        return inflater.inflate(R.layout.fragment_dashboard, container, false)
    }

    override fun onResume() {
        super.onResume()

        getDashboardItemsList()
    }

    private fun getDashboardItemsList() {
        showProgressDialog("please_wait")

        FirestoreClass().getDashboardItemsList(this@DashboardFragment)
    }

    fun successDashboardItemsList(dashboardItemsList: ArrayList<Quiz>) {

        hideProgressDialog()

        for (i in dashboardItemsList) {
            Log.i("Item Title", i.quiz_name)
        }

        if (dashboardItemsList.size > 0) {

            rv_dashboard_items.visibility = View.VISIBLE
            tv_no_dashboard_items_found.visibility = View.GONE

            rv_dashboard_items.layoutManager = GridLayoutManager(activity, 1)
            rv_dashboard_items.setHasFixedSize(true)

            val adapter = DashboardItemsListAdapter(requireActivity(), dashboardItemsList)
            rv_dashboard_items.adapter = adapter

        } else {
            rv_dashboard_items.visibility = View.GONE
            tv_no_dashboard_items_found.visibility = View.VISIBLE
        }
    }
}

With the above code my app crashes after logging in entering the username and password, but when I remove the rv_dashboard_items.adapter = adapter at least the app does not crashes. However, it does not show any data from the Firestore at all.

I get the following errors when I run the app without rv_dashboard_items.adapter = adapter

The message in the following snippet was in red colour.

E/DashboardFragment: [DocumentSnapshot{key=quizzes/C8STnkYwp3cYWMxm1Y0xQWERTZq1, metadata=SnapshotMetadata{hasPendingWrites=false, isFromCache=false}, doc=Document{key=quizzes/C8STnkYwp3cYWMxm1Y0xQWERTZq1, version=SnapshotVersion(seconds=1621955183, nanos=678854000), type=FOUND_DOCUMENT, documentState=SYNCED, value=ObjectValue{internalValue=# com.google.firestore.v1.Value@1abc2d14
integer_value: 0
map_value {
  fields {
    key: "quiz_id"
    value {
      integer_value: 0
      string_value: "C8STnkYwp3cYWMxm1Y0xQWERTZq1"
    }
  }
  fields {
    key: "num_questions"
    value {
      integer_value: 0
      string_value: "10"
    }
  }
  fields {
    key: "quiz_name"
    value {
      integer_value: 0
      string_value: "Easy Quiz"
    }
  }
  fields {
    key: "duration"
    value {
      integer_value: 0
      string_value: "10"
    }
  }
  fields {
    key: "num_participants"
    value {
      integer_value: 0
      string_value: "5"
    }
  }
  fields {
    key: "user_id"
    value {
      integer_value: 0
      string_value: "C8STnkYwp3cYWMxm1Y0xQWERTZq1"
    }
  }
}}}}]

Also this line

E/RecyclerView: No adapter attached; skipping layout

QuizFragment.kt

package com.example.quiz.ui.fragments

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.quiz.R
import com.example.quiz.firestore.FirestoreClass
import com.example.quiz.models.Quiz
import com.example.quiz.ui.adapters.QuizListAdapter
import kotlinx.android.synthetic.main.fragment_quiz.*

class QuizFragment : BaseFragment() {

    private lateinit var mRootView: View


    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        mRootView = inflater.inflate(R.layout.fragment_quiz, container, false)
        return mRootView
    }

    fun successQuizListFromFireStore(quizList: ArrayList<Quiz>) {

        hideProgressDialog()

        if (quizList.size > 0) {
            rvQuizzesFrag.visibility = View.VISIBLE
            tv_no_products_found.visibility = View.GONE

            rvQuizzesFrag.layoutManager = LinearLayoutManager(activity)
            rvQuizzesFrag.setHasFixedSize(true)
            val adapterQuizzes = QuizListAdapter(requireActivity(), quizList)
            rvQuizzesFrag.adapter = adapterQuizzes

        } else {
            rvQuizzesFrag.visibility = View.GONE
            tv_no_products_found.visibility = View.VISIBLE
        }
    }


    private fun getQuizListFromFireStore() {

        showProgressDialog("Please_wait")
        FirestoreClass().getQuizList(this)
    }

    override fun onResume() {
        super.onResume()
        getQuizListFromFireStore()
    }
}

activity_dashboard.xml

    <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/nav_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="0dp"
        android:layout_marginEnd="0dp"
        android:background="@drawable/app_gradient_color_background"
        app:itemIconTint="@color/colorWhite"
        app:itemTextColor="@color/colorWhite"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/bottom_nav_menu" />

    <fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toTopOf="@id/nav_view"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/mobile_navigation" />


</androidx.constraintlayout.widget.ConstraintLayout>

fragment_dashboard.xml

    <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    tools:context=".ui.fragments.DashboardFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_dashboard_items"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_no_dashboard_items_found"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="no_dashboard_item_found"
        android:textAlignment="center"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

fragment_quiz.xml

    <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.fragments.QuizFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvQuizzesFrag"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_no_products_found"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:text="NO QUIZZES TODAY"
        android:textAlignment="center"
        android:textSize="30sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

FirestoreClass.kt

Import part of the code is deleted from the question as I exceed the character limit in the question.

package com.example.quiz.firestore


class FirestoreClass {

    private val mFireStore = FirebaseFirestore.getInstance()

    fun getDashboardItemsList(fragment: DashboardFragment) {
       
        mFireStore.collection("quizzes")
            .get() 
            .addOnSuccessListener { document ->

                Log.e(fragment.javaClass.simpleName, document.documents.toString())

                val quizList: ArrayList<Quiz> = ArrayList()

               
                for (i in document.documents) {

                    val qz = i.toObject(Quiz::class.java)!!
                    qz.quiz_id = i.id
                    quizList.add(qz)
                }

                fragment.successDashboardItemsList(quizList)
            }
            .addOnFailureListener { e ->
              
                fragment.hideProgressDialog()
                Log.e(fragment.javaClass.simpleName, "Error while getting dashboard items list.", e)
            }
    }


    fun getCurrentUserID(): String {
        // An Instance of currentUser using FirebaseAuth
        val currentUser = FirebaseAuth.getInstance().currentUser

        var currentUserID = ""
        if (currentUser != null) {
            currentUserID = currentUser.uid
        }

        return currentUserID
    }


    fun uploadProductDetails(activity: AddProductActivity, productInfo: Quiz) {

        mFireStore.collection("quizzes")
            .document()
          
            .set(productInfo, SetOptions.merge())
            .addOnSuccessListener {

              
                activity.productUploadSuccess()
            }
            .addOnFailureListener { e ->

                activity.hideProgressDialog()

                Log.e(
                    activity.javaClass.simpleName,
                    "Error while uploading the product details.",
                    e
                )
            }
    }

    fun getUserDetails(activity: Activity) {

        mFireStore.collection("users")
         
            .document(getCurrentUserID())
            .get()
            .addOnSuccessListener { document ->

                Log.i(activity.javaClass.simpleName, document.toString())

                val user = document.toObject(User::class.java)!!

                val sharedPreferences =
                    activity.getSharedPreferences(
                        Constants.MYAPP_PREFERENCES,
                        Context.MODE_PRIVATE
                    )

                val editor: SharedPreferences.Editor = sharedPreferences.edit()
                editor.putString(
                    Constants.LOGGED_IN_USERNAME,
                    "${user.firstName} ${user.lastName}"
                )
                editor.apply()

                when (activity) {
                    is LoginActivity -> {
                      
                        activity.userLoggedInSuccess(user)
                    }

                }
            }
            .addOnFailureListener { e ->
               
                when (activity) {
                    is LoginActivity -> {
                        activity.hideProgressDialog()
                    }
                }

                Log.e(
                    activity.javaClass.simpleName,
                    "Error while getting user details.",
                    e
                )
            }
    }


    fun getQuizList(fragment: Fragment) {
      
        mFireStore.collection("quizzes")
            .whereEqualTo("user_id", getCurrentUserID())
            .get() 
            .addOnSuccessListener { document ->

                Log.e("Products List", document.documents.toString())

                val productsList: ArrayList<Quiz> = ArrayList()

                for (i in document.documents) {

                    val product = i.toObject(Quiz::class.java)
                    product!!.quiz_id = i.id

                    productsList.add(product)
                }

                when (fragment) {
                    is QuizFragment -> {
                        fragment.successQuizListFromFireStore(productsList)
                    }
                }
            }
            .addOnFailureListener { e ->
               
                when (fragment) {
                    is QuizFragment -> {
                        fragment.hideProgressDialog()
                    }
                }

                Log.e("Get Product List", "Error while getting product list.", e)
            }
    }


    fun getAllQuizList(activity: Activity) {
       
        mFireStore.collection("quizzes")
            .get() 
            .addOnSuccessListener { document ->

                Log.e("Products List", document.documents.toString())

                val productsList: ArrayList<Quiz> = ArrayList()

                for (i in document.documents) {

                    val product = i.toObject(Quiz::class.java)
                    product!!.quiz_id = i.id

                    productsList.add(product)
                }

            }
            .addOnFailureListener { e ->
                Log.e("Get Product List", "Error while getting all product list.", e)
            }
    }

}

Upvotes: 0

Views: 226

Answers (2)

Siri
Siri

Reputation: 941

After reading your code, I think the reason for this is: there may be some minor problems with the use of your recycleView.

In your code, you seem to use two recycleView in the same place of xml, one is the recycleView with no data, and the other is the recycleView after getting the data asynchronously. And then control the display and hiding of recycleView in the function of getting data?

However, if you do not initialize the recyclerview immediately after attaching it to the Fragment, you may see No adapter attached; skipping layout.

Solution: Just set a recycleView, and set an empty data to it in the initialization function of Fragment/activity. DashboardItemsListAdapter(requireActivity(), listOf<Quiz>())

Part of the code:


private lateinit var adapter: DashboardItemsListAdapter

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    adapter = DashboardItemsListAdapter(requestActivity(), arrayListOf<Quiz>())
}

fun successDashboardItemsList(dashboardItemsList: ArrayList<Quiz>) {
    adapter.list = dashboardItemsList
    adapter.notifyDataSetChanged()
}



I just provide one of my thoughts here. You cannot set a new adapter every time you call successDashboardItemsList(). Before calling successDashboardItemsList(), your adapter should be initialized (there may be no data) . Every time successDashboardItemsList() is called, Re-assign the value of the list field of the Adapter object. And call the notifyDataSetChanged() of the Adapter object, so that the problem can be solved.


import android.os.Bundle
import android.util.Log
import android.view.*
import androidx.recyclerview.widget.GridLayoutManager
import com.example.quiz.R
import com.example.quiz.firestore.FirestoreClass
import com.example.quiz.models.Quiz
import com.example.quiz.ui.adapters.DashboardItemsListAdapter
import kotlinx.android.synthetic.main.fragment_dashboard.*

class DashboardFragment : BaseFragment() {

    private lateinit var adapter: DashboardItemsListAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_dashboard, container, false)
    }



    private lateinit var recyclerView: RecyclerView

    private lateinit var textView: TextView

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        recyclerView = view.findViewById<RecyclerView>(R.id.rv_dashboard_items)
        textView = view.findViewById(R.id.tv_no_dashboard_items_found)
        adapter = DashboardItemsListAdapter(requireActivity(), arrayListOf<Quiz>())
        recyclerView.layoutManager = GridLayoutManager(requireContext(), 1)
        recyclerView.setHasFixedSize(true)
        recyclerView.adapter = adapter
    }

    override fun onResume() {
        super.onResume()

        getDashboardItemsList()
    }

    private fun getDashboardItemsList() {
        showProgressDialog("please_wait")

        FirestoreClass().getDashboardItemsList(this@DashboardFragment)
    }

    fun successDashboardItemsList(dashboardItemsList: ArrayList<Quiz>) {

        hideProgressDialog()

        for (i in dashboardItemsList) {
            Log.i("Item Title", i.quiz_name)
        }

        if (dashboardItemsList.size > 0) {

            recyclerView.visibility = View.VISIBLE
            textView.visibility = View.GONE

            adapter.list = dashboardItemsList
            adapter.notifyDataSetChanged()
        } else {
            recyclerView.visibility = View.GONE
            textView.visibility = View.VISIBLE
        }
    }
}

DashboardItemListAdapter.kt

change into:

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
         return MyViewHolder(
             LayoutInflater.from(context).inflate(
                 R.layout.item_list_layout,
                 parent,
                 false
             )
         )
     }

Upvotes: 1

laalto
laalto

Reputation: 152867

In your DashboardItemsListAdapter you are inflating item_dashboard_layout but you're importing synthetic bindings for fragment_dashboard.

The inflated layout likely does not contain views that would be required by the fragment_dashboard binding, hence the binding returns nulls.

Make sure you're using the same layout for both inflating and view binding.

Upvotes: 1

Related Questions