• Android 插件开发框架 总结


    1)类转载器ClassLoader:
     标准的javaSDK中有ClassLoader类,ClassLoader 加载类的方式常称为双亲委托,ClassLoader.java 具体代码如下:
    1. protectedClassloadClass(StringclassName,booleanresolve)throwsClassNotFoundException{
    2. Classclazz=findLoadedClass(className);
    3. if(clazz==null){
    4. try{
    5. clazz=parent.loadClass(className,false);
    6. }catch(ClassNotFoundExceptione){
    7. // Don't want to see this.
    8. }
    9. if(clazz==null){
    10. clazz=findClass(className);
    11. }
    12. }
    13. returnclazz;
    14. }

     
    loadClass 会先看这个类是不是已经被 loaded 过,没有的话则去他的 parent 去找,如此递归,称之为双亲委托。
    在Android中可以动态加载,但无法像Java中那样方便动态加载jar。原因:Android的虚拟机(Dalvik VM)是不认识Java打出jar的byteCode,需要通过dx工具来优化转换成Dalvik byteCode才行。项目中,引入其他Jar的内容都被打包进了classes.dex。dex文件是Android系统将所需要的所有Class文件重新打包,打包时并进行了优化。
    DexClassLoader 可以加载jar/apk/dex,也可以从SD卡中加载.
    PathClassLoader 只能加载已经安装到Android系统中的apk文件。
    2)插件框架如何动态加载Activity。
    由于Activity需要在清单文件注册了才能使用,要么注册一个Activity基类,供插件中的Activity继承,在这个基类里做动态加载的核心逻辑,这就要求插件必须依赖某种API类库。
    要么就是依赖倒转,不让插件依赖框架API,而是反过来,自动生成一个Activity类依赖(继承)插件中的Activity,这个自动生成的类就叫PluginActivity
    并且声明在框架的清单文件中,如下: 

     
    原理1:Activity的启动都通过Instrumentation进行一步代理,重写Instrumentation可以得到Activity生命周期。重写 newActivity 方法构造自己的Activity对象返回给系统,这样以后onCreate等事件都入自动传入我们的Activity。也就是 在主程序的manifest中声明一个PluginActivity,当启动插件中activity A 时我们在Instrumentation的execStartActivity方法中告诉系统我要启动PluginActivity,但是当系统真正构造PluginActivity对象时我们在newActivity方法中 new A()对象返回系统。
    插件开发实践:
    1  关于服务
    这里所说的服务是指插件项目或者主项目提供的某种功能,这种功能的调用和实现一般是跨项目的存在的。
    插件和主项目之间的服务采用接口依赖的方式。
    跨项目调用服务,该服务必须在插件框架中注册。
    原则是:谁提供服务,谁注册服务,谁实现服务接口。调用服务只需要提供自己业务对应数据,并调用该接口的方法
    2 关于接口
    接口的设计目的是让插件和主项目之间的服务采用该接口相互依赖。同时,通过接口方法提供跨项目间传递数据的功能。
    通过接口方法传递数据方式无非两种, 一种是通过方法的参数来set,一种是通过get方法的返回值
    对于依赖接口的设计,尽量保证简洁,高效,低的耦合性。
    3 项目中的应用:
       1 ) 首先要搞清楚谁来提供服务,要明确该服务需要哪些数据,如何来调用。
             然后根据该服务写对应的依赖服务接口,以及接口中定义的抽象方法。
      2 ) 对于服务提供方:  实现该服务接口,向框架注册该服务。
             注册操作应该在插件的入口中执行。插件入口配置:Bundle-Activator=com.netease.plugin.webcontainer.MyActivator
            // 注册服务
           bundleContext.registerService(WebViewService.class.getName(),  new WebViewServiceImpl(), null);
              对于服务使用方:首先获取该服务,然后调用该服务的提供的方法。
            //获取服务
           mWebViewService = (WebViewService) PluginUtils  .getService(WebViewService.class.getName());
      
    注意: 在插件项目中提供的服务,主项目一般先启动,然后在使用该插件的服务之前一定要保证让插件项目启动起来,并注册了该服务。
    3) 在服务接口的实现类中的方法中启动对应的activity来完成该功能。 但是如果方法中没有获取到content,
       可以使用框架提供的全局的context即StartActivityService来跳转。
          
    1. StartActivityService sas = (StartActivityService) PluginUtils .getService(StartActivityService.class.getName());
    2. Intent intent = new Intent();
    3. intent.setClassName(PLUGIN_ID, WebViewActivity.class.getName());
    4. intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
    5. sas.StartActivity(PLUGIN_ID, intent);
  • 相关阅读:
    设计模式之解释器模式
    格式优雅的表单标签
    【小程序】微信小程序自定义组件Component详细总结
    TorchVision Transforms API 大升级,支持目标检测、实例/语义分割及视频类任务
    【Ribbon】SpringCloud的Ribbon负载均衡使用
    Anaconda的安装与卸载
    k8s高可用集群搭建(三)
    【Unity好插件之PlayMaker系列一上半部分】如何只用一个插件和一个脚本完成制作一个简易的游戏
    yolov5剪枝实战4: 正常训练和稀疏化训练
    Centos系统上安装包(软件)时常用的命令wget、rpm、yum分别是什么意思和作用?
  • 原文地址:https://blog.csdn.net/qyl10241024/article/details/49510957