Reputation: 769
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
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
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