Android插件化开发实现动态换肤

今晚实在不想coding,于是想着整理点知识点,那么简单整理了下插件化开发实现动态更换皮肤。插件化开发大家应该不陌生或多或少用过或听过,插件化开发在项目业务拓展、模块化等方面有不小优势,当然实现一个完美的插件是有困难的。本文如果存在问题恳请指正!欢迎评论交流哦!
效果图:
这里写图片描述

1、换肤方案分析

  1. res下放多种皮肤的资源文件

  2. 加载插件apk使用其中的皮肤资源

方案一:
优点:容易实现。
缺点:res下放多种皮肤的资源文件,无疑会加大apk文件大小,而且资源文件是写死的,不利于后期拓展,若有其他皮肤需求只能通过版本迭代。
方案二:
优点:不会加大apk包,更容易扩展,有新的皮肤只需下载新的插件包即可,无需更新。(相对于方案一)
缺点:相对于方案一实现较困难,若有更多业务处理需要插件,如使用插件中的四大组件及处理它们的生命周期则是比较麻烦的,需用到动态代理。不过还好有360手机助手团队,在github上开源出来了DroidPlugin插件框架,https://github.com/Qihoo360/DroidPlugin,大家以后用这个就OK啦!

2、换肤实现分析

通过插件化实现更换皮肤,其实做的就是把插件apk中的皮肤资源文件拿到当前apk中使用而已。那么不妨先看下如何获取资源文件;

getResources().getDrawable(R.drawable.ic_launcher);

以上代码通过getResources()获取Resources对象,通过getDrawable(int id)获取Drawable对象,其中参数id R.drawable.ic_launcher是R文件类中的静态内部类drawable类的ic_launcher成员变量的值,如下。

public final class R {
   
    public static final class drawable {
   
        public static final int ic_launcher=0x7f020000;
    }
 }

那么如何加载一个插件apk中的资源文件呢?肯定也是先获取Resources对象,在获取Drawable对象。不过使用getResources()方法显然是不可行的,因为插件是一个apk,要想拿到里面的资源必须先把该apk加载到内存中来,然后利用反射拿到相关类的方法并使用。如果你对反射技术不是很了解可以看下http://blog.csdn.net/magic_jss/article/details/52187726;
基本步骤:

  • 通过DexClassLoader把插件apk加载到内存
  • 利用反射技术获取相关类的方法并使用,构造Resources对象

通过DexClassLoader加载插件apk,只需指定插件路径及创建一个优化目录即可,不在赘述,本文主要结合源码讲解如何通过反射构造Resources对象。

查看getResources()源码:

    //ContextThemeWrapper.java
    @Override
    public Resources getResources() {
   
        if (mResources != null) {
   
            return mResources;
        }
        if (mOverrideConfiguration == null) {
   
            mResources = super.getResources();
            return mResources;
        } else {
   
            Context resc = createConfigurationContext(mOverrideConfiguration);
            //通过源码可以看出mResources对象是通过Context的getResources()方法获取的,查看Context源码
            mResources = resc.getResources();
            return mResources;
        }
    }

查看Context源码:

	// 抽象类  则通过查看该类的实现类ContextImpl
	public abstract class Context {
   
		/** Return a Resources instance for your application's package. */
		// 抽象方法
		public abstract Resources getResources();
	}

查看ContextImpl源码:

    @Override
    public Resources getResources() {
   
        return mResources;
    }
    
    @Override
    public Context createConfigurationContext(Configuration overrideConfiguration) {
   
        if (overrideConfiguration == null) {
   
            throw new Ille
  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值