作为一个Android开发者,相信大家都一定接触并使用过context吧,以前只是用并不了解他真正的机制,似懂非懂,总想把他研究一下,搞透他,最近手头的活稍微少一点,可以稍微喘口气好好记录一下自己对的看法和感受了。
如果你有你自己的看法或者我的说法有不对的地方欢迎指正。1.Context、 What Context?
Context is probably the most used element in Android applications…it may also be the most misused.–https://possiblemobile.com/2013/06/context/这是在这个网址上看见的第一句话。Context相信大家都不陌生。几乎每个从事Android的开发者都用过,他的身影随处可见,Intent实现页面跳转,弹吐司,创建View,加载资源等等,它几乎是我们最常用的,但也是我们经常滥用的!首先什么是Context,简单从字面上来看就是上下文,背景和环境。从程序角度来看就是一个抽象类,而,Activity,Service都是其的实现类。其内部有众多资源。Context提供了一个应用的运行环境,在Context的大环境里,应用才可以访问资源,才能完成和其他组件、服务的交互,Context定义了一套基本的功能接口,可以理解为一套规范,而Application,Activity和Service是实现这套规范的子类,这么说也许并不准确,因为这套规范实际是被ContextImpl类统一实现的,Activity和Service只是继承并有选择性地重写了某些规范的实现。故而说不是说所有的Context实例都是相同的,它取决于你的应用程序组件,访问的时候可以稍有不同。
其层级关系是:
2.Context 不同的应用场景
这张图片也许大家都见过很多次,这也是我在该网站http://www.doubleencore.com/2013/06/context/直接下载的,他展示了Context在不同的环境下应该使用那种类型。(注:在原有的基础上我去掉了广播接受者和内容提供者,原因是二者并不是继承与他,只是在其内部方法中都有一个context用于使用,故不做讨论)
解释:
No:不能使用
NO1:可以使用,可以创建一个新的任务但是不推荐。
NO2:可以使用,但是会使用默认主题,自定义主题失效。
在一般的用法中,我们常常使用xxxActivity.this,或者在页面跳转时使用
Intent intent = new Intent(this, xxxActivity.class);
startActivity(intent);
来实现页面的跳转,或者使用布局加载器
View inflate = LayoutInflater.from(this).inflate(resource, rootView);
来获取View布局,此时我们我们所使用的一般都是当前activity实例化的上下文。也就是说其生命周期适合activity一致的。
但是当我们写一个单例,类中的对象是一个static且强引用的,在其内部引用了一个Activity作为Context,也就是说,我们的这个Activity只要我们的项目活着,就没有办法进行内存回收。而我们的Activity的生命周期肯定没这么长,所以造成了内存泄漏。此时也许会有人说定义成软引用不就行了,当然这样会出现另外一个问题,Context被回收,但是恰好我刚要调用,此时会报空指针异常。
public class User{
private static User user;
private Context mContext;
private User(Context context)
{
this.mContext = context;
}
public static synchronized User getInstance(Context context)
{
if (user== null)
{
user= new User(context);
}
return user;
}
}
故而我们只需要
if (user== null)
{
user= new User(context.getApplicationContext());
}