博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从crash看kotlin-android-extensions工作原理
阅读量:5906 次
发布时间:2019-06-19

本文共 3473 字,大约阅读时间需要 11 分钟。

最近项目开始转kotlin其中用了官方推荐的kotlin-android-extensions,这次通过一次crash看kotlin-android-extensions免去findviewbyId的原理

1.一次crash的产生

引入kotlin-android-extensions这里不多做解释了,下面是一次fragment中不当使用kotlin-android-extensions导致crash的代码

override fun onCreateView(        inflater: LayoutInflater, container: ViewGroup?,        savedInstanceState: Bundle?    ): View? {        // Inflate the layout for this fragment        rootView = inflater.inflate(R.layout.fragment_blank, container, false)        //import kotlinx.android.synthetic.main.fragment_blank.*       textView.text = "123"  //其中textView 是fragment_blank.xml中的一个TextView控件的id        return rootView    }复制代码

此时会存在以下错误

Caused by: android.view.InflateException: Binary XML file line #0: Binary XML file line #0: Error inflating class fragment                                                                        Caused by: android.view.InflateException: Binary XML file line #0: Error inflating class fragment                                                                        Caused by: java.lang.IllegalStateException: textView must not be null                                                                           at com.zjw.mykotlinproject.BlankFragment.onCreateView(BlankFragment.kt:45)                                                                           at android.support.v4.app.Fragment.performCreateView(Fragment.java:2261)复制代码

好这个时候就有人说了fragment应该使用如下代码,可以解决这个异常

override fun onCreateView(        inflater: LayoutInflater, container: ViewGroup?,        savedInstanceState: Bundle?    ): View? {        // Inflate the layout for this fragment        rootView = inflater.inflate(R.layout.fragment_blank, container, false)        import kotlinx.android.synthetic.main.fragment_blank.view.*      //  rootView?.textView?.text = "123"        return rootView    }复制代码

可以解决,但是这一种方式是一次回避查看源码的机会,因为以上2种方式的原理是不一样的,那么怎么分析上述的异常呢,因为代码被kotlin-android-extensions动了手脚,因此直接看是看不懂的,什么你要看kotlin-android-extensions源码?你自己找找吧,反正我在本地找到的source.jar是空的,网上github上也没找到,就算找到也要花时间分析,我只想知道我现在的这个fragment到底被kotlin-android-extensions改成了什么样子而已,emmmm~嘤嘤嘤~,怎么办呢?以下将给出办法

2. 使用kotlin代码还原术!让插件给我生成的代码在我面前一览无余吧!

第一步

第二步

按了 Decompile 按钮之后

咦,onCreateView方法里面多了一个_$_findCachedViewById方法,在当前文件搜索这个方法可以看见实现如下图

到这里就清楚了,kotlin-android-extensions让你直接用id就能得到xml中的控件对象并且使用,其实是他生成了findviewbyId的代码我们开发者就方便了,这里注意到这句this.getView()这里才是产生crash的真正原因,因为`this.getView()调用时候onCreateView还没有返回,因此最后findViewById的时候就产生了问题。要避免crash的话同时不想用 rootView?.textView``这一长串代码的话就这样干

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {        super.onViewCreated(view, savedInstanceState)        textView.text = "123"        // Log.e(TAG,TAG)    }复制代码

好接着说 为什么下面代码使用正常

override fun onCreateView(        inflater: LayoutInflater, container: ViewGroup?,        savedInstanceState: Bundle?    ): View? {        // Inflate the layout for this fragment        rootView = inflater.inflate(R.layout.fragment_blank, container, false)        //import kotlinx.android.synthetic.main.fragment_blank.*        //textView.text = "123"        // import kotlinx.android.synthetic.main.fragment_blank.view.*        rootView?.textView?.text = "123"        return rootView    }复制代码

来继续反编译操作!看看真相

简单吧

// import kotlinx.android.synthetic.main.fragment_blank.view.*        rootView?.textView?.text = "123"复制代码

上述代码做的事情就是使用了rootView然后用rootView.findViewById 所以我上文才说这一种方式是一次回避查看源码的机会

3.思维扩展

通过反编译手段我们除了可以看见第三方插件对源码的改动以外,还能定位到java和kotlin之间如何相互翻译语义的,有的时候语义翻译不对会导致crash(具体例子有兴趣就加我和我讨论吧),当出现神奇的Bug的时候建议你往这方面想想

转载地址:http://becpx.baihongyu.com/

你可能感兴趣的文章
word中页码设置
查看>>
如何彻底删除文件,让文件没办法恢复,保证数据安全?
查看>>
使用Supervisor管理进程
查看>>
nodejs pm2配置使用教程
查看>>
The given object has a null identifier解决.
查看>>
GreenPlum简单性能测试与分析
查看>>
reactJS -- 10 独立组件间共享Mixins
查看>>
【HIMI转载推荐之三】基于Cocos2dx引擎UI扩展引擎包[cocos2d-x-3c]
查看>>
教大家提高Vista系统的安全
查看>>
bash的case语句,for语句
查看>>
《罗一笑,你给我站住》被指为P2P公司炒作
查看>>
轻量级 Linux 发行版CRUX 发布 3.4 版
查看>>
IPSEC-×××
查看>>
vim常用命令
查看>>
【python笔记 三 】python脚本实战---数字密码小游戏
查看>>
Liferay中页面的权限控制
查看>>
elasticsearch 5.1.1安装
查看>>
Java中存储金额用什么数据类型?
查看>>
maven报错需要引入这个
查看>>
Selenium+Python对开源中国官网进行模拟登录
查看>>