美文网首页
插件化换肤(1)

插件化换肤(1)

作者: EnzoRay | 来源:发表于2021-12-13 15:41 被阅读0次

如何实现插件化换肤

1.拿到App中要替换的view以及该view在App中的resId
2.通过该view的resId它拿到在App中的属性名字和类型等信息,然后通过这些信息拿到皮肤中的id,暂命名为skinId
3.把skinId设置给要替换的view

来看一个例子,我们新建一个TestActivity继承自AppCompatActivity :

public class TestActivity extends AppCompatActivity {

    private static final String TAG = TestActivity.class.getSimpleName();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);

        TextView mTvTest = findViewById(R.id.tv_test);
        Log.d(TAG, "The instance is:" + mTvTest);

        TextView textView = new TextView(this);
        Log.d(TAG, "The instance is:" + textView);
    }
}

布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tv_test"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

Manifest.xml里面的theme要继承Theme.AppCompat.Light.NoActionBar,运行到手机上后打印信息如下:
The instance is:androidx.appcompat.widget.AppCompatTextView
The instance is:android.widget.TextView

发现了吗?我们自己new出来的TextView与布局文件里的TextView不一样,说明sdk对布局文件里的TextView进行了改造。sdk里面具体是怎么实现的呢,我们来看看AppCompatActivity的onCreate()方法:

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        final AppCompatDelegate delegate = getDelegate();
        delegate.installViewFactory();
        delegate.onCreate(savedInstanceState);
        super.onCreate(savedInstanceState);
    }

其中第4行的delegate.installViewFactory()会调用AppCompatDelegateImpl的installViewFactory()方法,代码如下:

    @Override
    public void installViewFactory() {
        LayoutInflater layoutInflater = LayoutInflater.from(mContext);
        if (layoutInflater.getFactory() == null) {
            LayoutInflaterCompat.setFactory2(layoutInflater, this);
        } else {
            if (!(layoutInflater.getFactory2() instanceof AppCompatDelegateImpl)) {
                Log.i(TAG, "The Activity's LayoutInflater already has a Factory installed"
                        + " so we can not install AppCompat's");
            }
        }
    }

在这里设置了setFactory2为this,通过上一篇文章LayoutInflater.inflate参数配置,我们知道inflate()方法会通过createViewFromTag()来根据节点名创建View对象,如果mFactory2 != null,会调用mFactory2.onCreateView(parent, name, context, attrs),所以这里会调用AppCompatDelegateImpl的onCreateView(View parent, String name, Context context, AttributeSet attrs)方法,最终调用AppCompatViewInflater的createView(),在这里我们可以看到把TextView改造成AppCompatTextView的代码,这就是继承AppCompatActivity打印的布局的实例是AppCompatTextView的原因。

我们也可以模仿这种方法通过onCreateView()拿到view以及resId等信息。AppCompatActivity 的布局是通过setContentView()解析的,所以我们必须在setContentView()之前执行setFactory2()方法,同时我们还需要注意LayoutInflater中的setFactory2(Factory2 factory)代码如下:

    public void setFactory2(Factory2 factory) {
        if (mFactorySet) {
            throw new IllegalStateException("A factory has already been set on this LayoutInflater");
        }
        if (factory == null) {
            throw new NullPointerException("Given factory can not be null");
        }
        mFactorySet = true;
        if (mFactory == null) {
            mFactory = mFactory2 = factory;
        } else {
            mFactory = mFactory2 = new FactoryMerger(factory, factory, mFactory, mFactory2);
        }
    }

如果mFactorySet为true,会抛出异常,我们还需要提前把mFactorySet的值改为false,再执行setFactory2()方法。

相关文章

  • 插件化换肤(1)

    如何实现插件化换肤 1.拿到App中要替换的view以及该view在App中的resId 2.通过该view的re...

  • 插件化换肤

    插件化换肤的优点 1)换肤无闪烁,立即生效,无需重启APP,用户体验好2)扩展和维护方便,入侵性小,低耦合3)插件...

  • Android知识点

    1,知识点列表 1.1反射,泛型,源码,设计模式 1.2热更新,热修复,插件化换肤,插件化架构,NDK图片压缩 1...

  • 插件式换肤框架搭建 - 插件式换肤框架的完善

    1. 概述 基于插件式换肤框架搭建 - 资源加载源码分析和插件式换肤框架搭建 - setContentView源码...

  • 插件化换肤的简介

    换肤有好几种方式,今天主要来看看插件化换肤的相关知识,本文主要涉及到的知识点: 、 、 、 1.setConten...

  • Android LayoutInflater inflate过程

    Android插件化换肤原理 1.Android View的加载流程分析 Activity的view都是通过set...

  • 初步了解安卓的主题更换

    换肤一般分为两种:插件换肤和主题换肤 插件换肤就是所谓的apk换肤,将需要更换的属性写好打成apk包放在asset...

  • 插件化换肤方案

    插件化换肤,需要考虑两个核心的问题。第一、如何收集到所有需要换肤的View,因为我们需要在换肤的时机中调用这些Vi...

  • 插件化换肤(2)

    上一篇文章里面我们已经拿到了App中的resId,通过下面的代码: 可以拿到属性的名字和类型,而属性名和类型在Ap...

  • Android Framework层整体执行流程高性能屏幕适配方

    应用场景:自定义View,APK加固,热修复,组件化,插件化,换肤,leakCanary,hilt,jetpack...

网友评论

      本文标题:插件化换肤(1)

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