Android 开发是基于Java环境开发的,但是你如果写过测试用例的话你就会有个感觉就是,它和Java还是有很大区别的,比如你不能随便new一个类让它运行起来,我们在测试用例中有的使用要费劲心思来创建和待测试一样的运行环境,这里要介绍的Context就是一种上下文环境,下面内容是来自我在入职初期学习时候做的PPT来的,所以比较简洁不过大概涵盖了Context所涉及的知识点。
如上面提到的Android是基于组件,每个组件的运行都要有一个环境才能够正常工作,所以不是简单地New一个对象调用就能创建实例了,而是要有它们各自的上下文环境Context。在Android开发初期大家可能最难理解的就是这个Context了吧,至少我当时是萌逼状态的。

Context的作用

  • 可以通过 Context识别调用者的实例。
    (例如:TextView label = new TextView(this)
    意味着view拥有一个指向Activity的引用,进而引用Activity占有的资源).
  • 管理应用程序特定的配置细节
  • 管理应用程序范围的操作和数据
  • 访问当前包的资源(getResources、getAssets)
  • 启动其他组件(Activity、Service、Broadcast)
  • 得到各种系统服务(getSystemService)
  • 使用Application Context来访问设置和资源可以在多个Activity实例中共享

Application Context

Application-Context的生命周期是整个应用,Application Context可以通过Context.getApplicationContext或者Activity.getApplication方法获取。
在Activity或者Service中可以通过getApplication()函数获得,不管通过何种方法在哪里获得的,在一个进程内,总是获得到同一个实例。

Application通常有如下常用用途:

1.获得当前应用的主题,资源文件中的内容等
2.使用Application同步Activity之间的状态,例子见备注部分:

实现在任何位置获取Applcation Context 方法:

在Android中只有Activity, Provider等组件中才能使用API获取Application Context,但是在某些工具类中往往需要它来访问资源。这就需要我们自定义一个Application类来解决这个问题:

public class MyApplication extends Application {  
private static MyApplication instance;
public static MyApplication getInstance() {
return instance;
}
public void onCreate() {
super.onCreate();
instance = this;
}
}

为了能正确地调用MyApplication.getInstance(),需要在manifest中中加入name=”mypackage.MyApplication”。

获取Context的方式

  • 可以使用getApplicationContext()方法从当前进程中获取Context,这个方法在例如Activity或者Service中能够找到。通常我们使用Context对象时,要优先考虑这个全局的进程Context。

    Context context = getApplicationContext();
  • getContext()当前Activity对象的Context对象

  • Activity.this 返回当前的Activity实例,这个和上一个有点类似。

使用应用程序Context

获得了一个应用程序Context后,就可以用它来访问应用程序范围的功能和服务了,这些功能和服务包括:

  • 获取应用程序资源,例如字符串,图像和XML文件:
    String greeting = getResource().getString(R.string.hello);
  • 访问应用程序首选项使用getSharedPreferences来访问共享的应用程序首选项
  • 管理私有的应用程序文件以及目录
  • 获取未编译的应用程序组件使用getAssets方法来获取应用程序的资源
  • 获取系统服务
  • 管理私有的应用程序数据库
  • 使用应用程序权限

应用程序的Context数目

在Android中 Context的子类有:Application,Activity,Service,所以:

Context数量 = Activity数量 + Service数量 + 1 (Application Context)

错误使用带来的问题:

Context 错误使用会带来很严重的内存泄漏的问题,这个在内存优化部分有做过介绍,比如下面的例子,这是一个非常简单的懒汉式单例:

public class Singleton {

private Context mContext;
private static Singleton instance;
private Singleton(Context context) {
this.mContext = context;
}

public static Singleton getInstance(Context context) {
if (instance == null) {
instance = new Singleton(context);
}
return instance;
}
}

我们知道单例的生命周期要长于一般的组件,一般是常驻内存的,如果在创建这个单例的时候传入的是Activity的上下文那么除了应用退出,否则Activity的上下文会一直被单例持有,所以导致即使Activity被销毁掉,也不能被GC回收,从而导致了内存泄漏。

使用Context要注意的几点

一般Context造成的内存泄漏,几乎都是当Context销毁的时候,却因为被引用导致销毁失败,而Application的Context对象可以理解为随着进程存在的,所以我们总结出使用Context的正确姿势:

  • 在开发中尽量使用Application的Context,特别是生命周期长的情况下。不要让生命周期长于组件的对象持有组件的引用。
  • 非静态内部类会隐式持有外部类实例的引用,如果需要使用内部类那么需要将外部实例引用作为弱引用持有,从而避免内存泄漏。
Contents
  1. 1. Context的作用
  2. 2. Application Context
    1. 2.1. Application通常有如下常用用途:
    2. 2.2. 实现在任何位置获取Applcation Context 方法:
  3. 3. 获取Context的方式
  4. 4. 使用应用程序Context
  5. 5. 应用程序的Context数目
  6. 6. 错误使用带来的问题:
  7. 7. 使用Context要注意的几点