当前位置:   article > 正文

Android换肤原理_android 换肤原理

android 换肤原理

 提到换肤,我的第一反应就是if+else去弄(俗称静态换肤),这样带来的结果就是代码臃肿,扩展性非常差,所以pass掉。那么动态换肤就不会存在这个问题,弄懂原理,加上AOP的思想去干,就类似于插件化了。

那么它的原理是怎样的呢?下面让我们来看:

都知道Acitivity的setContentView是用来设置布局的,而我们的换肤功能就是要动态改变控件的属性值,所以从setContentView的源码走起。

setContentView -> getDelegate().setContentView(layoutResID)  -> AppCompatDelegateImpl.setContentView(int id) -> LayoutInflater.from(mContext).inflate(resId, contentParent); -> return inflate(parser, root, attachToRoot); -> final View temp = createViewFromTag(root, name, inflaterContext, attrs); -> View view = tryCreateView(parent, name, context, attrs);

在tryCreateView这个方法里,我们就会发现一个变量名为mFactory2的东东,是通过它的onCreateView方法去创建控件的,仔细一看,这个LayoutInflate类里的一个接口,继续找它的实现方法,在AppCompatDelegateImpl这个类,实现了该接口以及该方法,一路狂点,直达最核心源码,最终发现在这个类里的createView方法看到了创建控件的代码。

 再点进去一看,

 原来的TextView被替换成了AppCompatTextView,至此,我们可以想象,他们能替换,为什么我们不能替换呢?  是不是我自己弄一个mFactory2的实例,我也能创建我想要的东西呢?之前我们已经看到是通过mFactory2来创建view,那么接下来,我们就要寻找这个东西是在哪里使用的,该如何去使用它?

还是回到MainActivity(又回到最初的起点,呆呆的。。。点进去看源码!!!)

从super.onCreate -> delegate.installViewFactory(); ->AppCompatDelegateImpl.installViewFactory -> LayoutInflaterCompat.setFactory2 -> LayoutInflater.setFactory2

可以看出,是在这里设置了mFactory2

接下来我们做个测试,把xml布局文件里的TextView动态改成Button

布局文件 activity_test

通过代码设置自定义mFactory2

运行看结果

 

 没错,一个活生生的TextView已经被拦截修改为Button,于是,换肤的思路大概就出来了,拦截->修改!!

有一个要注意的小地方,设置mFactory2要在super.onCreate之前,因为在源码的LayoutInflater.setFactory2这个方法中,已经有明确的错误抛出

可以看出,条件就是mFactorySet这个标识,如果是在 super.onCreate之后,这个标识已经被修改为true(如第二个箭头所示),但是如果非要在super.onCreate之后,也不是不可以,通过反射修改这个标识的值为false,我们还是愉快的运行代码- -

好啦,通过源码知道了系统的运行顺序以及逻辑,那么接下来我们就采用AOP的思想,动手做我们的换肤。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/86925
推荐阅读
相关标签
  

闽ICP备14008679号