美文网首页Android知识Android技术知识Android开发
【工作总结】Fragment 实例化浅析

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

作者: dongbingliu | 来源:发表于2017-06-21 19:30 被阅读112次
image.png

Fragment 实例化浅析


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

image_1bj569mk015od1s67jru1nj1rvq2q.png-247.4kBimage_1bj569mk015od1s67jru1nj1rvq2q.png-247.4kB

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

image_1bj56dsv41dp9haj1bge1c8liqm37.png-43.2kBimage_1bj56dsv41dp9haj1bge1c8liqm37.png-43.2kB image_1bj56emgi1e07gqt14kmmba13uv3k.png-31.2kBimage_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 打印正好是闪退异常时候打印,异常的确来源于此

image_1bj51c34q1fopo351136a664vf1j.png-127.9kBimage_1bj51c34q1fopo351136a664vf1j.png-127.9kB

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

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

查看newInstance()源码:


image_1bj523ip01f6s1ia413crsfodfi20.png-146.8kBimage_1bj523ip01f6s1ia413crsfodfi20.png-146.8kB

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

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


image_1bj52fst4dgc1f9s38kil81u92d.png-59.9kBimage_1bj52fst4dgc1f9s38kil81u92d.png-59.9kB

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

问题解决方案:

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

相关文章

网友评论

    本文标题:【工作总结】Fragment 实例化浅析

    本文链接:https://www.haomeiwen.com/subject/izetcxtx.html