No1:

插件化技术的好处:

1)减轻应用的内存和CPU占用

2)实现热插拔,即在不发布新版本的情况下更新某些模块

No2:

插件化方案必须要解决三个基础性问题:资源访问、Activity生命周期的管理和ClassLoader的管理

No3:

宿主是指普通的apk,插件一般指经过处理的dex或者apk。插件化框架大多采用apk作为插件,很多需要用到代理Activity,插件Activity的启动大多数是借助一个代理Activity来实现的。

No4:

Activity的工作主要是通过ContextImpl来完成的,Activity中有一个交mBase的成员变量,它的类型就是ContextImpl。Context中有两个抽象方法getAssets和getResources,通过它们来获取资源的,真正实现在ContextImpl中。

No5:

资源访问

加载apk中的资源



protected void loadResources(){
try{
AssetManager assetManager = AssetManager.class.newInstance();
Method addAssetPath = assetManager.getClass().getMethod("addAssetPath",String.class);
addAssetPath.invoke(assetManager,mDexPath);
mAssetManager = assetManager;
}catch(Exception e){
e.printStackTrace();
}
Resources superRes = super.getResources();
mResources = new Resources(mAssetManager,superRes.getDisplayMetrics(),superRes.getConfiguration());
mTheme = mResources.newTheme();
mTheme.setTo(super.getTheme());
}


通过反射,调用AssetManager中addAssetPath方法,将一个apk中的资源加载到Resources对象中。然后通过AssetManager来创建一个新的Resources对象



public final int addAssetPath(String path){
synchronized(this){
int res = addAssetPathNative(path);
makeStringBlocks(mStringBlocks);
return res;
}
}


接着在代理Activity中实现getAssets和getResources



@Override
public AssetManager getAssets(){
return mAssetManager == null?super.getAssets():mAssetManager;
}

@Override
public Resources getResources(){
return mResources == null?super.getResources():mResources;
}


No6:

Activity生命周期的管理

反射方式



@Override
protected void onResume(){
super.onResume();
Method onResume = mActivityLifecircleMethods.get("onResume");
if(onResume!=null){
try{
onResume.invoke(mRemoteActivity,new Object[]{ })
}catch(Exception e){
e.printStackTrace();
}
}
}

@Override
protected void onPause(){
Method onPause = mActivityLifecircleMethods.get("onPause");
if(onPause!=null){
try{
onPause.invoke(mRemoteActivity,new Object[]{ })
}catch(Exception e){
e.printStackTrace();
}
}
super.onPause();
}


接口方式



public interface DLPlugin{
public void onStart();
public void onRestart();
public void onResume();
public void onPause();
public void onStop();
public void onDestroy();
...
}


代理Actvitiy中调用



...
@Override
protected void onStart(){
mRemoteActivity.onStart();
super.onStart();
}

@Override
protected void onRestart(){
mRemoteActivity.onRestart();
super.onRestart();
}

@Override
protected void onResume(){
mRemoteActivity.onResume();
super.onResume();
}


mRemoteActivity就是DLPlugin的实现

No7:

插件ClassLoader的管理



public class DLClassLoader extends DexClassLoader{
private static final String TAG ="DLClassLoader";
private static final HashMap<String,DLClassLoader> mPluginClassLoaders = new HashMap<String,DLClassLoader>();

protected DLClassLoader(String dexPath,String optimizedDirectory,String libraryPath,Classloader parent){
super(dexPath,optimizedDirectory,libraryPath,parent);
}

public static DLClassLoader getClassLoader(String dexPath,Context context,Classloader parentLoader){
DLClassLoader dLassLoader = mPluginClassLoaders.get(dexPath);
if(dLassLoader != null){
return DLClassLoader;
}

File dexOutputDir = context.getDir("dex",Context.MODE_PRIVATE);
final String dexOutputPath = dexOutputDir.getAbsolutePath();
dLClassLoader = new DLClassLoader(dexPath,dexOutputPath,null,parentLoader);
mPluginClassLoaders.put(dexPath,dLClassLoader);

return dLClassLoader;
}
}


 

通过将不同插件的ClassLoader存储在一个HashMap中,这样就可以保证不同插件中的类彼此互不干扰。