一、目的
主app加载第三方apk提供的view,当view有变化时,只需更换三方app。优点:充分解耦,方便维护
二、实施
1、三方app需提供
(1)action:android.intent.action.CREATE_THIRD
<activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/TranslucentTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.CREATE_THIRD" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
(2)对外暴露的静态方法:
public static View createThirdView(Context hostContext, Context context, Bundle bundle) { Log.i("============", "createThirdView"); View view = LayoutInflater.from(context).inflate(R.layout.layout_view, null, false); return view; }
2、宿主app
(1)通过action查找revolveinfo信息,revolveinfo可提供包名和类名
(2)通过revolveinfo提供的包名,创建插件context
(3)插件context创建类加载器,配合类名获取类对象
(4)通过反射,由类获取到对应的方法,并调用方法
var action = "third_action" var funcName = "third_method" var pluginView: View? = null val packageManager = application.packageManager val intent = Intent(action) //1.查找action对应的resolveInfo信息 val resolveInfoList = packageManager.queryIntentActivities(intent, PackageManager.GET_META_DATA) if (resolveInfoList.isNotEmpty()) { val resolveInfo = resolveInfoList[0] if (resolveInfo.activityInfo == null) { return null } val packageName = resolveInfo.activityInfo.packageName val className = resolveInfo.activityInfo.name //2.创建插件上下文 val pluginContext = this.createPackageContext( packageName, Context.CONTEXT_INCLUDE_CODE or Context.CONTEXT_IGNORE_SECURITY ) //3.通过插件上下文,创建类加载器 val pluginClassLoader = PathClassLoader(pluginContext.packageResourcePath, pluginContext.classLoader) //4.通过类加载器加载类,并获取方法 val loadClass = pluginClassLoader.loadClass(className) val localMethod = loadClass.getMethod( funcName, Context::class.java, Context::class.java, Bundle::class.java ) //5.通过反射调用方法,获取view pluginView = localMethod.invoke( loadClass, application.applicationContext, pluginContext, Bundle() ) as View? }