专栏名称: 郭霖
Android技术分享平台,每天都有优质技术文章推送。你还可以向公众号投稿,将自己总结的技术心得分享给大家。
目录
相关文章推荐
复利大王  ·  老同学中捞一捞能不能找到免费P友 ·  10 小时前  
复利大王  ·  不讲武德!中x银行? ·  10 小时前  
鸿洋  ·  务必立即拿下软考证(政策红利) ·  昨天  
复利大王  ·  冷暴力女王,翻车了 ·  昨天  
复利大王  ·  手握25w华子股票,躺平了 ·  昨天  
51好读  ›  专栏  ›  郭霖

Android Context完全解析,你所不知道的Context的各种细节

郭霖  · 公众号  · android  · 2025-06-03 08:00

正文

请到「今天看啥」查看全文



那么除了getApplication()方法,其实还有一个getApplicationContext()方法,这两个方法看上去好像有点关联,那么它们的区别是什么呢?我们将代码修改一下:

public class MainActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    MyApplication myApp = (MyApplication) getApplication();
    Log.d("TAG""getApplication is " + myApp);
    Context appContext = getApplicationContext();
    Log.d("TAG""getApplicationContext is " + appContext);
  }
}

同样,我们把getApplicationContext()的结果打印了出来,现在重新运行代码,结果如下图所示:



咦?好像打印出的结果是一样的呀,连后面的内存地址都是相同的,看来它们是同一个对象。其实这个结果也很好理解,因为前面已经说过了,Application本身就是一个Context,所以这里获取getApplicationContext()得到的结果就是MyApplication本身的实例。


那么有的朋友可能就会问了,既然这两个方法得到的结果都是相同的,那么Android为什么要提供两个功能重复的方法呢?实际上这两个方法在作用域上有比较大的区别。getApplication()方法的语义性非常强,一看就知道是用来获取Application实例的,但是这个方法只有在Activity和Service中才能调用的到。那么也许在绝大多数情况下我们都是在Activity或者Service中使用Application的,但是如果在一些其它的场景,比如BroadcastReceiver中也想获得Application的实例,这时就可以借助getApplicationContext()方法了,如下所示:

public class MyReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
    MyApplication myApp = (MyApplication) context.getApplicationContext();
    Log.d("TAG""myApp is " + myApp);
  }
}

也就是说,getApplicationContext()方法的作用域会更广一些,任何一个Context的实例,只要调用getApplicationContext()方法都可以拿到我们的Application对象。


那么更加细心的朋友会发现,除了这两个方法之外,其实还有一个getBaseContext()方法,这个baseContext又是什么东西呢?我们还是通过打印的方式来验证一下:



哦?这次得到的是不同的对象了,getBaseContext()方法得到的是一个ContextImpl对象。这个ContextImpl是不是感觉有点似曾相识?回去看一下Context的继承结构图吧,ContextImpl正是上下文功能的实现类。也就是说像Application、Activity这样的类其实并不会去具体实现Context的功能,而仅仅是做了一层接口封装而已,Context的具体功能都是由ContextImpl类去完成的。那么这样的设计到底是怎么实现的呢?我们还是来看一下源码吧。因为Application、Activity、Service都是直接或间接继承自ContextWrapper的,我们就直接看ContextWrapper的源码,如下所示:

/**
 * Proxying implementation of Context that simply delegates all of its calls to
 * another Context.  Can be subclassed to modify behavior without changing
 * the original Context.
 */

publicclass ContextWrapper extends Context {
    Context mBase;

    /**
     * Set the base context for this ContextWrapper.  All calls will then be
     * delegated to the base context.  Throws
     * IllegalStateException if a base context has already been set.
     *
     * @param base The new base context for this wrapper.
     */

    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            thrownew IllegalStateException("Base context already set");
        }
        mBase = base;
    }

    /**
     * @return the base context as set by the constructor or setBaseContext
     */

    public Context getBaseContext() {
        return mBase;
    }

    @Override
    public AssetManager getAssets() {
        return mBase.getAssets();
    }

    @Override
    public Resources getResources() {
        return mBase.getResources();
    }

    @Override
    public ContentResolver getContentResolver() {
        






请到「今天看啥」查看全文