全局Application实例使用及分析
简单明了通过源码分析获取其Context对象实例
思考-分析-解决
通过Kaede Akatsuki的这篇文章了解到:
Application
实例在App
运行时,始终存在着。ActivityThread
匿名类中存在其实例的值
反射Context
对象引用
1 2 3 4 5 6 7 8
| Object activityThread = null; try { Method method = Class .forName("android.app.ActivityThread") .getMethod("currentActivityThread"); method.setAccessible(true); activityThread = method.invoke(null); } catch (final Exception e) { Log.w(TAG, e); }
|
其反射对应方法内容
1 2 3 4
| @UnsupportedAppUsage public static ActivityThread currentActivityThread() { return sCurrentActivityThread; }
|
emmm这里看了源码发现有两个可以直接反射出实例的方法
这里先给出源码
1 2 3 4 5
| @UnsupportedAppUsage public static Application currentApplication() { ActivityThread am = currentActivityThread(); return am != null ? am.mInitialApplication : null; }
|
注意到了没,这里已经将其currentActivityThread方法返回值
转化为Application
对象实例
那么问题看起来就简单多了
1 2 3
| val method = Class.forName("android.app.ActivityThread") .getDeclaredMethod("currentApplication") context = method.invoke(null) as Application
|
至于为什么不使用try catch
两点
- 正常状态不会抛出异常 调试才会一直抛出
- try catch 一旦使用 catch错误类型须写全 否则无法识别
比如这样
1 2 3 4 5 6 7 8 9 10 11 12 13
| try { val method =Class.forName("android.app.ActivityThread") .getDeclaredMethod("currentApplication") context = method.invoke(null) as Application } catch (e: NoSuchMethodException) { e.printStackTrace() } catch (e: ClassNotFoundException) { e.printStackTrace() } catch (e: IllegalAccessException) { e.printStackTrace() } catch (e: InvocationTargetException) { e.printStackTrace() }
|
那第二种方法呢? 嗯。直接看源码
1 2 3 4 5 6 7 8 9
| @UnsupportedAppUsage public ContextImpl getSystemContext() { synchronized (this) { if (mSystemContext == null) { mSystemContext = ContextImpl.createSystemContext(this); } return mSystemContext; } }
|
这个方法为什么看起来好眼熟 但是不能用哦
ContextImpl
这个类是继承Context
但是在Android sdk
较低版本是未实现的类