初学Android的困惑
初学Android跳转页面的时候,往往教程里是这么写的:
1 | Intent intent = new Intent(); |
当时可能想当然的把setClass()当作是传递了两个class进去,从而实现了class之间的某种“切换”动作。
但是如果你看看这个方法的参数就会发现它原型其实是这样的:
1 | public android.content.Intent setClass(android.content.Context packageContext, java.lang.Class<?> cls) |
那么什么是Context呢?为什么传递个MyActivity.this就相当于传递了Context呢?这些疑问先放到一边,我们先来看另一个困惑:
初学者常常会在某个Activity里写了太多太多的代码,其实心中是向往着“面向对象”的,也希望把很多复杂的逻辑功能封装成一个外部类,而不是写在Activity里面,搞很多内部类、内部函数。但阻碍这一想法的往往是写在外部类里怎么调用startActivity(),就好像新建了一个外部的类之后,就与Android断绝了某种联系了似的变成了一个独立的java代码块。
这些困惑的主要原因就是对Android理解不够深入,对Context还不了解。
字面理解Context
Context直接翻译成汉语可以翻译成:环境变量、上下文、来龙去脉。
只从字面翻译还是很形象的,你可以直接理解为它就是Android的环境。
做个小实验你可以直接在一个Activity里直接写这样一句:
1 | Context context=getApplicationContext(); |
然后你用得到的这个context,后面加点,让IDE来自动提示你它有哪些方法。
我点几个常见的出来,是不是很眼熟?:
1 | //启动Activity |
你要操作Android的什么?系统管理、组件的开启调用、访问资源应有尽有,想做什么做什么!
这时候,是不是就可以在外部定义各种复杂逻辑的class了?只需通过构造函数传递一个Context,想怎么操作Android都没有问题。
Context的子类
现在你知道了,Context是一个高度抽象的“大环境”。那么为啥Intent传递参数的时候第一个参数是Context,你却可以写一个MyActivity.this呢?
这其实也很容易想到(善于读API和源码的小伙伴不要嘲讽……)。因为Activity和Context是继承关系,如图:
虽然隔了很多代继承,但毕竟是继承,当然可以直接传递Activity对象了(子类的向上转型嘛)。同时,在Activity里自然可以直接用startActivity等等这些成员函数了。
当然,不仅仅Activity了,Service也一样:
ps:这些图都是在官网API文档上截的,英语好的可以直接去看,提高很大的(看得懂的话也就不用看我这个教程了)。
注意两种不同Context
要注意的是,往往说Context有两种:
- Application Context
- Activity Context
其实差别就在于生命周期。
Application Context是整个Application的Context,app的进程结束了,Application Context才会结束。
而Activity Context的生命周期和你获取这个Context的Activity相关,这个Activity销毁了,这个Context也失效了。
获取Application Context的方式一般就如上文所说的调用getApplicationContext()方法就好。
获取Activity Context就是构造Intent经常用的MyActivity.this。
所以啊,你想,用Intent实现跳转的时候,这个Context只用一次就好,所以直接写MyActivity.this没有问题,但是你要是想在Activity外独立一个Class用Context实现很多很多事,又不确定这个Activity会不会被结束掉,还是乖乖地getApplicationContext()来获取一个“全局的”Context好了。
总结
总的来说,Context很强大也很神奇,你就放心地写你的java代码,有Context的地方就有Android。