热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

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

这篇文章主要为大家详细介绍了Android开发过程中,关于获取当前Activity的一些思考,感兴趣的小伙伴们可以参考一下

在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 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实例无法释放,导致内存泄露的出现。

以上就是本文的全部内容,希望对大家学习Android软件编程有所帮助。


推荐阅读
  • https:developers.weixin.qq.comminiprogramdevapinetworksocket.htmlwxconnectsocke ... [详细]
  • Mac安装Appium
    Appium官网http:appium.io实际步骤1.appium基于node.js首先安装node.jsbrewinstallnode2.安装appiumnpminstal ... [详细]
  • 1的Metro界面用户的使用反馈怎么样?
      有大量的技术改进到来的Windows8,你已经可以在开发者预览版看到,从更快的启动时间到WindowsUpdate不会骚扰你(当你下载东西的一个昂贵的移动宽带连接等)met ... [详细]
  • 基于bionic c分析线程的一生
    1.概述和问题进程和线程操作系统基础和重要的机制,从源码角度理解进程和线程的区别对于理解操作系统的基本原理非常有帮助,同时进程和线程的创建又是通过系统 ... [详细]
  • 一、Web前端技术HTML:HTML、HTML5、CSS、TCPIPXML:XMLWeb脚本:JavaScript、AJAX、jQuery、JSONServ脚本:JSP、APS、P ... [详细]
  • Android_打开Android Studio时报Unable to access Android SDK addon list ... [详细]
  • 如何绘制直观易懂的时标网络图
    时标网络图是用活动的定位和长度表示活动历时的项目网络图。是含网络逻辑的横道图,并且是任何以工作位置和长度代表其持续时间的项目网络图。项目经理圈子在时标网络图中,以实箭线表示工作,实 ... [详细]
  • 一,深浅拷贝看拷贝列子day19-1.py假如修改的元素是一个列表,源列表也会发生变化day19-2.py为什么会这样,因为第一次修改的是一个不可变元素对应的指针发生了变化,第二次 ... [详细]
  • D-War(8.4.3)CrawlinginprocessCrawlingfailedTimeLimit:3000MS    MemoryLimit:0KB  ... [详细]
  • 实验六提交版
    1.21.3part2共用体与结构体类型的区别?答:共用体与结构体的区别在于它们的表示方法不同。结构体内,结构体的各成员顺序排列存储,每个成员都有自己独立的存储位置,而共用体的情况 ... [详细]
  • TP框架 事件
    原文 http:www.cnblogs.comFushichop6600241.html1.在程序运行到应用模块的时候,先进行事件的注册:对事件进行监听注册监听注册其中,获取监听权 ... [详细]
  • JS swiper轮播图完美兼容手机端
    swiper ... [详细]
  • 使用IGP和BGP的配合达到降低路由容量目的的实验与总结
    本文描述了OSPF和BGP配合来降低路由器的容量压力的实验和总结,有助于对IGP协议和BGP协议的互 ... [详细]
  • Python对象特性0x01:所有Python对象都有三个特性以及属性*身份:每一个对象都有一个唯一的身份标识自己,任何一个都可以用内建函数id()来得到。*类型:决定了可以保存什 ... [详细]
  • Forexamplewehavefollowingcode:$(el).hide()el.style.display'none'$(el).forEach((){ ... [详细]
author-avatar
手机用户2502857113
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有