android插件化开发activity篇
来源:互联网 发布:淘宝水印怎么设置大小 编辑:程序博客网 时间:2024/06/05 07:33
现在都使用过支付宝吧,支付宝里边有好多功能就是采用插件化开发的,例如支付宝里边的小黄车,小蓝车等功能,都是采用的插件化做的。一开始我认为是WebView做的,
后来打开手机里的显示边框布局发现不是WebView,是原生的。他采用的是插件化加载第三方应用。
采用插件化开发的好处有宿主app与插件进行分开编译;并发开发节约时间和成本;按需要下载模块,但是第一次加载比较慢。
下边我们来讲解一下这个插件化开发:在进行插件化开发的时候要,有个桥梁将宿主APP和插件进行互相连接,这个连接也就是一个标准,那么这个标准是什么呢,就是一个
接口,让宿主app和插件都使用这套标准接口,这个接口就写有关activity的生命周期的方法。
/** * 两端都使用的标准 * Created by yzl on 2017/10/10. */public interface PayInterface { public void onCreate(Bundle savedInstance); public void onStart(); public void onResume(); public void onPause(); public void onStop(); public void onDestroy(); public void onSaveInstanceState(Bundle outState); public boolean onTouchEvent(MotionEvent event); public void onBackPressed(); public void attach(Activity activity);}
标准接口写好了,然后进行写插件,我们这里写简单的插件,两个activity的展示。
在插件里我们要抽出一个基类activity,BaseActivity。让她继承activity并实现PayInterface. 插件中的主activity(mainactivity)继承BaseActivity。
现在mainactivity中要查找控件,使用this是不可以的,因为MainActivity.this是系统注入如入的上下文,插件只可以使用宿主注入的上下文也就是这里的that(所以
在接口中写里attach(Activity,activity),这个拿到的上下文就是宿主APP注入的上下文。
** * * 重写关于上下文的父方法 * Created by yzl on 2017/10/10. */public class BaseActivty extends Activity implements PayInterface{ protected Activity that; @Override public void setContentView(@LayoutRes int layoutResID) { if(that == null){ super.setContentView(layoutResID); }else { that.setContentView(layoutResID); } } @Override public <T extends View> T findViewById(int id) { if(that == null){ return super.findViewById(id); }else { return that.findViewById(id); } } @Override public ClassLoader getClassLoader() { if(that == null){ return super.getClassLoader(); }else { return that.getClassLoader(); } } @NonNull @Override public LayoutInflater getLayoutInflater() { if(that == null){ return super.getLayoutInflater(); }else { return that.getLayoutInflater(); } } @Override public Window getWindow() { if(that == null){ return super.getWindow(); }else { return that.getWindow(); } } @Override public WindowManager getWindowManager() { if(that == null){ return super.getWindowManager(); }else { return that.getWindowManager(); } } @Override public void onCreate(Bundle savedInstance) { } @Override public void onStart() { } @Override public void onResume() { } @Override public void onPause() { } @Override public void onStop() { } @Override public void onDestroy() { } @Override public void onSaveInstanceState(Bundle outState) { } @Override public void attach(Activity activity) { this.that = activity; }}现在插件写好了,在说说宿主App。宿主app就是先加载在内存卡里存放的pak,然后找到要加载的activity的classname然后加载对应的class文件,在加载对应资源文件。public class MainActivity extends BaseActivty implements View.OnClickListener { private TextView tv_chajian; @Override public void onCreate(Bundle savedInstance) { super.onCreate(savedInstance); setContentView(R.layout.activity_main); tv_chajian = that.findViewById(R.id.tv_chajian); }}
这里加载很明显分为四步,apk文件,classname,class文件,资源文件。加载apk我们简单现在不说明,现在说说其余三个。现在我们写一个插件管理器pluginManger
工具类,将类设计为单利的,保证对象的唯一性。找加载的第一个activity的classname,
File dexOutFile = context.getDir("dex", Context.MODE_PRIVATE);dexClassLoader = new DexClassLoader(path,dexOutFile.getAbsolutePath(),null,context.getClassLoader());PackageManager packageManager = context.getPackageManager();PackageInfo packageInfo = packageManager.getPackageArchiveInfo(path,packageManager.GET_ACTIVITIES);entryActivityName = packageInfo.activities[0].name;接下来在准备资源,利用反射的方法zhao daoAssetManager assetManager = AssetManager.class.newInstance();Method addAssetPath = AssetManager.class.getMethod("addAssetPath",String.class);addAssetPath.invoke(assetManager,path);resources = new Resources(assetManager,context.getResources().getDisplayMetrics(),context.getResources().getConfiguration());pluginManger工具类的代码如下:/** * Created by yzl on 2017/10/10. */public class pluginManger { private Context context; private DexClassLoader dexClassLoader; private Resources resources; private String entryActivityName; private static final pluginManger ourInstance = new pluginManger(); public static pluginManger getInstance() { return ourInstance; } private pluginManger() { } public void loadpath(String path){ File dexOutFile = context.getDir("dex", Context.MODE_PRIVATE); dexClassLoader = new DexClassLoader(path,dexOutFile.getAbsolutePath(),null,context.getClassLoader()); PackageManager packageManager = context.getPackageManager(); PackageInfo packageInfo = packageManager.getPackageArchiveInfo(path,packageManager.GET_ACTIVITIES); entryActivityName = packageInfo.activities[0].name; Log.i("插件activity的classname",entryActivityName); try { AssetManager assetManager = AssetManager.class.newInstance(); Method addAssetPath = AssetManager.class.getMethod("addAssetPath",String.class); addAssetPath.invoke(assetManager,path); resources = new Resources(assetManager,context.getResources().getDisplayMetrics(),context.getResources().getConfiguration()); } catch (Exception e) { e.printStackTrace(); } } public DexClassLoader getDexClassLoader() { return dexClassLoader; } public Resources getResources() { return resources; } public String getEntryActivityName() { return entryActivityName; } public void setContext(Context context) { this.context = context.getApplicationContext(); }}现在要加载的class文件的名字与资源都准备好了,接下来去加载对应的class文件,并显示。name宿主APP显示一个界面,那就必须的有容器去放置这个内容,那么我们去插件一个宿主activity(ProxyActivity)className = getIntent().getStringExtra("classname");//得到要加载的全类名 Class activityClazz = getClassLoader().loadClass(className); Constructor constructor = activityClazz.getConstructor(new Class[]{});//创建构造方法 Object instance = constructor.newInstance(new Object[]{}); payInterface = (PayInterface) instance;//将得到的实力转化为标准的接口类型 payInterface.attach(this); Bundle bundle = new Bundle();//创建bundle对象便于传递参数 payInterface.onCreate(bundle);//创建这样界面还是空白的因为她还没有生命周期,我们要将对应的生命周期加上就完美了。/** * Created by yzl on 2017/10/10. */public class ProxyActivity extends Activity { private String className;//要跳转的activity private PayInterface payInterface; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); className = getIntent().getStringExtra("classname");//得到要加载的全类名 Log.i("传递过来的class名称为",className); try { Class activityClazz = getClassLoader().loadClass(className); Constructor constructor = activityClazz.getConstructor(new Class[]{}); Object instance = constructor.newInstance(new Object[]{}); payInterface = (PayInterface) instance; payInterface.attach(this); Bundle bundle = new Bundle(); payInterface.onCreate(bundle); } catch (Exception e) { e.printStackTrace(); } //利用反射加载class对应的class文件 //因为插件不在art虚拟机里安装的,所以直接使用凡事是找不到class文件的, //这个类所加载的class都是插件中的class,不能是宿主中的class,所以要重写getclassloader(); } @Override protected void onStart() { super.onStart(); payInterface.onStart(); } @Override protected void onResume() { super.onResume(); payInterface.onResume(); } @Override protected void onPause() { super.onPause(); payInterface.onPause(); } @Override protected void onStop() { super.onStop(); payInterface.onStop(); } @Override protected void onDestroy() { super.onDestroy(); payInterface.onDestroy(); } @Override public ClassLoader getClassLoader() { return pluginManger.getInstance().getDexClassLoader(); //由于super是系统注入的上下文(也就是本宿主的上下文)xi } @Override public Resources getResources() { return pluginManger.getInstance().getResources(); } @Override public void startActivity(Intent intent) { String twoActivityClass = intent.getStringExtra("className"); Intent intent1 = new Intent(this,ProxyActivity.class); intent1.putExtra("classname",twoActivityClass); super.startActivity(intent1); }}
阅读全文
0 0
- android插件化开发activity篇
- Android插件化开发 第四篇 [加载插件Activity]
- Android插件化开发 第四篇 [加载插件Activity]
- android插件化(Activity篇)
- 【Android开发学习笔记】【高级】【随笔】插件化——Activity生命周期
- Android插件化开发之运行未安装apk的activity
- Android中插件开发篇之----动态加载Activity(免安装运行程序)
- Android中插件开发篇之----动态加载Activity(免安装运行程序)
- Android中插件开发篇之----动态加载Activity(免安装运行程序)
- Android中插件开发篇之----动态加载Activity(免安装运行程序)
- android插件化开发
- Android插件化开发
- Android插件化开发
- Android 插件化开发
- Android插件化开发
- Android插件化开发
- android插件化开发
- Android插件化开发
- 不为繁华易匠心
- VS2012下编译libeXosip2
- 大数据商业智能争议不断,IT技术面临挑战
- Git详解之一:Git起步
- OpenCV2编程手册笔记之 10.5应用光流法跟踪视频中的特征点
- android插件化开发activity篇
- Spring boot Druid监控、Mybatis、pageHelper集成
- eclipse在tomcat中项目别名
- Java中类与对象(二):构造方法
- AngularJS基础练习(3)
- OpenCV中两个旋转矩形RotatedRect的交集
- spring容器启动,初始化某个方法(init)
- javaWeb文件上传下载
- 第六周第一课--队列