Android如何获得当前应用显示的Activity
2016-02-27 20:45
513 查看
在 Android 开发过程中,我们有时候需要获取当前的 Activity 实例,比如弹出 Dialog 的操作,AlertDialog 的创建必须用到 Activity 的 Window 。
- 获取 ActivityThread 重点内容 中所有的ActivityRecord
- 从 ActivityThread 中获取所有状态不是 pause 的实例
一个使用反射来实现的代码大概如下
然而这种方式的缺点和所有使用反射解决问题的缺点一样
- 反射通常会比较慢 (其实还是可以接受的)
- 不稳定性,这是主要的原因,你不能保证 Andorid框架的代码在未来不变化,如果未来 某些字段 名、方法名被改变了呢,所以采用反射的方式并不是完全可靠的
然而,这一种方法也不仅完美,因为这种方法是基于约定的,所以必须每个Activity都继承BaseActivity,如果一旦出现没有继承BaseActivity的就可能有问题。
介绍了上面两种不是尽善尽美的方法,这里实际上还是有一种更便捷的方法,那就是通过Framework提供的回调来实现。
Android自 API 14开始引入了一个方法,即 Application 的 registerActivityLifecycleCallbacks 方法,用来监听所有 Activity 的生命周期回调,比如 onActivityCreated , onActivityResumed 等。
So,一个简单的实现如下
然而,金无足赤人无完人,这种方法唯一的遗憾就是只支持API 14即其以上。不过还在现在大多数设备都满足了这个要求。
本文章装载自 http://droidyue.com/blog/2016/02/21/thinking-of-getting-the-current-activity-in-android/
反射
反射是我们经常会想到的方法,思路大概为- 获取 ActivityThread 重点内容 中所有的ActivityRecord
- 从 ActivityThread 中获取所有状态不是 pause 的实例
一个使用反射来实现的代码大概如下
[code] public static Activity getActivity() { Class activityThreadClass = null; try { activityThreadClass = Class.forName("android.app.ActivityThread"); Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null); Field activitiesField = activityThreadClass.getDeclaredField("mActivities"); activitiesField.setAccessible(true); Map activities = (Map) activitiesField.get(activityThread); for (Object activityRecord : activities.values()) { Class activityRecordClass = activityRecord.getClass(); Field pausedField = activityRecordClass.getDeclaredField("paused"); pausedField.setAccessible(true); if (!pausedField.getBoolean(activityRecord)) { Field activityField = activityRecordClass.getDeclaredField("activity"); activityField.setAccessible(true); Activity activity = (Activity) activityField.get(activityRecord); return activity; } } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } return null; }
然而这种方式的缺点和所有使用反射解决问题的缺点一样
- 反射通常会比较慢 (其实还是可以接受的)
- 不稳定性,这是主要的原因,你不能保证 Andorid框架的代码在未来不变化,如果未来 某些字段 名、方法名被改变了呢,所以采用反射的方式并不是完全可靠的
Activity基类
既然反射不是很可靠的,那么有一种比较可靠的方式,就是将所有的 Activity 都继承自我们的实现的基类,在基类中对 Activity 的信息作记录[code]public class BaseActivity extends Activity{ @Override protected void onResume() { super.onResume(); MyActivityManager.getInstance().setCurrentActivity(this); } }
然而,这一种方法也不仅完美,因为这种方法是基于约定的,所以必须每个Activity都继承BaseActivity,如果一旦出现没有继承BaseActivity的就可能有问题。
介绍了上面两种不是尽善尽美的方法,这里实际上还是有一种更便捷的方法,那就是通过Framework提供的回调来实现。
Android自 API 14开始引入了一个方法,即 Application 的 registerActivityLifecycleCallbacks 方法,用来监听所有 Activity 的生命周期回调,比如 onActivityCreated , onActivityResumed 等。
So,一个简单的实现如下
[code]public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { } @Override public void onActivityStarted(Activity activity) { } @Override public void onActivityResumed(Activity activity) { MyActivityManager.getInstance().setCurrentActivity(activity); } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { } }); } }
然而,金无足赤人无完人,这种方法唯一的遗憾就是只支持API 14即其以上。不过还在现在大多数设备都满足了这个要求。
具体看下我们的 Manager 类
[code]public class MyActivityManager { private static MyActivityManager sInstance = new MyActivityManager(); // 采用弱引用持有 Activity ,避免造成 内存泄露 private WeakReference<Activity> sCurrentActivityWeakRef; private MyActivityManager() { } public static MyActivityManager getInstance() { return sInstance; } public Activity getCurrentActivity() { Activity currentActivity = null; if (sCurrentActivityWeakRef != null) { currentActivity = sCurrentActivityWeakRef.get(); } return currentActivity; } public void setCurrentActivity(Activity activity) { sCurrentActivityWeakRef = new WeakReference<Activity>(activity); } }
本文章装载自 http://droidyue.com/blog/2016/02/21/thinking-of-getting-the-current-activity-in-android/
相关文章推荐
- Android图片压缩库——libjpeg-turbo
- 使用CircularReveal动画效果切换页面
- Android应用的自动升级、更新模块的实现
- 实现卡片翻转的动画效果
- Android 完美实现图片圆角和圆形(对实现进行分析)
- Android系统下载管理DownloadManager功能介绍及使用示例
- android 时间滚动控件 底部弹出
- androidstudio入门-新建模拟器
- Android通过DexClassLoader加载apk文件
- androidstudio入门-修改minSDK
- 最详细的Android Studio百度地图(BaiduMap)开发教程,可以用作官方文档的教程!
- Android疑问小结
- 制作了一个简单的viewhelper,用于在滑动listview时,隐藏顶部指定区域,下拉时再展示
- Android 图片缓存之内存缓存技术LruCache
- Android改变button等控件的样式
- Android学习历程15-Android 软键盘的强制隐藏
- Android上V8 JS引擎
- Android Fragment 真正的完全解析(下)
- Android学习历程15-SurfaceView的简单用法(实例:幸运抽奖以及控制中奖物品)
- Android Fragment 真正的完全解析(上)