【工作总结】Fragment 实例化浅析

【工作总结】Fragment 实例化浅析_第1张图片
image.png

Fragment 实例化浅析


智能微投项目中,蓝牙遥控器与 Device 连接成功后,按返回键,设置出现闪退,定位打印如下:

【工作总结】Fragment 实例化浅析_第2张图片
image_1bj569mk015od1s67jru1nj1rvq2q.png-247.4kB

查看并分析打印信息,闪退的打印信息以前也出现过,但没有重视,在微投项目中百分百复现,关键打印信息如下:

image_1bj56dsv41dp9haj1bge1c8liqm37.png-43.2kB
image_1bj56dsv41dp9haj1bge1c8liqm37.png-43.2kB
image_1bj56emgi1e07gqt14kmmba13uv3k.png-31.2kB
image_1bj56emgi1e07gqt14kmmba13uv3k.png-31.2kB
Caused by: android.support.v4.app.Fragment$InstantiationException: 
Unable to instantiate fragment ,
make sure class name exists, is public, 
and has an empty constructor that is public

定位问题出现在make sure class name exists, is public, and has an empty constructor that is public

异常的原因是没有 Fragment 无参数 public 构造函数,添加 Public 无参构造函数后,微投项目问题解决,但为什么其他项目能正常运行,而微投在蓝牙配对后会出现闪退。

查看Fragment 源码Instantiation方法:
This is the same as calling its empty 构造函数,instantiate 函数catch 打印正好是闪退异常时候打印,异常的确来源于此

【工作总结】Fragment 实例化浅析_第3张图片
image_1bj51c34q1fopo351136a664vf1j.png-127.9kB

instantiate 函数功能是通过 Java 反射机制实例化 Fragment;

Fragment f = (Fragment)clazz.newInstance();

查看newInstance()源码:


【工作总结】Fragment 实例化浅析_第4张图片
image_1bj523ip01f6s1ia413crsfodfi20.png-146.8kB

The class is instantiated expression with an empty argument list
类被实例化需无参 构造函数;

查看Fragment 无参构造函数源码:


【工作总结】Fragment 实例化浅析_第5张图片
image_1bj52fst4dgc1f9s38kil81u92d.png-59.9kB

总结:当系统因为内存紧张杀死非前台进程(并非真正的杀死),然后我们将被系统杀掉的非前台app带回前台,如果这个时候有UI是呈现在Fragment中,那么会因为restore造成fragment需要通过反射实例对象,从而将之前save的状态还原,而这个反射实例对象就是fragment需要Public的empty constructor的关键所在

问题解决方案:

  1. 添加 public 无参构造函数;
  2. 在含有参数的 Fragment 构造函数上添加注解@SuppressLint("ValidFragment")(避免使用非默认构造函数,因为Fragment源码中用到反射构造了对象,是无参数的构造函数)

你可能感兴趣的:(【工作总结】Fragment 实例化浅析)