context使用很多次了,还属于经常踩坑的一个点,今天没事(武汉加油(ง •̀_•́)ง)就总结一下,本文参考:http://blog.csdn.net/lmj623565791/article/details/40481055
context太常用了,加载资源、启动一个新的Activity、获取系统服务、获取内部文件(夹)路径、创建View操作时等都需要Context的参与。那么context到底是什么呢?官方解释是上下文对象,也就是用户与操作系统交互的对象,过程;包括交互的界面,以及隐藏在背后的数据信息。
从技术层面剖析context,那么它是一个抽象类,可以直接从代码看出它的结构是怎样的
可以看到Activity、Service、Application都是Context的子类;
也就是说,Android系统的角度来理解:Context是一个场景,代表与操作系统的交互的一种过程。从程序的角度上来理解:Context是个抽象类,而Activity、Service、Application等都是该类的一个实现。
在仔细看一下上图:Activity、Service、Application都是继承自ContextWrapper,而ContextWrapper内部会包含一个base context,由这个base context去实现了绝大多数的方法。
理解了context之后我们看它的使用的方式:一般在avtivity中,有两种使用方式:xxxactivity. this和getApplicationContext这两种传入方式,那这两种方式有何不同呢?一般在匿名内部类的时候不能使用. this的方式,只能使用getApplicationContext的方式,所以这两种方式返回的对象肯定不同,一个是Activity的实例,一个是Application的实例。因此这两种方式不能乱使用。
当我们在编写工具类的时候常常需要context的参与去访问资源,访问系统管理类等,这样的情况下就要注意context的使用了。
这种工具类内部保持了一个Context的引用;这个Context哪来的我们不能确定,很大的可能性,你在某个Activity里面为了方便,直接传了个this;这样问题就来了,我们的这个类中的sInstance或者方法是一个static且强引用的,在其内部引用了一个Activity作为Context,也就是说,我们的这个Activity只要我们的项目活着,就没有办法进行内存回收。而我们的Activity的生命周期肯定没这么长,所以造成了内存泄漏。这时候你说改成软引用,这样暂时没问题了,但是activity被回收了怎么办呢,就会造成抛出NullPointException的异常。又说那全部改成getApplicationContext就没有问题了,好我们暂时解决了内存泄露的问题。
但是又有一个问题,上面说了activity的context和application的context的使用场景虽然有些重合场景,但还是有不同的地方。并非所有Activity中的context都可以用application Context来表示。
下面列出context的应用场景
大家注意看到有一些NO上添加了一些数字,其实这些从能力上来说是YES,但是为什么说是NO呢?下面一个一个解释:
数字1:启动Activity在这些类中是可以的,但是需要创建一个新的task。一般情况不推荐。
数字2:在这些类中去layout inflate是合法的,但是会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用。
数字3:在receiver为null时允许,在4.2或以上的版本中,用于获取黏性广播的当前值。(可以无视)
注:ContentProvider、BroadcastReceiver之所以在上述表格中,是因为在其内部方法中都有一个context用于使用。
好了,这里我们看下表格,重点看Activity和Application,可以看到,和UI相关的方法基本都不建议或者不可使用Application,并且,前三个操作基本不可能在Application中出现。实际上,只要把握住一点,凡是跟UI相关的,都应该使用Activity做为Context来处理;其他的一些操作,Service,Activity,Application等实例都可以,当然了,注意Context引用的持有,防止内存泄漏。
至此,Context的分析基本完成了,希望大家在以后的使用过程中,能够稍微考虑下,这里使用Activity合适吗?会不会造成内存泄漏?会不会抛出异常?
今天的分析到此结束
~~~~~~~~~