Android插件化的思考——仿QQ一键换肤,思考比实现更重要!
关于QQ的换肤,他们的实现思路我不是很清楚,但是你可以看一下这张换肤的截图
我们想使用哪个主题就直接下载就好了,这一实现的过程我们大致的可以猜想:
首选是下载到本地指定文件夹,然后通过插件加载到我们的apk,最后应用为皮肤,逻辑大致是这样的逻辑了,那我们是不是应该动动手啊动动脑?
首选我们新建一个工程好了——PlugInSample
一.实现思路
其实说起来,这个插件的实现思路,确实是比较的麻烦,思来想去,还是一种办法比较靠谱,首先,我们刻意去获取手机上所有的安装的/未安装的程序,过滤掉没用的,留下我们的插件apk,我们的插件apk怎么去辨别呢?我们可用通过设置sharedUserId,然后用实体类把插件名称和包名保存下来,有了包名,就比较好说了,我们可用获取插件的上下文,也就是createPackageContext,然后就可以做点坏事了,我们可以去剖析我们的R文件
因为R文件里面都是静态的原因,我们很容易联想到反射机制,是的,我们可以再一次过滤掉无用的信息,通过我们的PathClassLoader去加载,访问我们的内加载器反射到我们的图片ID,也就是后面的那段数字,然后,嘿嘿,就可以使用了,是不是思路比较清晰了?这里要注意的就是图片命名统一,这样就比较号过来,那具体我们应该怎么做?
二.PlugIn主程序
我们写一个Spinner,每次切换就直接换肤怎么样?OK,每次换的时候就从插件APK里加载我们的图片资源,看起来是比较顺畅的逻辑,那我们具体该怎么做呢?
android:id="@+id/mLinearLayout"
xmlns:android="/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
android:id="@+id/mSpinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
1.初始化
/**
* 初始化View
*/
private void initView() {
//初始化控件
mSpinner = (Spinner) findViewById(R.id.mSpinner);
}
当然,我这刚应用就一个View,但是实际开发当中可不止,所以步骤一定要明了
2.获取所有的插件
/**
* 获取手机里的插件
*
* @return
*/
private List findPlugIn() {
mList = new ArrayList<>();
//获取相关信息
PackageManager mPackageManager = getPackageManager();
//获取卸载/未安装的安装包信息
List mUninstallPackage = mPackageManager.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
//遍历拿到我们的信息
for (PackageInfo info : mUninstallPackage) {
String pkgNmae = info.packageName;
//获取shareId,根据id判断是否是我们的ID
String shareUserId = info.sharedUserId;
if (!TextUtils.isEmpty(shareUserId)) {
//如果id相同
if (shareUse