Android-skin-support: 实现原理

本文探讨了Android换肤框架的实现原理,重点分析了appcompat-v7包中的AppCompatActivity和AppCompatDelegate的源码,以及如何在Android-skin-support中应用这些思想。通过自定义LayoutInflaterFactory和重写系统组件,实现了对特定属性的换肤处理,降低了框架的侵入性,提高了兼容性。同时,文章也提到了在开发过程中遇到的问题和解决方案。
摘要由CSDN通过智能技术生成

背景

换肤方案原理在网上已经很多了, 这里不再详细描述, 强迫症的我总是想让提供给别人使用的SDK尽量好用, 哪怕是给自己带来额外的工作量, 经过一段时间的奋斗, 实现了一个自我感觉良好的换肤框架.

这里主要来看看Android 源码中”com.android.support:appcompat-v7”包的实现, 以及源码思想在Android-skin-support中的应用 – 如何打造一款好用的换肤框架.

appcompat-v7包实现

首先来看一下源码的实现:
AppCompatActivity源码

public class AppCompatActivity extends FragmentActivity {
   
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        final AppCompatDelegate delegate = getDelegate();
        delegate.installViewFactory();
        delegate.onCreate(savedInstanceState);
        ...
    }

    @Override
    public MenuInflater getMenuInflater() {
        return getDelegate().getMenuInflater();
    }

    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        getDelegate().setContentView(layoutResID);
    }

    @Override
    public void setContentView(View view) {
        getDelegate().setContentView(view);
    }
    ....
}

AppCompatActivity 将大部分生命周期委托给了AppCompatDelegate

再看看相关的类图
这里写图片描述

AppCompateDelegate的子类AppCompatDelegateImplV9

class AppCompatDelegateImplV9 extends AppCompatDelegateImplBase
        implements MenuBuilder.Callback, LayoutInflaterFactory {
    @Override
    public void installViewFactory() {
        LayoutInflater layoutInflater = LayoutInflater.from(mContext);
        if (layoutInflater.getFactory() == null) {
            LayoutInflaterCompat.setFactory(layoutInflater, this);
        } else {
            if (!(LayoutInflaterCompat.getFactory(layoutInflater)
                    instanceof AppCompatDelegateImplV9)) {
                Log.i(TAG, "The Activity's LayoutInflater already has a Factory installed"
                        + " so we can not install AppCompat's");
            }
        }
    }
}

从这可以看出通过实现LayoutInflaterFactory接口来实现换肤至少可以支持到api 9以上

网上很多换肤框架的实现, 通过LayoutInflater.setFactory的方式, 在回调的onCreateView中解析每一个View的attrs, 判断是否有已标记需要换肤的属性, 比方说background, textColor, 或者说相应资源是否为skin_开头等等.
然后保存到map中, 对每一个View做for循环去遍历所有的attr, 想要对更多的属性进行换肤, 需要Activity实现接口, 将需要换肤的View, 以及相应的属性收集到一起
那么是不是能够寻求一种让使用者更方便的方式来实现, 做一个侵入性尽量小的框架呢?

本着开发者应有的好奇心, 深入的研究了一些v7包的实现
onCreate
setContentView
AppCompatDelegateImplV9中, 在LayoutInflaterFactory的接口方法onCreateView 中将View的创建交给了AppCompatViewInflater

@Override
public final View onCreateView(View parent, String name,
        Context context, AttributeSet attrs) {
    
  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值