Context是什么
展开全部
Context
Context,翻译是上下文环境,在android应用开发中的地位举足轻重,甚至源码也有一句话:everything needs a context(看到过,但是忘了在哪里了)。
从这个类图中我们看到,Context是一个抽象类,一边是Context的具体实现ContextImpl,一边则是组件的封装类ContextWrapper,便于二者各司其职,我理解是接口和实现分开,这样比较符合开闭原则吧。
既然要搞清楚Context是干嘛的,得先看Context的实例什么时候创建的。这里有两个我们经常接触的组件,Activity和Service,以及用的较少的Application,它们的关系如下:
1.Application:保存应用的全局信息的类,它的实例在应用创建的时候被创建,生命周期最长,应用销毁了才会被销毁。
2.Activity:创建一个Activity便对应一个Context的实例,生命周期随着Activity的周期变化。
3.Service:创建一个Service便对应一个Context的实例,生命周期随着Service的周期变化。
下面逐一看看它们是什么时候实例Context类的,我们需要知道,一个ContextWrapper类对应一个ContextImpl类的实例,因为具体实现的地方还是在ContextImpl中,ContextWrapper中的mBase变量指向ContextImpl变量的实例。
(1) Application的Context创建:
如图:
跳过Process创建过程,在我们的应用被zygote进程孵化出来后,被反射调用main函数,这里会创建ActivityThread类的实例,该类并不是一个线程类的子类,但是它的main函数跑在新创建的进程的主线程。 创建后,调用attach方法,与AMS绑定:
这里传入的mAppThread变量为ApplicationThread类,它为ActivityThread的内部类,作用就是作为应用端的binder服务端,负责接收AMS的调度,这里我们传入这个服务端的句柄,让AMS持有,从而AMS可以通过这个句柄来操控应用的行为。我们向AMS请求,则是通过AMS的句柄。接下来就到了AMS的逻辑:
在ApplicationThread的实现端中,就是把跨进程传递过来的各种数据再用一个AppBindData类保存下来,然后调用Handler对象H发送消息BIND_APPLICATION,最后在app线程中处理此逻辑,让AMS线程可以不必同步阻塞。接下来就到了handleBindApplication:
Instrumentation类是用于管理Acitivty的工具类。这又有一个比较重要的对象出现,LoadedApk,它里面保存了类加载器ClassLoader,data.info的对象便是它,makeApplication函数中的逻辑:
这里我们看到了ContextImpl的创建时机,就是在Application实例创建的时候:
如此就完成了Application的创建,并且调用attach方法把Application的mBase对象赋值给创建的ContextImpl,至此Application的创建就完成了,getApplicationContext() 返回的便是此处我们创建的Application类的对象。
这里为什么要去LoadedApk类中利用类加载器,把对象创建出来呢?因为我们的Application类是可以自己拓展的,创建的时候是不确定应用自己是否复写了Application对象, 利用类加载器就可以动态决定创建什么类的对象了 ,我们只需要从PMS中获取到application的具体类名即可,这个类名是写在Mainfest文件中的,后面Activity也是利用这种机制去创建对象。
(2)Actvity的启动过程,网上非常多文章分析了,我也就不再重复罗列出来了,大概的过程就是startActivity()被调用,然后检查目标Acitivity的进程是否创建,没创建就先向Zygote进程请求fork应用进程,然后一系列初始化过程后,最后在AMS模块中的ActivityStackSupervisor中realStartActivityLocked()调用IApplicationThread代理类,调用到scheduleLaunchActivity(),然后在应用的线程开始执行handleLaunchActivity(),最主要的逻辑在performLaunchActivity:
至于Activity的生命周期后面怎么走的,这里不在乎,我们只看Context实例化过程。同样的,这里也会创建ContextImpl对象,在Activity对象创建后,调用Attach(),这个函数挺重要的,我们看看都干了什么:
在attach函数中,也会为ContextWrapper中的mBase对象赋值一个ContextImpl对象,我们这里也能猜想到Service的创建估计也会有这个过程,而事实上Service的创建差不多也是这个过程,所以不再赘述了。
我们可以知道Context例的实例化都是在我们在Application,Activity和Service创建的时候会实例化,而这些组件的父类都是ContextWrapper,所以在创建的时候还会先创建一个ContextImpl类对象,然后给自己的父类mBase变量赋值,既然如此,Context的引用对应的就是Application,Activity和Service了,Context的用处就是提供了一组抽象的函数,让子类去相对应的实现,当你持有一个Context引用的时候,你可以通过这个引用去获取相对应组件的信息。比如持有一个Activity的Context引用,你可以在别的地方调用startActivity()去启动一个新的activity。
总结:
1.Context是抽象类,所以实例化要在子类中,Application,Service,Activity是我们实例化的地方,一般应用创建会实例化一个Application类,Service和Activity则是在startService和StartActivity被调用的时候会实例化,它们都会创建一个ContextImpl类实例,给自己的父类ContextWrapper的mBase变量赋值。
2.Context是组件中通用操作的一组集合,当具体的子类实例化后,可以在别的地方通过保存一个Context引用去获取信息和通用操作等,也就是说,我们可以通过这个引用去获取到这个应用中的重要信息以及这个应用的通用操作。
Context,翻译是上下文环境,在android应用开发中的地位举足轻重,甚至源码也有一句话:everything needs a context(看到过,但是忘了在哪里了)。
从这个类图中我们看到,Context是一个抽象类,一边是Context的具体实现ContextImpl,一边则是组件的封装类ContextWrapper,便于二者各司其职,我理解是接口和实现分开,这样比较符合开闭原则吧。
既然要搞清楚Context是干嘛的,得先看Context的实例什么时候创建的。这里有两个我们经常接触的组件,Activity和Service,以及用的较少的Application,它们的关系如下:
1.Application:保存应用的全局信息的类,它的实例在应用创建的时候被创建,生命周期最长,应用销毁了才会被销毁。
2.Activity:创建一个Activity便对应一个Context的实例,生命周期随着Activity的周期变化。
3.Service:创建一个Service便对应一个Context的实例,生命周期随着Service的周期变化。
下面逐一看看它们是什么时候实例Context类的,我们需要知道,一个ContextWrapper类对应一个ContextImpl类的实例,因为具体实现的地方还是在ContextImpl中,ContextWrapper中的mBase变量指向ContextImpl变量的实例。
(1) Application的Context创建:
如图:
跳过Process创建过程,在我们的应用被zygote进程孵化出来后,被反射调用main函数,这里会创建ActivityThread类的实例,该类并不是一个线程类的子类,但是它的main函数跑在新创建的进程的主线程。 创建后,调用attach方法,与AMS绑定:
这里传入的mAppThread变量为ApplicationThread类,它为ActivityThread的内部类,作用就是作为应用端的binder服务端,负责接收AMS的调度,这里我们传入这个服务端的句柄,让AMS持有,从而AMS可以通过这个句柄来操控应用的行为。我们向AMS请求,则是通过AMS的句柄。接下来就到了AMS的逻辑:
在ApplicationThread的实现端中,就是把跨进程传递过来的各种数据再用一个AppBindData类保存下来,然后调用Handler对象H发送消息BIND_APPLICATION,最后在app线程中处理此逻辑,让AMS线程可以不必同步阻塞。接下来就到了handleBindApplication:
Instrumentation类是用于管理Acitivty的工具类。这又有一个比较重要的对象出现,LoadedApk,它里面保存了类加载器ClassLoader,data.info的对象便是它,makeApplication函数中的逻辑:
这里我们看到了ContextImpl的创建时机,就是在Application实例创建的时候:
如此就完成了Application的创建,并且调用attach方法把Application的mBase对象赋值给创建的ContextImpl,至此Application的创建就完成了,getApplicationContext() 返回的便是此处我们创建的Application类的对象。
这里为什么要去LoadedApk类中利用类加载器,把对象创建出来呢?因为我们的Application类是可以自己拓展的,创建的时候是不确定应用自己是否复写了Application对象, 利用类加载器就可以动态决定创建什么类的对象了 ,我们只需要从PMS中获取到application的具体类名即可,这个类名是写在Mainfest文件中的,后面Activity也是利用这种机制去创建对象。
(2)Actvity的启动过程,网上非常多文章分析了,我也就不再重复罗列出来了,大概的过程就是startActivity()被调用,然后检查目标Acitivity的进程是否创建,没创建就先向Zygote进程请求fork应用进程,然后一系列初始化过程后,最后在AMS模块中的ActivityStackSupervisor中realStartActivityLocked()调用IApplicationThread代理类,调用到scheduleLaunchActivity(),然后在应用的线程开始执行handleLaunchActivity(),最主要的逻辑在performLaunchActivity:
至于Activity的生命周期后面怎么走的,这里不在乎,我们只看Context实例化过程。同样的,这里也会创建ContextImpl对象,在Activity对象创建后,调用Attach(),这个函数挺重要的,我们看看都干了什么:
在attach函数中,也会为ContextWrapper中的mBase对象赋值一个ContextImpl对象,我们这里也能猜想到Service的创建估计也会有这个过程,而事实上Service的创建差不多也是这个过程,所以不再赘述了。
我们可以知道Context例的实例化都是在我们在Application,Activity和Service创建的时候会实例化,而这些组件的父类都是ContextWrapper,所以在创建的时候还会先创建一个ContextImpl类对象,然后给自己的父类mBase变量赋值,既然如此,Context的引用对应的就是Application,Activity和Service了,Context的用处就是提供了一组抽象的函数,让子类去相对应的实现,当你持有一个Context引用的时候,你可以通过这个引用去获取相对应组件的信息。比如持有一个Activity的Context引用,你可以在别的地方调用startActivity()去启动一个新的activity。
总结:
1.Context是抽象类,所以实例化要在子类中,Application,Service,Activity是我们实例化的地方,一般应用创建会实例化一个Application类,Service和Activity则是在startService和StartActivity被调用的时候会实例化,它们都会创建一个ContextImpl类实例,给自己的父类ContextWrapper的mBase变量赋值。
2.Context是组件中通用操作的一组集合,当具体的子类实例化后,可以在别的地方通过保存一个Context引用去获取信息和通用操作等,也就是说,我们可以通过这个引用去获取到这个应用中的重要信息以及这个应用的通用操作。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询