您的位置:首页 > 其它

360插件化方案RePlugin学习笔记-插件使用宿主中的类

2018-03-07 08:46 441 查看
使用场景1:插件的xml布局中有以宿主的全类名作为节点的时候

在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()
}


用到反射的地方写起来代码比较多,真正用的时候还是要抽取放到工具类里,优化一下代码。

以上仅个人学习记录,如有疏漏或谬误,欢迎留言交流!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: