Android——如何优雅的维护最前台的Activity实例
Posted David-Kuper
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android——如何优雅的维护最前台的Activity实例相关的知识,希望对你有一定的参考价值。
在android开发过程中,我们有时候需要获取当前的Activity实例,比如弹出Dialog操作、当Notification来到时判断某个页面是否在前台等等。所以维护一个当前显示的Activity是比较好的方式。关于如何实现由很多种思路,这其中有的简单,有的复杂,这里简单总结一下几种方式。
1、反射(获取ActivityThread,从而拿到当前的Activitys,该方式不推荐,比较消耗内存)
2、继承(通过基类控制每个继承类,从而维护一个当前Activity的引用,但无法控制不继承的类)
3、Application注册系统回调(通过framework层,在Application里面注册回调监听全局所有Activity运行状态,从而维护一个当前的Activity引用,推荐使用)
反射
我们可以像下面这样,通过反射来获取一个Activity的引用。
1. 获取ActivityThread中所有的ActivityRecord
2. 从ActivityRecord中获取状态不是pause的Activity并返回
一个使用反射来实现的代码大致如下:
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;
反射虽然是个利器,但是它也是把双刃剑:
- 但是反射总是缓慢的,过多的反射、枚举会占用系统内存,拖慢系统速度。
- 不稳定性,这个才是不推荐的原因,Android框架代码存在修改的可能性,谁要无法100%保证mActivities,paused固定不变。所以可靠性不是完全可靠。
继承
反射一般是不推荐的,java还可以通过继承的方式来实现这个维护。
- 建立一个Activity基类,在基类中维护一个全局的activity引用(currentActivity)
- 系统中的所有Activity继承自该Activity下,每当Activity中的onResume方法调用的时候就替换当前的currentActivity.
public class BaseActivity extends Activity
@Override
protected void onResume()
super.onResume();
//这是一个管理当前Activity引用的工具类
MyActivityManager.getInstance().setCurrentActivity(this);
这种方式对性能影响不大,而且非常简单,大部分的时候这种方式都能够解决问题。但是当我们的工程当中有了一些不继承自BaseActivity的类的时候(第三方的库下面的Activity),这个时候这种方式就不行了。因此,如果能够在系统层面做一个监听就好了,就是下面的回调方式。
回调
上面两种方式都不能满足我们的需求。第一种,反射虽好,用途强大,但是用在这里真的是杀鸡用牛刀;第二种,继承的方式,很好的使用了java的特性,但是对于不是继承自基类的类别就无法维护。还好,系统为我们提供了一个全局监控Activity生命周期的功能。
Android自 API 14开始引入了一个方法,即Application的registerActivityLifecycleCallbacks方法,用来监听所有Activity的生命周期回调,比如onActivityCreated,onActivityResumed等。
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)
);
/**
*
public class MyActivityManager
private static MyActivityManager sInstance = new MyActivityManager();
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);
这里我们维护了一个指向当前展示的Activity的弱引用。使用弱引用的目的是为了不影响系统的回收,否则就会导致内存的泄漏。
以上是关于Android——如何优雅的维护最前台的Activity实例的主要内容,如果未能解决你的问题,请参考以下文章