Application context 和 Activity context 有什么区别
When to call activity context OR application context?
先看完这个问题。

总结如下:

  1. UI相关
      一般和UI相关的都要用Activity Context。而且只有Activity Context 才能启动Dialog、PopupWindow等这类需要attach到具体Activity的View。而Toast这类则可以使用Application Context。另外在start Activity时,在Intent中需要使用Activity Context来构建Activity stack,或者使用Application Context和Intent.FLAG_ACTIVITY_NEW_TASK来在一个新的task中启动Activity。
  2. 生命周期
      Application Context 存在于整个application的生命周期中,而Activity Context会和具体的某个Activity的生命周期绑定在一起。

  获得一个Context,通常使用下面几个函数:

MainActivity.this //activity context. ContextThemeWrapper
getBaseContext() //activity context.
getApplication() //application context.
getApplicationContext() //application context.

  在registerReceiver(BroadcastReceiver, IntentFilter)中,Context不同,具体的表现也不同。

If used from an Activity context, the receiver is being registered within that activity. This means that you are expected to unregister before the activity is done being destroyed;
in fact if you do not do so, the framework will clean up your leaked registration as it removes the activity and log an error.
Thus, if you use the Activity context to register a receiver that is static (global to the process, not associated with an Activity instance) then that registration will be removed on you at whatever point the activity you used is destroyed.

If used from the Context returned here, the receiver is being registered with the global state associated with your application. Thus it will never be unregistered for you.
This is necessary if the receiver is associated with static data, not a particular component. However using the ApplicationContext elsewhere can easily lead to serious leaks if you forget to unregister, unbind, etc.[1]

  • Activity Context:注册后只会在Activity的生命周期内接收到通知,在Activity销毁时,系统会期待你unregister(而且就算你不这样做,它也会自动帮你清理掉泄露的Receiver,即使BroadcastReceiver是static的)
  • Application Context:Receiver注册后会在整个app的进程生命周期内有效,适用于处理static data。但是同时也需要注意如果没有手动unregister会有内存泄露。

  另外在某些场景经常需要存一份Context引用,如果实体的生命周期大于该Context,比如在static instance中引用Activity Context,会导致Context所属的Activity无法被GC。或者使用了非static inner的Handler、Runnable,或是在其中引用了Activity Context[2]。这种时候:

  1. 你的设计肯定有问题
  2. 是否可以替换成Application Context
  3. 使用WeakReference
  4. 使用staic inner Class

  第三个场景是在Layout Inflation时,如果使用Application Context,layout布局会用系统自带的theme来加载,manifest中指定的theme则不会应用。

参考文档:


  1. Context Google官方文档

  2. Context is probably the most used element in Android applications…it may also be the most misused