Application、Activity、Context的关系

参考http://blog.youkuaiyun.com/woaieillen/article/details/10234807

Application继承关系图

Activity继承关系图

  • 从上面两张图我们可以看出:Application和Activity都是继承自Context
  • Application对象是整个应用的上下文(通过打印日志可知:无论在哪里,通过getApplication或getApplicationContext得到的都是同一个Cotext对象,也就是应用的上下文),而Activity则不同,虽然都是继承自Context,但是在Activity中this和getApplication(getApplicationContext)得到的对象不是同一个!Activity的this这个上下文可用于界面UI的构造等(如弹窗,new View),而Application则不行。
  • 在Acctivity中通过getParent获得的也是Activity对象(父activity)。顺便扩展一下,这个方法是只有当activity是一个嵌入式的activity时才返回父activity(否则为null)。如下,查看Activity源码的说明:

      /** Return the parent activity if this view is an embedded child. */
      public final Activity getParent() {
        return mParent;
      }
  • 通过 getBaseContext获得的上下文对象则各不相同,引用google工程师的一句话:

    Don’t use getBaseContext(), just use the Context you have.
    不要使用getBaseContext(),只使用你有的Context。

  • Application(或者说应用的上下文对象)是和应用程序关联的,并且在程序的生命周期内,总是一样的。而Activity(Activity的上下文)是关联在某个活动上的,随着Activity的销毁(比如横竖屏切换等情况),这个Context也会被销毁N多次。

在 Android 中,**Application Context(`Application.getApplicationContext()`)不能直接用于启动 Activity**,但可以通过添加 `FLAG_ACTIVITY_NEW_TASK` 标志间接实现。以下是详细说明: --- ### **1. 直接使用 Application Context 的问题** ```java // 错误示例:直接使用会崩溃 context.startActivity(new Intent(context, TargetActivity.class)); ``` - **崩溃原因**: Activity 启动需要关联一个任务栈(Task),而 `Application Context` 不属于任何任务栈,系统无法确定新 Activity 的堆栈归属,抛出异常: `android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag.` --- ### **2. 解决方案:添加 `FLAG_ACTIVITY_NEW_TASK`** ```java // 正确用法:添加标志位 Intent intent = new Intent(context, TargetActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 关键代码 context.startActivity(intent); ``` - **作用**: 强制为新 Activity 创建一个新的任务栈(即使原 Activity 不存在)。 --- ### **3. 注意事项** - **用户体验影响**: - 新 Activity 会脱离原有应用的任务栈,可能导致返回逻辑混乱(按返回键可能直接回到桌面)。 - 建议仅在 **后台服务、广播接收器等非 UI 场景** 中使用此方式。 - **Android 10+ 限制**: 从 Android 10(API 29)开始,后台应用启动 Activity 受到严格限制,需满足以下条件之一: - 应用具有前台权限(如 `FOREGROUND_SERVICE`)。 - 用户手动交互触发(如点击通知)。 --- ### **4. 替代方案(推荐)** - **传递 Activity Context**: 通过接口/回调将 `Activity` 的 Context 传递到非 UI 组件(如工具类)。 - **使用 `startActivity()` 的合法场景**: - 从 `Activity` 或 `Fragment` 的 Context 启动。 - 从 `Service` 启动时,需结合 `PendingIntent`(如通知点击)。 --- ### **5. 各场景下的 Context 类型对比** | **场景** | **可用 Context 类型** | **是否需要 `NEW_TASK`** | |-----------------------|-------------------------------|-----------------------| | Activity 中 | `Activity.this` | 否 | | Application 类 | `getApplicationContext()` | 是 | | Service | `Service.this` | 是 | | BroadcastReceiver | `Receiver` 的 `Context` | 是 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值