android中的context
A. android里每个服务启动时context到底从哪里来的呢
1.android里每个服务启动时context到底从哪里来的呢????以mountservice的context为例
在SystemServer.java的run函数中有如下代码
context = ActivityManagerService.main(factoryTest);
......
if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) {
try {
/*
* NotificationManagerService is dependant on MountService,
* (for media / usb notifications) so we must start MountService first.
*/
Slog.i(TAG, "Mount Service");
mountService = new MountService(context);
ServiceManager.addService("mount", mountService);
} catch (Throwable e) {
reportWtf("starting Mount Service", e);
}
}
由此可知,由systemserver启动的服务的context都来自ActivityManagerService
ActivityManagerService.java
public static final Context main(int factoryTest) {
......
ActivityThread at = ActivityThread.systemMain();
......
Context context = at.getSystemContext();
......
return context;
}
由上可知,该context是由ActivityThread 创建的
ActivityThread .java
public ContextImpl getSystemContext() {
synchronized (this) {
if (mSystemContext == null) {
ContextImpl context =
ContextImpl.createSystemContext(this);
LoadedApk info = new LoadedApk(this, "android", context, null,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
context.init(info, null, this);
context.getResources().updateConfiguration(
getConfiguration(), getDisplayMetricsLocked(
Display.DEFAULT_DISPLAY,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO));
mSystemContext = context;
//Slog.i(TAG, "Created system resources " + context.getResources()
// + ": " + context.getResources().getConfiguration());
}
}
return mSystemContext;
}
在ContextImpl .java中
static ContextImpl createSystemContext(ActivityThread mainThread) {
final ContextImpl context = new ContextImpl();
context.init(Resources.getSystem(), mainThread, Process.myUserHandle());
return context;
}
由此可知所有systemserver启动的服务的context对象实际为一个ContextImpl对象
即ServerThread::run<-ActivityManagerService.main<-ActivityThread::getSystemContext<-ContextImpl.createSystemContext
2.对于一个apk中的context一般直接指向这个activity本身,因为activity本身即继承自context
B. Android中,Context,什么是Context
context其实就是句柄,只不过不像windows一样,每个资源都可以是一个句柄,Android的一个句柄包含了很多全局信息,比如说Activity就是一个句柄。
官方文档的解释是:Context提供了关于应用环境全局信息的接口。它是一个抽象类,它的执行被Android系统所提供。它允许获取以应用为特征的资源和类型。同时启动应用级的操作,如启动Activity,broadcasting和接收intents。
C. Android中的context是什么东西
Context,中文直译为“上下文”,SDK中对其说明如迅败察下:
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
从上可知一下三点,即:
1、它描述的是一个应用程序环境的信息,即上下文。
2、该类是一个抽象(abstract class)类,Android提供了该抽象类的具体实现类(后枯纤面我们会讲到是ContextIml类)。
3、通过它我们可以获取应用程序的资源和类,也包括一些应用级别操作,例如:亩茄启动一个Activity,发送广播,接受Intent信息等。
D. android中的Context到底该怎么用
在Android系统中,有很多的service,也就是服务。我们的程序如果用到系统功能,一般都是调用服务间接完成的。也就是在Android系统中存在许多C/S架构。而context的作用,就是android应用连接service的桥梁。比如Activity中有一个方法,getSystemService()。这个方法调到最后,实际上是调用的ContextImpl的getSystemService()方法。而ContextImpl是对Context的实现。
Context不是函数而是一个类——如果不返档太了解面向对象,可以把“类”看做一种数据类型,就像int,不过类型为“类”的数据(称为对象)可能储存远比int多的信息,比如这里的类型为Context的对象就储存关于程序、窗口的一些资源。
有些函数调用时需要一个Context参数,漏核乱比如Toast.makeText,因为函数需要知道是在哪个界面中显示的Toast。
再比如,Button myButton = new Button(this); 这里也需要Context参数(this),表示这个按钮是在“this”这个屏幕中显示的。
Android开发使用(纯粹的)面向对象语言,一切都是对象,就连我们写的函数都是对象的函数。
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(this,
"OK!",
Toast.LENGTH_LONG).show();
Button button1 = (Button)findViewById(R.id.button1);
button1.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v)
{
Toast.makeText(MainActivity.this,
"Hello, world!",
Toast.LENGTH_LONG).show();
}
});
}
}
这里OnCreate就是MainActivity的对象的函数(MainActivity是类),所以这个函数中的this就表示当前的、包含这个函数的MainActivity对象。
MainActivity extends Activity,意思是MainActivity 继承 Activity,即MainActivity 是 Activity 的一种,所有的MainActivity 都是 Activity。同样,在Android文档中Activity继承ContextThemeWrapper,ContextThemeWrapper继承ContextWrapper,ContextWrapper继承Context。所以this这个MainActivity也是Context,氏雹把this传入Toast.makeText表示“OK!”是在当前的MainActivity对象(也是Context)中显示的。
对于显示"Hello, world!"的Toast.makeText,这个函数在onClick中,而onClick是new Button.OnClickListener(){...}这个没有名字的类的函数,this表示匿名类的对象,不表示MainActivity对象,所以这里用MainActivity.this,强制选择外面一层MainActivity的this。
望采纳,谢谢。
E. Android中,Context,什么是Context
Context对象是如此常见和传递使用,它可能会很容易产生并不是你预期的情形。加载资源、启动一个新的Activity、获取系统服务、获取内部文件路径以及创建view(其实还远不止这些)统统都需要Context对象来完成。我(原文作者)想做的只是给大家提供一些Context是如何工作的见解,以及让大家在应用中更有效的使用Context的技巧。
Context的类型
并不是所有的context实例都是等价的。根据Android应用的组件不同,你访枣兄掘问的context推向有些细微的差别。
Application - 是一个运行在你的应用进程中的单例。在Activity或者Service中,它可以通过getApplication()函数获得,或者人和继承于context的对象中,通过getApplicationContext()方法获得。不管你是通过何种方法在哪里获得的,在一个进程内,你总是获得到同一个实例。
Activity/Service - 继承于ContextWrapper,它实现了与context同样API,但是代理这些方法调用到内部隐藏的Context实例,即我们所知道的基础context。任何时候当系统创建一个新的Activity或者Service实例的时候,它也创建一个新的ContextImpl实例来做所有的繁重的工作。每一个Activity和Service以及其对应的基础context,对每个实例来说都是唯一的。
BroadcastReciver - 它本身不是context,也没有context在它里面,但是每当一个新的广播到达的时候,框架都传递一个context对象到onReceive()。这个context是一个ReceiverRestrictedContext实例,它有两个主要函数被禁掉:registerReceiver()和bindService()。这两个凳核函数在BroadcastReceiver.onReceive()不允许调用。每次Receiver处理一个广播,传递进来的context都是一个新的实例。
ContentProvider - 它本身也不是一个Context,但是它可以通过getContext()函数给你一个Context对象。如果ContentProvider是在调用者的的本地(例如,在同一个应用进程),getContext()将返回的是Application单例。然而,如果调用这和ContentProvider在不同的进程的时候,它将返回一个新创建的实例代表这个Provider所运行的包。
保存引用
第一个我们需要解决问题是,在一个对象或者类内部保存一个context引用,而它生命周期却超过其保存引用的对象的尘迟生命周期。例如,创建一个自定义的单例,它需要一个context来加载资源或者获取ContentProvider,从而保存一个指向当前Activiy或者Service的引用在单例中。
糟糕的单例
[java] view plain
public class CustomManager {
private static CustomManager sInstance;
public static CustomManager getInstance(Context context) {
if (sInstance == null) {
sInstance = new CustomManager(context);
}
return sInstance;
}
private Context mContext;
private CustomManager(Context context) {
mContext = context;
}
}
这里的问题在于,我们不知道这个context是从哪里来的,并且如果保存一个最终指向的是Activity或者Servece的引用是并不安全的。这是一个问题,是因为一个单例在类的内部维持一个唯一的静态引用,这意味着我们的对象,以及所有其他它所引用的对象,将永远不能被垃圾回收。假如这个Context是一个Activity,我们将保存与这个Activity相关的所有的view以及其他大的对象,从而造成内存泄漏。
为了解决这个问题,我们修改单例永远只是保存Application context:
改善的单例:
[java] view plain
public class CustomManager {
private static CustomManager sInstance;
public static CustomManager getInstance(Context context) {
if (sInstance == null) {
//Always pass in the Application Context
sInstance = new CustomManager(context.getApplicationContext());
}
return sInstance;
}
private Context mContext;
private CustomManager(Context context) {
mContext = context;
}
}
现在这个例子中,我们的Context来自哪里都没有关系,因为我们这里保存引用是安全的。Application Context 本身就是一个单例,所以我们再创建另外一个static引用,不会造成任何内存泄漏。另外一个很好的例子是,在后台线程或者一个等待的Handler中保存Context的引用,也可以使用这样的方法。
为什么我们不能总是引用Application context呢?正如前面说的,引用Application context永远不用担心内存泄漏的问题。问题的答案,就像我在开始的介绍中说的,是因为不同context并不是等价的。
Context的能力
Conext能做的通用操作决定于这个context最初来源于哪里。下表所列的是,在应用中常见的会收到context对象的,以及对应的每种情况,它可以用于哪些地方:
Application
Activity
Service
ContentProvider
BroadcastReceiver
Show a Dialog NO YES NO NO NO
Start an Activity NO1 YES NO1 NO1 NO1
Layout Inflation NO2 YES NO2 NO2 NO2
Start a Service YES YES YES YES YES
Bind to a Service YES YES YES YES NO
Send a Broadcast YES YES YES YES YES
Register BroadcastReceiver YES YES YES YES NO3
Load Resource Values YES YES YES YES YES
注:NO1 表示Application context的确可以开始一个Activity,但是它需要创建一个新的task。这可能会满足一些特定的需求,但是在你的应用中会创建一个不标准的回退栈(back stack),这通常是不推荐的或者不是是好的实践。
NO2 表示这是非法的,但是这个填充(inflation)的确可以完成,但是是使用所运行的系统默认的主题(theme),而不是你app定义的主题。
NO3 在Android4.2以上,如果Receiver是null的话(这是用来获取一个sticky broadcast的当前 值的),这是允许的。
用户界面UI
从前面的表格中可以看到,application context有很多功能并不是合适去做,而这些功能都与UI相关。实际上,只有Activity能够处理所有与UI相关的任务。其他类别的context实例功能都差不多。
幸运的是,在应用中这三种操作基本上都不需要在Activity范围之外进行,这很可能是android框架故意这么设计的。尝试显示一个使用Aplication context创建的Dialog,或者使用Application context开始一个Activity,系统会抛出一个异常,让你的application崩溃,非常强的告诉你某些地方出了问题。
一个并不明显的问题是填充布局(inflating layout)。如果你已经读过了我(原文作者)的上一篇文章Layout inflation,你就已经知道它可能是一个非常神秘过程,伴随一些隐藏的行为。使用正确的context关系到其中的一个行为。当你使用Application context来inflate一个布局的时候,框架并不会报错,并返回一个使用系统默认的主题创建一个完美的view给你,而没有考虑你的applicaiton自定义的theme和style。这是因为Acitivity是唯一的绑定了在manifast文件种定义主题的Context。其他的Context实例将会使用系统默认的主题来inflater你的view。导致显示的结果并不是你所希望的。
规则的路口
可能有些读者已经得出两个规则互相矛盾的结论。可能有些情况下,在某些Application的设计中,我们可能既必须长期保存一个的引用,并且为了完成与UI相关的工作又必须保存一个Activity。如果出现这种情况,我将会强烈建议你重新考虑你的设计,它将是一个很好的“反框架”教材。
经验法则
绝大多数情况下,使用在你的所工作的组建内部能够直接获取的Context。只要这个引用没有超过这个组建的生命周期,你可以安全的保存这个引用。一旦你要保存一个context的引用,它超过了你的Activity或者Service的生命周期范围,甚至是暂时的,你就需要转换你的引用为Application context。
F. android中的context是什么意思,能详细说一下吗
context是环境,上下文的意思。在程序中,起码我没有发现更帆型好腔轿局的翻译。软件中间很多词在翻译成中文的时候,都是只可意会不可言传的。大意就是只一个伍让范围,比如变量的生存范围、会话范围等。
G. android context是什么
Context字面意思是上下文,位于framework package的android.content.Context中,其实该类为LONG型,类似Win32中的Handle句柄。很多方法需要通过 Context才能识别调用者的实例:比如说Toast的第一个参数就是Context,一般在Activity中我们直接用this代替,代表调用者的实例为Activity,而到了一个button的onClick(View view)等方法时,我们用this时就会报错,所以我们可能使用ActivityName.this来解决,主要原因是因为实现Context的类主要有Android特有的几个模型,Activity以及Service。
Context提供了关于应用环境全局信息的接口。它是一个抽象类,它的执行被Android系统所提供。它允许获取以应用为特征的资源和类型。同时启动应用级的操作,如启动Activity,broadcasting和接收intents。
H. 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代理类,调用到scheleLaunchActivity(),然后在应用的线程开始执行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引用去获取信息和通用操作等,也就是说,我们可以通过这个引用去获取到这个应用中的重要信息以及这个应用的通用操作。
I. android中的context是起什么作用的
当我们访问当前应用的资源,启动一个新的activity的时态大仔候都需要提供Context。
Context是一个抽象基类,我们仿唯通过它访问当前包的资源(getResources、getAssets)和启动其他组件(Activity、Service、Broadcast)以及得到各种服务(getSystemService),当然,通过Context能得到的不仅仅只有上述这些内容。对Context的理解可以来说:Context提供了一个应用的运行环境,在Context的大环境里,应用才可以访问资源,才能完成和其他组件、服务的交互,Context定义了一套基本的功能接口,可以理解为一套规范,而Activity和Service是实现这套规范的子类,这么说也许并不准确,因为这套规范实际是被ContextImpl类统一实现的,Activity和Service只是继承并有选择性地重写了某些规范的实现。
activity继承关系
可以看出几个组件都继承于Context
一个应用中Context的数量等于Activity的个数+ Service的个数+ 1,这帆汪个1为Application
J. android中的context和this的区别
在android中常常会遇到与context有关的内容,特写下这篇blog,浅论一下context : 在语句 AlertDialog.Builder builder = new AlertDialog.Builder(this); 中,要求传递的 参数就是一个context,在这里我们传入的是this,那么这个this究竟指的是什么东东呢? 这里的this指的是Activity.this,是这个语句所在的Activity的this,是这个Activity 的上下文。网上有很多朋友在这里传入this.getApplicationContext(),这是不对的。 AlertDialog对象是依赖于一个View的,而View是和一个Activity对应的。 于是,这里涉及到一个生命周期的问题,this.getApplicationContext()取的是这个应 用程序的Context,Activity.this取的是这个Activity的Context,这两者的生命周期是不同 的,前者的生命周期是整个应用,后者的生命周期只是它所在的Activity。而AlertDialog应 该是属于一个Activity的,在Activity销毁的时候它也就销毁了,不会再存在;但是,如果传 入this.getApplicationContext(),就表示它的生命周期是整个应用程序,这显然超过了它 的生命周期了。 所以,在这里我们只能使用Activity的this
context指的上下文环境
this指的是本类的对象,
一般情况:有context但是不一定有this,有this一定有context环境