Android换肤框架原理解析,实现皮肤随心换

前言

首先须知道系统资源如何加载,怎么拦截并替换资源,以下都有讲解

xml的View怎么解析的

从setContentView进入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RwMAtxbu-1652971781532)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220519203444503.png)]

一路走到下图这里

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-InVaseOu-1652971781534)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220519203603135.png)]![

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6xm8TyPt-1652971781535)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220519203710378.png)]

找到createViewFromTag

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EO0SCQfi-1652971781537)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220519203953032.png)]

操作几乎都在这里

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6hx12eyL-1652971781538)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220519204415460.png)]

进入tryCreateView()看看

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WahWtvQI-1652971781539)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220519204624512.png)]

那么mFactory2在哪里初始化了?

让我们进入oncreate

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NiU5HkY2-1652971781540)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220519204720559.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TbjHziez-1652971781542)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220519204759047.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ikc3UVLf-1652971781543)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220519204834131.png)]

那么如何拦截系统的创建流程?

直接使用系统的setFactory2方法

public class Factory2Activity extends AppCompatActivity {
   
   

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
   
   
        // 必须在 super 之前调用
        //name:view的名字 如 Textview,ListView
        //attrs:view里面的参数 如 宽高等
        LayoutInflater.from(this).setFactory2(new LayoutInflater.Factory2() {
   
   
            @Nullable
            @Override
            public View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context,
                                     @NonNull AttributeSet attrs) {
   
   
                return null;
            }

            @Nullable
            @Override
            public View onCreateView(@NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {
   
   
                return null;
            }
        });
        super.onCreate(savedInstanceState);
        // 如果想在super之后调用,需要反射  设置mFactorySet = false;
        setContentView(R.layout.activity_factory2);
    }
}

这个方法必须在super之前调用,因为setFactory2只能执行一次

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9jnqkN8Y-1652971781545)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220519205805402.png)]

如果原来界面上只有一个Textview,经过我下面操作会变成一个Button

LayoutInflater.from(this).setFactory2(new LayoutInflater.Factory2() {
   
   
    @Nullable
    @Override
    public View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context,
                             @NonNull AttributeSet attrs) {
   
   
        if (TextUtils.equals(name, "TextView")) {
   
   
            Button btn = new Button(Factory2Activity.this);
            btn.setText("我是一个按钮");
            return btn;
        }
        return null;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {
   
   
        return null;
    }
});

拦截后怎么做

因为这不能每一个activity里面都写一段,写在baseActivity里也比较low。况且如果把功能抽出来让别人使用也不方便。

答案:使用lifecycle实现Aop切面编程,来重写系统的创建过程的代码(复制)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mZJzkbPC-1652971781546)(C:\Users\Admin\AppData\Roaming\Typora\typora-user-images\image-20220519211008273.png)]

然后只要activity进入super.onCreate方法就会执行我们的onActivityCreated()。接下来看下onActivityCreated里的代码。

@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
   
   
    /**
     *  更新状态栏
     */
    SkinThemeUtils.updateStatusBarColor(activity);

    /**
     *  更新布局视图
     */
    //获得Activity的布局加载器
    LayoutInflater layoutInflater = activity.getLayoutInflater();

    try {
   
   
        //因为需在super之前调用,但现在在之后了,需要反射修改一下属性
        
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值