Context的中文翻译为:语境; 上下文; 背景; 环境,在开发中我们经常说称之为“上下文”

在语文中,我们可以理解为语境,在程序中,我们可以理解为当前对象在程序中所处的一个环境,一个与系统交互的过程。
比如微信聊天,此时的“环境”是指聊天的界面以及相关的数据请求与传输,
Context在加载资源、启动Activity、获取系统服务、创建View等操作都要参与。

1.1context是什么?

一个Activity就是一个Context,一个Service也是一个Context。

Android程序员把“场景”抽象为Context类,他们认为用户和操作系统的每一次交互都是一个场景,
比如打电话、发短信,这些都是一个有界面的场景,
还有一些没有界面的场景,比如后台运行的服务(Service)。

一个应用程序可以认为是一个工作环境,用户在这个环境中会切换到不同的场景,
这就像一个前台秘书,她可能需要接待客人,可能要打印文件,还可能要接听客户电话,而这些就称之为不同的场景,前台秘书可以称之为一个应用程序。

1.2 四大组件不能随便new一个对象

Activity,Service,Broadcast Receiver,Content Provider这四大组件,不能随便new一个对象
四大组件必须工作在Context环境下

那Button,TextView,LinearLayout这些控件呢,可以new一个对象,
但必须工作在Context环境下,所以Button mButton=new Button(Context)是可以的。

1.3 一个应用程序有几个Context

context和容器 context and_context和容器

在应用程序中Context的具体实现子类就是:Activity,Service,Application。
那么Context数量=Activity数量+Service数量+1。

Broadcast Receiver,Content Provider并不是Context的子类,
他们所持有的Context都是其他地方传过去的,所以并不计入Context总数。

2.1 Context能干什么?

这个就实在是太多了,弹出Toast、启动Activity、启动Service、发送广播、操作数据库等等都需要用到Context

TextView tv = new TextView(getContext());

ListAdapter adapter = new SimpleCursorAdapter(getApplicationContext(), ...);

AudioManager am = (AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE);getApplicationContext().getSharedPreferences(name, mode);

getApplicationContext().getContentResolver().query(uri, ...);

getContext().getResources().getDisplayMetrics().widthPixels * 5 / 8;

getContext().startActivity(intent);

getContext().startService(intent);

getContext().sendBroadcast(intent);

2.2 Context作用域

context和容器 context and_内部类_02

凡是跟UI相关的,都应该使用Activity做为Context来处理;
其他的一些操作,Service,Activity,Application等实例都可以,
当然了,注意Context引用的持有,防止内存泄漏。

3.1 如何获取Context

通常我们想要获取Context对象,主要有以下四种方法

1:View.getContext,返回当前View对象的Context对象,通常是当前正在展示的Activity对象。

2:Activity.getApplicationContext,获取当前Activity所在的(应用)进程的Context对象,通常我们使用Context对象时,要优先考虑这个全局的进程Context。

3:ContextWrapper.getBaseContext():用来获取一个ContextWrapper进行装饰之前的Context,可以使用这个方法,这个方法在实际开发中使用并不多,也不建议使用。

4:Activity.this 返回当前的Activity实例,如果是UI控件需要使用Activity作为Context对象,但是默认的Toast实际上使用ApplicationContext也可以。

3.2 Context引起的内存泄露

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

1:当Application的Context能搞定的情况下,并且生命周期长的对象,优先使用Application的Context。

2:不要让生命周期长于Activity的对象持有到Activity的引用。

3:尽量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用,
如果使用静态内部类,将外部实例引用作为弱引用持有。

4 总结

总之Context在Android系统中的地位很重要,它几乎无所不能,
但它也不是你想用就能随便用的,谨防使用不当引起的内存问题。