关于利用java反射实现,Android 工程插件化的理解。个人认为并不是上下文的注入,而是调用。

1 篇文章 0 订阅
1 篇文章 0 订阅

最近在研究Android 工程的插件化,也可是说是热更新,让项目插件化,功能模块放到插件工程中,编译为插件apk。已实现在不重新安装开发包的基础上,达到更新项目功能模块的效果。当然也可以用于换肤

了很多网上的资料和视频,感觉有些地方还是很误导读者。所以在这里整理一下,关于java反射使Android 项目插件化的原理。

实际上是利用了java反射的原理和DexClassLoader 这个类,载入apk中的class类和资源。

  dexClassLoader = new DexClassLoader(dexpath,dexOutputPath, null, mContext.getClassLoader());
                AssetManager assetManager = AssetManager.class.newInstance();
                Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
                addAssetPath.invoke(assetManager, dexpath);
                resources = new Resources(assetManager,
                        mContext.getResources().getDisplayMetrics(),
                        mContext.getResources().getConfiguration());

执行了上面的代码,就可以得到两个类 一个是 Resources类型,一个是DexClassLoader类型

而关于很多文章中提到的,上下文注入,这里就误导了读者。实际上并不是把代理Activity的上下文注入到了插件apk中加载进来

Activity ,而只是代理Activity调用了插件apk中的接口。所以插件包中的apk实际上可以直接写成一个接口而不需继承Activity。这样也避免了代码的冗余。而且也免于覆盖很多没有必要处理的抽象类。写成下面的形式是完全没有问题的。实际上它只是一个接口而并不是一个Activity。所以其实很多开源的,在插件中继承Actitity是不对的。因为代码只是给代理Activity调用而已。只需要实现代理Activity中调用的接口就可以了。下面的代码中也把代理Activity的源代码放进来(BaseContainerActivity)。并没有完全覆盖公共接口中的所有方法,只是一个简单的示例。实际上还应该在代理的相应方法中调用公共接口的方法,以保证插件类中实现的方法被调用。关于公共接口,在插件工程和子工程中使用一模一样的包名和类名就可以了。

service 等等 BroadcastReceiver等其他的类型原理也是相同的就不累述了。实际上可以用于实现任何类中的代码的动态更改(可以随时从服务器是下载相应的apk,不需要重新安装)。个人觉得非常的灵活方便。

public  class   OpenActivity   implements OpenInterface {
    protected Activity activity;


    @Override
    public void onOpenStart() {

    }

    @Override
    public void onOpenResume() {

    }

    @Override
    public void onOpenPause() {

    }

    @Override
    public void onOpenStop() {

    }

    @Override
    public void onOpenDestroy() {

    }

    @Override
    public void onOpenCreate(Bundle savedInstanceState) {
        activity.setContentView(R.layout.activity_open);
        activity.findViewById(R.id.click).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(activity,"djfkjd",Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void setProxy(Activity proxyActivity) {
        this.activity=proxyActivity;
    }

}
public class BaseContainerActivity extends Activity {
    private static String classname;

    public static void setClassname(String classname) {
        BaseContainerActivity.classname = classname;
    }

    public static final String CLASSNAME="classname";
    private OpenInterface openInterface;
    LoaderPluginManager loaderPluginManager;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Log.e("classname",classname);
            loaderPluginManager = LoaderPluginManager.create(this, classname);
        try {
            DexClassLoader loader = loaderPluginManager.getClassLoader();
            Class clazz = loader.loadClass(classname);
            Constructor<?> localConstructor = clazz.getConstructor(new Class[]{});
            openInterface = (OpenInterface) localConstructor.newInstance(new Object[]{});

            openInterface.setProxy(this);

            openInterface.onOpenCreate(savedInstanceState);

        } catch (Exception e) {
            Log.e("载入class出错",e.getMessage());
            e.printStackTrace();
        }



    }

    @Override
    public ClassLoader getClassLoader() {

        if (loaderPluginManager == null) {
            return super.getClassLoader();
        } else {
            return loaderPluginManager.getClassLoader();
        }

    }

    @Override
    public Resources getResources() {
        if(loaderPluginManager==null){
            return  super.getResources();
        }else{
            return loaderPluginManager.getResource();
        }
    }

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值