Issue
I am testing out the Room database and I am passing information between my List fragment and Update fragment. The list fragment contains a list of users in a RecyclerView stored by room, the update fragment should allow me to edit the data of users stored by room. So if I click on a user in list fragment, it should use navargs to pass the user object and prompt me to a screen with EditText views and that user data in the EditText fields. However, my android app crashes when I do this.
This is the error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.testingroomdatabase, PID: 9192
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.NoSuchMethodException: java.lang.Object.fromBundle [class android.os.Bundle]
at java.lang.Class.getMethod(Class.java:2072)
at java.lang.Class.getMethod(Class.java:1693)
at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:46)
at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:34)
at com.example.testingroomdatabase.realFragments.update.UpdateFragment.getArgs(Unknown Source:4)
at com.example.testingroomdatabase.realFragments.update.UpdateFragment.onCreateView(UpdateFragment.kt:23)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
This is the UpdateFragment:
package com.example.testingroomdatabase.realFragments.update
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.navArgs
import com.example.testingroomdatabase.R
import kotlinx.android.synthetic.main.fragment_update_fragment.*
import kotlinx.android.synthetic.main.fragment_update_fragment.view.*
class UpdateFragment : Fragment() {
private val args: UpdateFragmentArgs by navArgs()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_update_fragment, container, false)
view.updateFirstName_et.setText(args.currentUser.firstName)
view.updateLastName_et.setText(args.currentUser.lastName)
view.updateAge_et.setText(args.currentUser.age.toString())
// view.update_btn.setOnClickListener{}
return view
}
}
This is the ListFragment code
package com.example.testingroomdatabase.realFragments.list
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.testingroomdatabase.R
import com.example.testingroomdatabase.viewmodel.UserViewModel
import kotlinx.android.synthetic.main.fragment_list.view.*
class listFragment : Fragment() {
private lateinit var mUserViewModel: UserViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_list, container, false)
// Recycler View
val adapter = listAdapter()
val recyclerView = view.recyclerview
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(requireContext())
//UserViewModel
mUserViewModel = ViewModelProvider(this).get(UserViewModel::class.java)
mUserViewModel.readAllData.observe(viewLifecycleOwner,Observer{user ->
adapter.setData(user)
} )
view.floatingActionButton.setOnClickListener{
findNavController().navigate(R.id.action_listFragment_to_addFragment)
}
return view
}
}
Edit
This is the ListAdapter code which is the adapter for the RecyclerView and contains an onclicklistener for each list item which navigates to the UpdateFragment. This worked fine, but the error started when I tried to load up the user data into the text fields of the UpdateFragment.
package com.example.testingroomdatabase.realFragments.list
import android.view.View
import android.view.ViewGroup
import androidx.navigation.findNavController
import androidx.recyclerview.widget.RecyclerView
import com.example.testingroomdatabase.R
import com.example.testingroomdatabase.model.User
import kotlinx.android.synthetic.main.row_item.view.*
import org.jetbrains.anko.layoutInflater
class listAdapter: RecyclerView.Adapter<listAdapter.ViewHolder>(){
private var userList = emptyList<User>()
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
// return ViewHolder(layoutInflater.from(parent.context).inflate(R.layout.row_item, parent, false))
val view = parent.context.layoutInflater.inflate(
R.layout.row_item,
parent,
false
)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val currentItem = userList[position]
holder.itemView.id_text.text =currentItem.id.toString()
holder.itemView.firstName_text.text = currentItem.firstName
holder.itemView.lastName_text.text = currentItem.lastName
holder.itemView.age_text.text = currentItem.age.toString()
holder.itemView.row_layout.setOnClickListener{
val action = listFragmentDirections.actionListFragmentToUpdateFragment(currentItem)
holder.itemView.findNavController().navigate(action)
} //Navigates to Update Fragment
}
fun setData(user: List<User>){
this.userList = user
notifyDataSetChanged()
}
override fun getItemCount(): Int {
return userList.size
}
}
I am following a tutorial for this code. I can link that if needed. Thanks for any guidance.
Solution
I faced same issue on my application which is in production. I also use navArgs, I did some research and found something about usage of safeArgs. For now I switched from navArgs to UpdateFragmentArgs.fromBundle(requireArguments()).
Highly recommended is to read navArgs document part. I hope it will help you to solve your issue. it solved mine :)
Answered By - oalpayli
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.