Android开发中关于获取当前Activity的一些思考

作者:lijiao 时间:2023-07-14 07:35:34 

在Android开发过程中,我们有时候需要获取当前的Activity实例,比如弹出Dialog操作,必须要用到这个。关于如何实现由很多种思路,这其中有的简单,有的复杂,这里简单总结一下个人的一些经验吧。

反射

反射是我们经常会想到的方法,思路大概为

  • 获取ActivityThread中所有的ActivityRecord

  • 从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固定不变。所以可靠性不是完全可靠。
     

Activity基类

既然反射不是很可靠,那么有一种比较可靠的方式,就是使用Activity基类。

在Activity的onResume方法中,将当前的Activity实例保存到一个变量中。


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,一个简单的实现如下


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即其以上。不过还在现在大多数设备都满足了这个要求。

为什么是弱引用

可能有人会带着疑问看到这里,MyActivityManager是个什么鬼,好,我们现在看一下这个类的实现


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的设置和获取。

那么为什么要使用弱引用持有Activity实例呢?

其实最主要的目的就是避免内存泄露,因为使用默认的强引用会导致Activity实例无法释放,导致内存泄露的出现。

标签:Android,Activity
0
投稿

猜你喜欢

  • Mybatis Generator最完美配置文件详解(完整版)

    2021-06-13 05:11:06
  • 一文掌握MyBatis Plus的条件构造器方法

    2023-06-18 13:00:26
  • 解析Android获取系统cpu信息,内存,版本,电量等信息的方法详解

    2023-11-20 10:50:15
  • c#数据绑定之将datatabel的data添加listView

    2022-01-02 03:02:33
  • Java拦截器Interceptor实现原理及代码示例

    2023-11-04 03:49:32
  • C#写差异文件备份工具的示例

    2022-02-21 02:14:00
  • C# 多线程更新界面的错误的解决方法

    2022-01-20 15:52:21
  • java多线程有序读取同一个文件

    2022-05-28 20:41:57
  • 基于Java swing组件实现简易计算器

    2023-03-29 02:10:07
  • 详解Java图形化编程中的鼠标事件设计

    2022-07-11 08:11:31
  • Android实现简单卡片布局

    2023-05-22 11:43:37
  • WPF实现钟表效果

    2022-11-18 15:38:05
  • Android语音识别技术详解及实例代码

    2022-09-23 03:46:33
  • C#线性渐变画刷LinearGradientBrush用法实例

    2022-01-21 05:29:43
  • JAVA 格式化日期、时间的方法

    2023-10-17 07:53:22
  • C# Partial:分部方法和分部类代码实例

    2022-04-07 11:28:26
  • java Socket实现网页版在线聊天

    2022-10-19 12:13:42
  • 详解springboot测试类注解

    2023-06-04 21:04:37
  • Android 处理OnItemClickListener时关于焦点颜色的设置问题

    2021-09-02 01:47:00
  • eclipse导入appcompat项目报错解决办法

    2021-11-10 14:25:57
  • asp之家 软件编程 m.aspxhome.com