Android Application 多继承
来源:互联网 发布:加盟淘宝孕婴店 编辑:程序博客网 时间:2024/06/07 00:12
Android Application 多继承
首先,附上Demo链接:
https://github.com/EshelGuo/AppMultipleExtends/tree/master
众所周知,Java里的继承都是单继承,而我们今天的话题是通过反射实现Application多继承。那么为什么非要Application多继承呢?想必大家在做项目的时候肯定集成很多SDK吧,也应该遇见过一部分SDK要求继承他们提供的Application吧,那假如我集成了两个SDK并且都要求集成他们提供的Application呢?
我首先想到了Application串联继承,自定义Application继承SDK1的Application,然后让SDK1的Application继承SDK2的Application,但是一般三方SDK代码都是封装在jar包里的,想要修改SDK中Application的继承关系不太可能,该方法不可行。
其实最简单的办法就是定义Application,查看SDK1 和SDK2中Application的代码,一般都是在onCreate中有一句或几句初始化SDK的代码,copy粘贴到自己的Application中就好了,但是该方法很容易将SDK初始化逻辑和自己APP初始化逻辑混在一起,加入项目比较大,Application代码比较多,维护起来不方便,并且假如SDK升级修改了初始化接口还要修改Application的代码。当然最重要的是这种方法复制粘贴太 low。哈哈哈~~~
接下来进入正题,由我来介绍一种比较高大上的方法来避免这种尴尬局面。首先看一下Application中的所有用得到的方法:
一般我们用得到的只有 从onCreate 到 onTrimMemory这些生命周期方法和 registerActivityLifecycleCallbacks Activity生命周期的注册和取消(Api14 添加的方法)。也就是说,加入我们想要不继承 SDK1Application 就能让这个Application正常使用,首先需要让它的生命周期方法正常运行,其次SDK1Application中的 registerActivityLifecycleCallbacks 能正常使用,还有就是在SDK1Application中使用 this 或者 getApplicationContext() 去开启Activity Toast等必须有效。
要实现最后一点,还需要再看几张图:
首先Application是继承ContextWrapper的,而ContextWrapper继承Context。如下图,ContextWrapper其实就是一个包装类,他的所有实现都在 成员变量 mBase 中,mBase是一个ContextIml类。而今天实现多继承的突破口就在这个mBase上。
假如现在我们不继承SDK的Application,仅仅普通的把他们 new 出来,然后通过反射将自己Application 中的mBase 赋值给 SDK Application中的mBase,并且在自己的Application生命周期中调用SDKApplication的生命周期方法,那么SDK 不就相当于间接继承了我们的Application了吗?
下面只说思路,想要看代码的话请到最上边github链接下载Demo。
- 第一步:新建 Application 并在清单文件配置,在 attachBaseContext 中创建 SDKApplication 并通过反射调用 它的 attachBaseContext方法。
- 第二步:重写Application方法,并在生命周期方法中依次调用SDKApplication的生命周期方法
- 第三步:接下来就有意思了,我们再看个图:
Application中有三个集合,我们注册ActivityLifecycleCallbacks等生命周期回调就是添加到这些集合中了,想要SDKApplication中的这些回调生效,我们在SDKApplication中注册ActivityLifecycleCallbacks就必须注册到真正Application中。这里有个小技巧,可以通过修改图中三个集合来打到Hook这些回调的目的,首先三个集合都是ArrayList,我们定义 HookArrayList 继承ArrayList,重写add 和 remove方法,如下代码:
public class HookArrayList<E> extends ArrayList<E>{ private static Application mApplication; public HookArrayList(Application application){ mApplication = application; } @Override public boolean add(E o) { if(o instanceof Application.ActivityLifecycleCallbacks){ mApplication.registerActivityLifecycleCallbacks((Application.ActivityLifecycleCallbacks) o); }else if(o instanceof ComponentCallbacks){ mApplication.registerComponentCallbacks((ComponentCallbacks) o); }else if(o instanceof Application.OnProvideAssistDataListener){ if (Build.VERSION.SDK_INT >= 18/*Build.VERSION_CODES.JELLY_BEAN_MR2*/) { mApplication.registerOnProvideAssistDataListener((Application.OnProvideAssistDataListener) o); } } return true; } public boolean remove(Object o) { if(o instanceof Application.ActivityLifecycleCallbacks){ mApplication.unregisterActivityLifecycleCallbacks((Application.ActivityLifecycleCallbacks) o); }else if(o instanceof ComponentCallbacks){ mApplication.unregisterComponentCallbacks((ComponentCallbacks) o); }else if(o instanceof Application.OnProvideAssistDataListener){ if (Build.VERSION.SDK_INT >= 18/*Build.VERSION_CODES.JELLY_BEAN_MR2*/) { mApplication.unregisterOnProvideAssistDataListener((Application.OnProvideAssistDataListener) o); } } return true; }}
然后通过反射修改上面三个ArrayList为我们的HookArrayList,其中HookArrayList构造中的Application是真正的Application。
这样我们已经实现了多继承,但是有个问题,这样不也把好多逻辑混到Application中了吗?还没完,接下来需要把Application的逻辑抽到一个单独的类中:APPManager,然后定义HookApplication,在其中调用相关方法,然后将自己的Application继承HookAapplication就可以了。
下面介绍下Demo中多继承的用法,首先把Demo中com.eshel.deom.hookapp 的代码复制到项目中,然后继承 HookApplication,并重写 addApplication方法,代码如下:
public class MainApplication extends HookApplication { public static Handler mHandler = new Handler(); @Override public void addApplications(AppConfig appConfig) { appConfig.add(new SDK1Application()); appConfig.add(new SDK2Application()); } @Override public void onCreate() { super.onCreate(); Toast.makeText(getApplicationContext(), "MainApp toast", Toast.LENGTH_SHORT).show(); }}
其中SDK1Application SDK2Application代表SDK的Application。代码请看github链接,欢迎start
- Android Application 多继承
- 继承Application实现Android数据共享
- 继承Application实现Android数据共享
- 继承Application实现Android数据共享
- 继承Application实现Android数据共享
- 继承Application实现Android数据共享
- 继承Application实现Android数据共享
- Android 调用继承application的类
- android 继承自application的类
- Android用类继承Application的全局变量使用注意
- Android Application
- Android application
- Android Application
- android Application
- Android Application
- Android Application
- Android Application
- Android Application
- 应用程序池提示:未指定错误,访问站点提示:Service Unavailable
- HBase盲点扫描:集群搭建及hbaseshell使用
- RecyclerView item内部点击事件、item点击事件冲突
- JavaFX控件——TableView
- Dubbo Hessian2序列化问题
- Android Application 多继承
- Oracle导出导入
- 购买二手房为了少纳税签下了“阴阳合同”,明年将坐牢!
- EasyDMA和PPI学习
- 本地仓库关联到远程仓库中
- Java实现内存可见性的两种方法比较:synchronized 和 Volatile以及涉及到锁的剖析
- 微信小程序项目实例
- 关于JMenuBAr,JMenu,JMenuItem,JList,JComboBox
- python导入中文命名的文件