在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的弱引用。使用弱引用的目的是为了不影响系统的回收,否则就会导致内存的泄漏。