I have an application that's supposed to open a popup dialog when the user clicks on the item but crashes when clicked. It started crashing as I added the (this as AppCompatActivity).supportFragmentManager line. Heres the code for the adapter pls help!!
class CategoryAdapter(var context: Context ,private val workoutList: ArrayList<CategoryModel?>): RecyclerView.Adapter<CategoryAdapter.ViewHolder>() {
inner class ViewHolder(private val itemBinding: WorkoutsListRowBinding): RecyclerView.ViewHolder(itemBinding.root) {
fun bindItem(item: CategoryModel, position: Int) {
itemBinding.workoutItem.text = item.name
(this as AppCompatActivity).supportFragmentManager
if (position % 2 == 0) {
itemBinding.workoutItem.setBackgroundColor(Color.parseColor("#072227"))
itemBinding.workoutItem.setTextColor(Color.parseColor("#FFFFFF"))
}
else {
itemBinding.workoutItem.setBackgroundColor(Color.parseColor("#FFFFFF"))
itemBinding.workoutItem.setTextColor(Color.parseColor("#000000"))
}
itemBinding.workoutItem.setOnClickListener{
var dialog = CustomDialogFragment()
dialog.show(supportFragmentManager, "customDialog")
Snackbar.make(itemView, "${item.name}", Snackbar.LENGTH_SHORT).show()
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val itemBinding = WorkoutsListRowBinding
.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(itemBinding)
}
override fun getItemCount() = workoutList.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindItem(workoutList[position]!!, position)
}
}
Here's the code for the fragment
class WorkoutListFragment : Fragment() {
private lateinit var categoryAdapter: CategoryAdapter
private lateinit var binding: FragmentWorkoutListBinding
var workoutList = ArrayList<CategoryModel?>()
var workoutDAO: CategoryDAO = CategoryDaoArrayList()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentWorkoutListBinding.inflate(inflater, container, false)
val view = binding.root
populateList()
categoryAdapter = CategoryAdapter(requireActivity()!!.getApplicationContext()
,workoutList)
binding.workoutListView.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
binding.workoutListView.adapter = categoryAdapter
return view
}
fun populateList() {
workoutList = workoutDAO.getWorkouts()!!
}
}
As well as the code for the custom dialog
class CustomDialogFragment: DialogFragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val rootView: View = inflater.inflate(R.layout.custom_popup_dialogue, container, false)
return rootView
}
}
Error messages found in the logcat
2022-02-09 01:32:18.137 7210-7210/com.mobdeve.s11.mco2.deleon.coronel.grnd E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mobdeve.s11.mco2.deleon.coronel.grnd, PID: 7210
java.lang.ClassCastException: com.mobdeve.s11.mco2.deleon.coronel.grnd.adapters.CategoryAdapter$ViewHolder cannot be cast to androidx.appcompat.app.AppCompatActivity
at com.mobdeve.s11.mco2.deleon.coronel.grnd.adapters.CategoryAdapter$ViewHolder.bindItem(CategoryAdapter.kt:26)
at com.mobdeve.s11.mco2.deleon.coronel.grnd.adapters.CategoryAdapter.onBindViewHolder(CategoryAdapter.kt:57)
at com.mobdeve.s11.mco2.deleon.coronel.grnd.adapters.CategoryAdapter.onBindViewHolder(CategoryAdapter.kt:20)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
at android.view.View.layout(View.java:17651)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1873)
at android.view.View.layout(View.java:17651)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at androidx.viewpager.widget.ViewPager.onLayout(ViewPager.java:1775)
at android.view.View.layout(View.java:17651)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1873)
at android.view.View.layout(View.java:17651)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:17651)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1873)
at android.view.View.layout(View.java:17651)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:17651)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
at android.view.View.layout(View.java:17651)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:17651)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
at android.view.View.layout(View.java:17651)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
2022-02-09 01:32:18.137 7210-7210/com.mobdeve.s11.mco2.deleon.coronel.grnd E/AndroidRuntime: at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:727)
at android.view.View.layout(View.java:17651)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2346)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2068)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1254)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6338)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
at android.view.Choreographer.doCallbacks(Choreographer.java:686)
at android.view.Choreographer.doFrame(Choreographer.java:621)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6138)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:893)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
this as AppCompatActivity doesn't make sense. Your adapter is not an activity, so you cannot cast your adapter as an activity and this will cause a ClassCastException crash.
If you need access to your fragment manager in this class, you need to add it as a property.
class CategoryAdapter(
val context: Context,
private val workoutList: List<CategoryModel>,
private val fragmentManager: FragmentManager
): RecyclerView.Adapter<CategoryAdapter.ViewHolder>() {
//...
}
Then you can use it in this class freely. The Fragment that instantiates this class can pass the fragment manager to the constructor, like this:
categoryAdapter = CategoryAdapter(requireActivity(), workoutList, requireActivity().supportFragmentManager)
However, following the OOP concept of separation of concerns, I think a better strategy is to expose a callback for your Activity to use. A view adapter shouldn't have to know about specific fragments and fragment transactions, etc.
class CategoryAdapter(
val context: Context,
private val workoutList: List<CategoryModel>,
private val onItemClicked: (CategoryModel)->Unit
): RecyclerView.Adapter<CategoryAdapter.ViewHolder>() {
//...
fun bindItem(item: CategoryModel, position: Int) {
itemBinding.workoutItem.text = item.name
if (position % 2 == 0) {
itemBinding.workoutItem.setBackgroundColor(Color.parseColor("#072227"))
itemBinding.workoutItem.setTextColor(Color.parseColor("#FFFFFF"))
}
else {
itemBinding.workoutItem.setBackgroundColor(Color.parseColor("#FFFFFF"))
itemBinding.workoutItem.setTextColor(Color.parseColor("#000000"))
}
itemBinding.workoutItem.setOnClickListener{
onItemClicked(item)
}
}
}
//...
and then in your Fragment that instantiates the adapter you can pass a listener that does the fragment transaction work, such as like this:
categoryAdapter = CategoryAdapter(requireActivity(), workoutList) { clickedItem ->
val dialog = CustomDialogFragment()
dialog.show(requireActivity().supportFragmentManager, "customDialog")
Snackbar.make(itemView, "${item.name}", Snackbar.LENGTH_SHORT).show()
}
Note I changed ArrayList to List. An ArrayList implies it will be mutated, but mutating a List that's being used by an adapter will cause bugs and crashes.