https://www.jianshu.com/p/7b4eb11bcbd1
https://blog.csdn.net/lanxingfeifei/article/details/50674667
https://blog.csdn.net/iaiti/article/details/12871445
在Android api当中是这样描述context对象的。
"Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc."
“是一个用于实现关于应用环境的整体信息的一个接口。这是一个由安卓系统提供的抽象类并且系统有对他进行实现。它允许访问到应用特殊的资源和类,同时它也可以实现到应用级别的操作,例如:Activity的启动,广播的实现和接受intent等。”
一、Context的主要实现和继续理解
知道了context的大概描述,我们可以再继续理解Context这个神秘的对象了,首先,作为基类,肯定有其它类去实现它,主要实现了context类的类是Activity,Service,Application。他们三个类虽然都是Context的子类,但是具体的继承关系却有些不大一样:
Activity的继承关系:
Service和Application的继承关系:
可以看出我们的Context其实就是我们熟知的Activity,Service,Application。
在这3个类中,Activity的context对象和Application的context对象最容易弄混淆。
二、Context中的主要方法
知道了Context的大概描述和他的一些继承关系,我们对Context这个类有了一个大致的了解。现在可以看看在context中的一些方法,来加深对context的一个理解,有很多我们使用过的方法其实都是从Context这个类中实现而来。
我们从Android api中查看Context类,这里出现了一个非常熟悉的方法:startActivity,可以看到其实Activity中的StartActivity方法是重写了Context中的方法。
abstract voidstartActivity(Intentintent)
Same asstartActivity(Intent, Bundle)with no options specified.
abstract voidstartActivity(Intentintent,Bundleoptions)
Launch a new activity.
同时context还可以访问到资源文件,获得资源文件中的信息。
abstractResourcesgetResources()
Return a Resources instance for your application's package.
abstractSharedPreferencesgetSharedPreferences(Stringname, int mode)
Retrieve and hold the contents of the preferences file 'name', returning a SharedPreferences through which you can retrieve and modify its values.
finalStringgetString(int resId)
Return a localized string from the application's package's default string table.
finalStringgetString(int resId,Object...formatArgs)
Return a localized formatted string from the application's package's default string table, substituting the format arguments as defined inFormatterandformat(String, Object...).
同时context不但可以开启一个activity,同时还可以开启或者关闭一个Service。
abstractComponentNamestartService(Intentservice)
Request that a given application service be started.
abstract booleanstopService(Intentservice)
Request that a given application service be stopped.
访问Android Api 或者查看源码可以看到,Context中还有很多访问资源文件和程序之间互相通信的方法。
可以看出context其实就是一个应用之中的手脚,可以通过他来拿取资源文件中的资源,还可以通过他来处理Activity和Service中的一些操作,这个类就是整个程序的枢纽,负责管理整个程序的通畅运行。
我们可以通过分析一个Toast通知的源码去分析context的去向和使用,来了解context到底做了些神马操作:
public static Toast makeText(Context context, CharSequence text, int duration) {
Toast result = new Toast(context);
LayoutInflater inflate = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
tv.setText(text);
result.mNextView = v;
result.mDuration = duration;
return result;
}
可以看到makeText方法接受的context被用于
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
这是用于获取XML中定义的View的方法,可以看到通过外部传入的Context,在这里获得了一个View布局用于显示Toast。
public Toast(Context context) {
mContext = context;
mTN = new TN();
mTN.mY = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.toast_y_offset);
mTN.mGravity = context.getResources().getInteger(
com.android.internal.R.integer.config_toastDefaultGravity);
}
这一行中可以看出在context又被用来获取资源文件,可以看出Toast的显示和布局都是通过context去调用系统写好的资源文件来进行实现的。
三、Activity context和Application context的区别
Activity的context和Application的context的区别在于生命周期的区别,Activity的context是依附在着Activity的生命周期的,而Application的Context的生命周期是依附在整个应用之上的。
不看不知道,看了之后,你会不会大吃一惊,原来我们经常使用的Context用这么多的机场关系。我是在看到这幅图之前是没有见过ContextImpl, ContextWrapper这两个类的。
既然类名不一样,肯定功能也是不一样的。ContextWrapper这个类是上下文功能的封装类,ContextImpl则是上下文功能的实现类。从图中可以很清楚的看到,ContextWrapper这个类有三个直接的子类,一个是Application , 一个是Service 这两个都是我们非常熟悉的和常用的类,还用一个ContextThemeWrapper这个类,我们不经常使用,但是咱们在看看这个类的直接子类是Activity这个类,大家就不会陌生了。但是为什么Acitivity不是跟Appliciton, Service平级,而非的在封装一层呢,那咱们在来看一看ContextThemeWrapper这个类,从意思是带主题的封装类。
现在我们看到的常用的Application, Activity, Service都是Context的一种类型,这三个类的作用是完全不相同的。他们具体的Context功能则是由ContextImpl类去实现的。我们最常使用的Context的地方,就是弹出Toast, 启动Activity, 启动service ,发送广播,等等,使用的地方真是太多了。但是由于Context的具体功能是由ContextImpl类去实现的,因此在绝大多数场景下,Activity , Service, 和 Application这三种类型的Context都是可以通用的。但是肯定会有一些特殊的情况,比如说,一个Activity跳转到另一个的Activtiy.
Intent intent= new Intent(context,要跳转的Activity的名字.class);
一个Activity的启动必须要建立在另一个Activity的基础之上。也就是以此形成了一个返回栈。因此在这种情况下,我们只能使用Activity类型的Context, 否则将会出错。
一个工程中那么多地方使用Context, 但是到底有多少个Context ??? 这个也是可以计算的。因为Context 有三种类型,Activity , service, Applictation. 所以一个项目中Context的数量,就可以这样计算。
Context 数量 = Activity的数量 + Service的数量 + 1 (application)
五、this在匿名内部类中
写语句的时候有两种情况:
- Toast.makeText(AlarmActivity.this,"闹钟取消", Toast.LENGTH_SHORT);
- <pre name="code" class="java">Toast.makeText(this,"闹钟5秒后启动", Toast.LENGTH_SHORT);
用英文在google搜what‘s difference between this and Activity.this,终于有了结果(其实自己后面用了Java里ClassName.this和this 之前搜的是Activity.this,所以没有结果,这点自己要灵活的提高自己的搜索能力了)。
在StackOverFlow找到了答案:
http://stackoverflow.com/questions/10102151/whats-the-difference-between-this-and-activity-this
- Intent intent = new Intent(this, SecondActivity.class);
- eclipse error: The method setClass(Context, Class) in the type Intent is not applicable for the arguments (FirstActivity.ClickEvent, Class)
- Intent intent = new Intent(FirstActivity.this, SecondActivity)
this
refers to your current object. In your case you must have implemented the intent in an inner class ClickEvent, and thats what it points to.
Activity.this
points to the instance of the Activity you are currently in.
this是你当前对象的引用,在你的例子中你肯定在内部类ClickEvent里面实现intent,他指向的是ClickEvent,而不是你要传入的Activity。
Activity.this指向你所填写的Activity名字的一个实例,也是引用。
其实这是java的基础,我自己忘了。
this作为当前对象,直接用在Activity里面是没问题的,当this在匿名内部类中使用,当前的对象就变成new的内部类,而你传入的东西如果是整个Activity的话,就要Activity.this了。
- Button b.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- Toast.makeText(AlarmActivity.this,"闹钟5秒后启动", Toast.LENGTH_SHORT);
- }};
所以在这里面需要指定是哪个activity的,Toast的那条语句移到外面,删掉AlarmActivity也行。
this作为当前对象,直接用在Activity里面是没问题的,当this在匿名内部类中使用,当前的对象就变成new的内部类,而你传入的东西如果是整个Activity的话,就要Activity.this了。
六、this与context
this代表当前activity的对象,而activity属于context的子类,所以this肯定是content的对象啊。
七,startactivity,startservice,创建新的context对象,原来的对象不会立即自己消失
startService:只要stop直接关服务,如果有服务,start不会重新创建,但可以向onStartCommand(Intent, int, int)
传信息,和bound一样,大量信息传递用bound services
,start耗系统资源。客户端:只有bound的时候,bound的那个activity才是。
ComponentName startService (Intent service)
Request that a given application service be started. The Intent should either contain the complete class name of a specific(特殊的) serviceimplementation(实现) to start, or a specific package name to target. If the Intent is less specified(指定), it logs a warning about this. In this case any of the multiple matching services may be used. If this service is not already running, it will be instantiated(例示) and started (creating a process for it if needed); if it is running then it remains running.
Every call to this method will result in a corresponding call to the target service's onStartCommand(Intent, int, int)
method, with the intent given here. This provides a convenient way to submit(服从) jobs to a service without having to bind(绑) and call on to its interface(界面).
Using startService() overrides(代理佣金) the default service lifetime that is managed by bindService(Intent, ServiceConnection, int)
: it requires the service to remain running until stopService(Intent)
is called, regardless(不管) of whether any clients are connected to it. Note that calls to startService() do not nest: no matter how many times you call startService(), a single call to stopService(Intent)
will stop it.
The system attempts to keep running services around as much as possible. The only time they should be stopped is if the current foreground(前景)application is using so many resources that the service needs to be killed. If any errors happen in the service's process, it will automatically(自动地) be restarted(重新启动).
This function will throw SecurityException
if you do not have permission to start the given service.
Note: Each call to startService() results in significant(重大的) work done by the system to manage service lifecycle(生活周期) surrounding the processing of the intent(意图), which can take multiple milliseconds(毫秒) of CPU time. Due to this cost, startService() should not be used for frequent intent delivery(交付) to a service, and only for scheduling(安排) significant work. Use bound services
for high frequency(频率) calls.
八、context在实际中的用法,
adapter = new Bluetooth_adapter(MainActivity.this, R.layout.bluetoothinfo_item, mDevices);
然后在我们自定义的adpter类中实现自定义的布局,会用到getcontext(),获取的就是manactivity;