学习自
https://www.jianshu.com/p/5eac94143bd6
首先是TypedArray进行一个定义,所以我们才能以src=...的形式去声明图片。所以我们需要关注TypedArray.getDrawable方法。其实他的本质还是像我们平时一样,通过Resource去获取drawable。
通过Resource去获取drawable的流程大致如下
先去找ResourceImpl的cache,没有的话就创建一个,它的创建依赖于AssetManager
而AssetManager的创建是和apk的路径进行一个绑定的
解决方案出来了:自己创建一个Resource对象,代码清晰明了
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
Resources superRes = getResources();
AssetManager assetManager = AssetManager.class.newInstance();
Method addAssetPathMethod = AssetManager.class.getDeclaredMethod("addAssetPath",String.class);
String skinPath = Environment.getExternalStorageDirectory().getAbsoluteFile()+ File.separator+"plugin.zip";
addAssetPathMethod.invoke(assetManager, skinPath);
Resources skinResources = new Resources(assetManager,superRes.getDisplayMetrics(),superRes.getConfiguration());
int bgId = skinResources.getIdentifier("main_bg","drawable","com.hc.skin");
Drawable bgDrawable = skinResources.getDrawable(bgId);
findViewById(R.id.activity_main).setBackgroundDrawable(bgDrawable);
} catch (Exception e) {
e.printStackTrace();
}
}
}
成功
所以实现插件换肤框架可以通过:
内置一套资源。
如果处于另外的皮肤状态,实现LayoutInflterFactory进行view的创建拦截,这是对于未在内存中的view进行一个换肤。
对于已在内存中的view换肤就注册到一个单例中,作为一个记录,在换肤的时候,进行一个皮肤的更换