360插件化方案RePlugin学习笔记-插件使用宿主中的类
2018-03-07 08:46
441 查看
使用场景1:插件的xml布局中有以宿主的全类名作为节点的时候
在application配置RePluginConfig时,有一行代码是:
这行代码设置为true时,插件项目中找不到该类,会在宿主项目中查找。
使用场景2:插件代码中用到宿主项目的类及类中的字段、内部类等的时候
宿主项目类
在跳转到插件页面之前存储:
在跳转到插件页面之后取值,插件代码(使用反射)
使用场景3:插件调用宿主类中的方法
其实这个应该算是通信方式,通过场景2中的反射可以实现,还可以通过aidl进程中通信方式在宿主项目中暴露一些方法,供插件调用。
以在宿主中存储,在插件中通过aidl取值为例。
宿主项目在main下新建包,在包下新建aidl文件,结构如下图:
如图所示,新建ISpImpl类继承ISp.Stub,代码如下:
暴露出getString方法,在SampleApplication中注册全局的IBinder,在其他地方注册也行,但要在你调用aidl前注册:
插件项目中新建与宿主项目下包名一致的aidl,结构如下图:
代码中调用:
用到反射的地方写起来代码比较多,真正用的时候还是要抽取放到工具类里,优化一下代码。
以上仅个人学习记录,如有疏漏或谬误,欢迎留言交流!
在application配置RePluginConfig时,有一行代码是:
// 允许“插件使用宿主类”。默认为“关闭” c.setUseHostClassIfNotFound(true);
这行代码设置为true时,插件项目中找不到该类,会在宿主项目中查找。
使用场景2:插件代码中用到宿主项目的类及类中的字段、内部类等的时候
宿主项目类
/** * Created by qby on 2018/2/23 0023. * 演示“插件”使用“宿主”类 */ class SpUtil { companion object { fun builder(): SpBuilder { return SpBuilder() } } class SpBuilder { var sp: SharedPreferences? = null var str: String? = null fun getSp(context: Context): SpBuilder { if (sp == null) { synchronized(SpUtil::class.java) { if (sp == null) { sp = context.applicationContext.getSharedPreferences("testReplugin", Context.MODE_PRIVATE) } } } return this } fun putString(key: String, value: String): SpBuilder { sp!!.edit().putString(key, value).apply() return this } fun getString(key: String, defValue: String): SpBuilder { str = sp!!.getString(key, defValue) return this } } }
在跳转到插件页面之前存储:
SpUtil.builder().getSp(this).putString("first","测试")
在跳转到插件页面之后取值,插件代码(使用反射)
//获取宿主类加载器 val hostClassLoader = RePlugin.getHostClassLoader() //获取SpUtil类 val clazz = hostClassLoader.loadClass("com.test.qby.myapplication.utils.SpUtil") //取得内部类,只有一个SpBuilder val declaredClass = clazz.declaredClasses[0] //初始化SpBuilder 对象 val newInstance = declaredClass.newInstance() //得到getSp方法 val method0 = declaredClass.getDeclaredMethod( "getSp", Context::class.java) //调用getSp方法,将值赋给sp method0.invoke(newInstance, RePlugin.getHostContext()) //得到getString方法 val method1 = de b76f claredClass.getDeclaredMethod( "getString", String::class.java, String::class.java) //调用getString方法,将值赋给str method1.invoke(newInstance, "first", "默认") //得到getStr方法 val method2 = declaredClass.getDeclaredMethod("getStr") //调用getStr方法,获取str值 val get = method2.invoke(newInstance) //弹出提示 Toast.makeText(this, get.toString(), Toast.LENGTH_SHORT).show()
使用场景3:插件调用宿主类中的方法
其实这个应该算是通信方式,通过场景2中的反射可以实现,还可以通过aidl进程中通信方式在宿主项目中暴露一些方法,供插件调用。
以在宿主中存储,在插件中通过aidl取值为例。
宿主项目在main下新建包,在包下新建aidl文件,结构如下图:
如图所示,新建ISpImpl类继承ISp.Stub,代码如下:
/** * Created by qby on 2018/2/24 0024. * AIDL 实现类 */ class ISpImpl : ISp.Stub() { @Throws(RemoteException::class) override fun getString(key: String, defValue: String): String? { return SpUtil.builder().getSp(SampleApplication.getContext()).getString(key, defValue).str } }
暴露出getString方法,在SampleApplication中注册全局的IBinder,在其他地方注册也行,但要在你调用aidl前注册:
//注册全局IBinder,host为自定义注册的名字 RePlugin.registerGlobalBinder("host", ISpImpl())
插件项目中新建与宿主项目下包名一致的aidl,结构如下图:
代码中调用:
//根据名字获取注册的IBinder val globalBinder = RePlugin.getGlobalBinder("host") //获取ISp实现类 val asInterface = ISp.Stub.asInterface(globalBinder) try { //调用方法,获取返回值 val string = asInterface.getString("first", "尝试") //弹出提示 Toast.makeText(this, string.toString(), Toast.LENGTH_SHORT).show() } catch (e: RemoteException) { //捕获异常 e.printStackTrace() }
用到反射的地方写起来代码比较多,真正用的时候还是要抽取放到工具类里,优化一下代码。
以上仅个人学习记录,如有疏漏或谬误,欢迎留言交流!
相关文章推荐
- 360插件化方案RePlugin学习笔记-插件与宿主间的通信方式
- 360插件化方案RePlugin学习笔记-外置插件
- 360插件化方案RePlugin学习笔记-资源共享
- 360插件化方案RePlugin学习笔记-数据持久化
- 360插件化方案RePlugin学习笔记-汇总
- Qt插件使用的学习笔记
- [笔记]学习HighCharts的使用(不错的web图表插件)
- 学习笔记之pdf在线预览插件的使用(可以适应浏览器)
- UI学习笔记---EasyUI panel插件使用---03
- Hadoop学习笔记之五:使用Eclipse插件
- springmvc学习笔记--mybatis--使用插件自动生成实体和mapper
- PhoneGap/Cordova学习笔记--3.初次使用Cordova插件
- knockoutJS学习笔记09:使用mapping插件
- nodejs学习笔记三——nodejs使用富文本插件ueditor
- 使用jetty-maven-plugin插件进行测试---学习笔记
- iOS 学习笔记四 【xcode 7.3 ESJsonFormat-Xcode 插件不能使用的解决办法】
- Hadoop学习笔记—6.Hadoop Eclipse插件的使用
- 文字自动补全插件typeahead的使用(学习笔记)
- Git学习笔记(2)-Eclipse中Git插件使用
- SMP3.0学习笔记之十 使用Kapsel EncryptedStorage插件以及GET/POST对OData服务进行操作