Android app generating Exception: androidx.fragment.app.Fragment$Instantiationexception

Asked

Viewed 509 times

-2

My app is in production and I’m having a problem in a small part of the devices, I haven’t been able to identify the reason or at least reproduce the problem in a test environment, I did some research looking for more information, but without success, I would like the community to direct me to possible situations that may be generating this problem. My app is simple, it’s a news app and when it has new news the app notifies users.

The devices that presented the error:

  1. Samsung Galaxy A20 (A20), 2816MB RAM, Android 9
  2. Samsung Galaxy J4 (j4lte), 2048MB RAM, Android 9
  3. Motorola Moto G (5th Gen) (Cedric), 2048MB RAM, Android 8.1
  4. Samsung Galaxy J4 Core (j4corelte), 1024MB RAM, Android 8.1

As I don’t know which parts of the code are related to the problem, I didn’t put any specific class, but if anyone wants to just ask in the comments, for example I believe it is related to notification.

The error was captured straight from google play console.

java.lang.Runtimeexception:

at android.app.Activitythread.performLaunchActivity (Activitythread.java:3121) at android.app.Activitythread.handleLaunchActivity (Activitythread.java:3264) at android.app.servertransaction.LaunchActivityItem.execute (Launchactivityitem.java:78) at android.app.servertransaction.TransactionExecutor.executeCallbacks (Transactionexecutor.java:108) at android.app.servertransaction.TransactionExecutor.execute (Transactionexecutor.java:68) at android.app.Activitythread$H.handleMessage (Activitythread.java:1955) at android.os.Handler.dispatchMessage (Handler.java:106) at android.os.Looper.loop (Looper.java:214) at android.app.Activitythread.main (Activitythread.java:7078) at java.lang.reflect.Method.invoke (Native Method) at com.android.Internal.os.Runtimeinit$Methodandargscaller.run (Runtimeinit.java:494) at com.android.Internal.os.Zygoteinit.main (Zygoteinit.java:965)

Caused by: androidx.fragment.app.Fragment$Instantiationexception:

at androidx.fragment.app.Fragment.instantiate (Fragment.java:538)
at androidx.fragment.app.FragmentContainer.instantiate (Fragmentcontainer.java:57) at androidx.fragment.app.FragmentManagerImpl$6.instantiate (Fragmentmanagerimpl.java:2851) at androidx.fragment.app.FragmentState.instantiate (Fragmentstate.java:85) at androidx.fragment.app.FragmentManagerImpl.restoreSaveState (Fragmentmanagerimpl.java:2488) at androidx.fragment.app.FragmentController.restoreSaveState (Fragmentcontroller.java:195) at androidx.fragment.app.FragmentActivity.onCreate (Fragmentactivity.java:288) at androidx.appcompat.app.AppCompatActivity.onCreate (Appcompatactivity.java:106) at xxx.xxxx.xxxxx.MainActivity.onCreate (Mainactivity.kt:70) at android.app.Activity.performCreate (Activity.java:7339) at android.app.Activity.performCreate (Activity.java:7330) at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1275) at android.app.Activitythread.performLaunchActivity (Activitythread.java:3101)

Caused by: java.lang.Nosuchmethodexception:

at java.lang.Class.getConstructor0 (Class.java:2328) at java.lang.Class.getConstructor (Class.java:1725) at androidx.fragment.app.Fragment.instantiate (Fragment.java:523)

Part of the class the problem points to

Mainactivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState) // Linha 70
        setContentView(R.layout.activity_main)

        ...
}

Other classes that may be related to the problem

Pageradapter.kt

class PagerAdapter(val fragmentActivity: FragmentActivity, private var lista: MutableList<Blog>) : FragmentStateAdapter(fragmentActivity) {


    override fun getItemCount(): Int {
        return lista.size+1
    }

    override fun createFragment(position: Int): Fragment {

        return if(position<lista.size)
            Tab(lista[position])
        else
            OutraTab() // tab fixa no final

    }

}

Tab.kt

 class Tab(private val blog: Blog) : Fragment() {

        ...

        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
            val view = inflater.inflate(R.layout.tab, container, false)

        ...


        }

}

Outratab.kt

   class OutraTab : Fragment() {

        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
            val view = inflater.inflate(R.layout.tab_outra, container, false)

        ...


        }

    }

Obs. Outratab.kt is similar to Tab.kt, only without the parameter blog it contains fixed content.

  • Your question is very broad, you could discuss something like that at the goal (if I’m not mistaken). Here the questions need to be objective, describing a problem in a way that is answered directly and not argumentatively.

  • I understand, I know that the information I have is insufficient to solve, this is perhaps the difficulty to solve this problem, I have not been able to reproduce this error in a test environment, I still do not know what flow generates this error, but I believe that someone here in the community can identify some flow or logic error.. today I will perform new tests and then I will post some snippets of the code

  • All right, we expect details to help you and also, leave useful answers for people who in the future have the same problem.

  • The method androidx.fragment.app.Fragment.instantiate was depreciated.

  • @Augustovasques is true I was using in my Pageradapter the deprecated Fragmentstatepageradapter, I switched to Fragmentstateadapter, I also changed Viewpager to Viewpager2 which was also deprecated, Android Studio did not warn me about this, as I can not reproduce the error in the test scenario, I also changed a part of the flow of my app, to see if the error will persist and now I am putting in production and I will observe if the error will continue. Such depreciation may cause the reported error?

  • I think we moved on to this problem, the doubt was also that the problem pointed to line 70 of Mainactivity, line 70 is super.onCreate(savedInstanceState), only until then it had no sense, but now we realized that there was a problem in the interface (Belittled viewpager), usually when there is a problem in the interface that is the line that is pointed out by the error, someone correct me if I’m wrong..

  • 1

    @LSA " Can this depreciation cause the reported error?". Do not use depreciated methods. The standard is only one Android, but each manufacturer implements the endpoints of the API according to its hardware and maybe, it may be for some other reason, the manufacturer to save, memory, manpower or time development with obsolete material decides not to implement the depreciated methods in certain versions of the OS and so it happens that the code works in some brands/models and other brands/models does not work.

  • Okay, the app is already production, I will wait until the next few days to see if the problem has been solved, if it was I will post here what was done exactly in the code so that I can help other people with the same problem.

  • Class R references are sometimes lost and cause Runtime problems. But seeing the error, it seems to be related to the access data that is instantiating and not being able to display in Activitythread. Tried a new build of the application? Is the application giving error only in these models cited? Uses access API to display news?

  • I thought that replacing the deprecated components the problem would be solved, however the problem continues, in this new version released had a similar error in the device Motorola Moto G (5S) (Montana) android 8.1, however I’m having another question and do not know the side effects of this type of implementation, I’ll have to open another question to take this doubt and then come back here, if you will not run away from the theme. I also noticed that another application that I manage has the same error.

  • @Nellonidas I did a new build, but the error continues, this error it happens from time to time still not able to reproduce in test scenario, I can only see that it has not been fixed with the reports of google failures, probably occurs in other devices too, news is uploaded directly from the websites through the Jsoup library

  • I guess you haven’t solved the problem yet. Do all your fragments have a constructor with 0 arguments (default constructor)? If not, the problem may be this (and then I can draft an answer on)

  • @Rafaeltavares, not yet, but I am trying to correct, only the Fragment Outratab that has 0 arguments in the default constructor, I updated the answer and put the classes

Show 8 more comments

1 answer

1


Summary

Your fragments need a default constructor (no arguments) so that Android can recreate them when necessary (when changing the orientation of the phone, for example).

Explanation

When there is a change of configuration on Android (such as change in portrait orientation to landscape, or change of language), your Activity is recreated.

In the recreation process, the Fragments that will be recreated will have a call Construtor(), i.e., the constructor without arguments. The fact that you do not have this constructor generates the following error (which you specified):

Caused by: java.lang.NoSuchMethodException:
at java.lang.Class.getConstructor0 (Class.java:2328) at java.lang.Class.getConstructor

According to the documentation of configuration changes android:

Some device settings may change during runtime, such as screen orientation, keyboard availability, and multi-window mode activation. When a change occurs, Android needs to restart running Activity (onDestroy() is called, followed by onCreate()).

Restart behavior is designed to help the application adapt to new settings by automatically updating the application with alternative features that match the device configuration.

Solution with New Instance Pattern (Newinstance)

This pattern allows you to pass arguments to a fragment without creating a constructor other than the default one. The pattern exists in both Java how much in Kotlin, but below I explain the process in Kotlin. In the fragments documentation this standard is used.

  1. Create a method novaInstancia to instantiate your Fragment;
  2. Get the required arguments in this method and pass to onCreate through arguments;
  3. In the method onCreate, store values as attributes of your class Fragment.

Fragment code:

private const val ARG_MEU_ATRIBUTO = "meuAtributoId"

class MeuFragmento: Fragment() {
    private var meuAtributo: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            meuAtributo = it.getString(ARG_MEU_ATRIBUTO)
        }
    }

    companion object {
        fun novaInstancia(valorDoAtributo: String?) =
                MeuFragmento().apply {
                    arguments = Bundle().apply {
                        putString(ARG_MEU_ATRIBUTO, valorDoAtributo)
                    }
                }
    }
}

To instill your fragment:

val meuFragmento = MeuFragmento.novaInstancia("texto")

Newinstance with Android Studio

When you are creating a new fragment, leave the option "Include Fragment Factory methods?" and the code will be generated with the pattern described above.

Janela de criação de fragmento do Android Studio

Generated code:

// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"

/**
 * A simple [Fragment] subclass.
 * Use the [BlankFragment.newInstance] factory method to
 * create an instance of this fragment.
 */
class BlankFragment : Fragment() {
    // TODO: Rename and change types of parameters
    private var param1: String? = null
    private var param2: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            param1 = it.getString(ARG_PARAM1)
            param2 = it.getString(ARG_PARAM2)
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_blank, container, false)
    }

    companion object {
        /**
         * Use this factory method to create a new instance of
         * this fragment using the provided parameters.
         *
         * @param param1 Parameter 1.
         * @param param2 Parameter 2.
         * @return A new instance of fragment BlankFragment.
         */
        // TODO: Rename and change types and number of parameters
        @JvmStatic
        fun newInstance(param1: String, param2: String) =
                BlankFragment().apply {
                    arguments = Bundle().apply {
                        putString(ARG_PARAM1, param1)
                        putString(ARG_PARAM2, param2)
                    }
                }
    }
}
  • I get it, I’ll make the changes to the code and as soon as I check that the problem has been fixed I accept the answer as correct.

  • @LSA Did the above answer solve your problem? Need help with something else?

  • Apparently yes, but I need a few more 2 to 3 3 days so that most of the users of the application are already using this latest version, now answers me, if possible, the fragment needs an empty constructor to recreate in these scenarios, but the context provides the arguments that the situation automatically asks for ? or if you need to recreate, the ARG_PARAM1 parameter would be "param1", or as in your example ARG_MEU_ATRIBUTO would be "mytribute"? I would need to create a "default" value in place of "mytax" for when this occurs ?

  • You do not need to enter a default value. Even after the fragment is recreated, the arguments continues to pass the value of novaInstancia in the onCreate. You can test this by putting a Log.d() to check past values

  • Perfect, it seems that the problem has been solved, about 95% of users are using the app now and I had no more reports from google play regarding this problem.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.