使用ViewPager2切换Fragment后返回闪退

(一)具体报错

androidx.fragment.app.Fragment$InstantiationException: 
Unable to instantiate fragment com.yl.newtaobaounion.ui.fragment.HomeViewPagerFragment: could not find Fragment constructor 

(二)报错原因

无法实例化 fragment 找不到 Fragment 构造函数 android - 堆栈溢出 (stackoverflow.com)

为什么使用Fragment时必须提供一个无参的构造函数? - 简书 (jianshu.com)

使用Fragment必须提供一个空参构造,因为当Fragment因为某种原因重新创建时,会调用到onCreate方法传入之前保存的状态, 在instantiate方法中通过反射无参构造函数创建一个Fragment,并且为Arguments初始化为原来保存的值, 而此时如果没有无参构造函数就会抛出异常,造成程序崩溃。

在fragment类的空参源码注释中也有提到

/**
     * Constructor used by the default {@link FragmentFactory}. You must
     * {@link FragmentManager#setFragmentFactory(FragmentFactory) set a custom FragmentFactory}
     * if you want to use a non-default constructor to ensure that your constructor
     * is called when the fragment is re-instantiated.(默认构造器)
     *
     * 

It is strongly recommended to supply arguments with {@link #setArguments}     * and later retrieved by the Fragment with {@link #getArguments}. These arguments     * are automatically saved and restored alongside the Fragment.     (强烈建议使用setArguments()方法为fragment保存参数,使其在切换时可以找到原来的状态)     *     *

Applications should generally not implement a constructor. Prefer     * {@link #onAttach(Context)} instead. It is the first place application code can run where     * the fragment is ready to be used - the point where the fragment is actually associated with     * its context. Some applications may also want to implement {@link #onInflate} to retrieve     * attributes from a layout resource, although note this happens when the fragment is attached.     (创建fragment通常不建议自定义带有参数的构造,即建议使用空参构造,避免程序出现异常)     */    public Fragment() {        initLifecycle();   }

而我在使用Fragment时,只为其提供了一个有参构造,而没有提供无参构造,导致程序切换fragment后切换回来的时候崩溃

但我之所以只为其提供了一个有参构造是因为我只允许fragment被创建时是带有参数的,但若只提供无参构造,如何获取参数呢?

(三)解决办法

不自定义带参构造方法,直接编写一个静态的getInstance(要传入的参数)方法来获取fragment的实例,在此方法中调用空参构造创建Fragment的对象,并调用setArguments()方法为fragment保存状态。

kotlin示例如下:

class HomeViewPagerFragment : BaseFragment(),
    IRecommendDataCallback {
    companion object {
        lateinit var fragment: HomeViewPagerFragment
        //参数传递
        //使用fragment必须提供一个无参构造,
        // 因为当Fragment因为某种原因重新创建时,会调用到onCreate方法传入之前保存的状态,
        // 在instantiate方法中通过反射无参构造函数创建一个Fragment,并且为Arguments初始化为原来保存的值,
        // 而此时如果没有无参构造函数就会抛出异常,造成程序崩溃。
        fun getInstance(categoriesData: CategoriesData?): HomeViewPagerFragment {
            val args = Bundle()
            args.putSerializable("categoriesData", categoriesData)
            fragment = HomeViewPagerFragment()
            fragment.setArguments(args)
            return fragment
        }
    }
        //若后面的其他地方需要使用到我们传进来的参数,直接调用
        //arguments?.getSerializable("categoriesData") as CategoriesData即可
 }

你可能感兴趣的:(Android调试报错记录,android,kotlin)