1、sdk当中关于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.
http://developer.android.com/reference/android/content/Context.html
Context提供了关于应用环境全局信息的接口。它是一个抽象类,它的由整个Android应用程序所实现。它允许获取应用当中特定的资源和类,同时允许调用应用级的操作,如启动Activity,broadcasting和接收intents等等。
从以上的描述当中,我们基本获得不了什么信息,更无法理性的认识Context。
我们再来看看Context是子类和部分方法如下:
其中Application、Activity、Service等我们在开发当中常用的类,都是其子类,我们在这里也无法认识到它的作用。右图,我们可以看到,我们平时用到的startActivty();startService();等方法都在这里,在这里,我们可以看到Context的第一个作用:
2、第一个作用
Interface to global information about an application environment. This is
an abstract class whose implementation is provided by the Android system.
他提供一个全局的接口,并且这些接口由Android应用程序当中特定的类实现。
我们再来看看Activity的源码:
/**
* Launch a new activity. You will not receive any information about when
* the activity exits. This implementation overrides the base version,
* providing information about
* the activity performing the launch. Because of this additional
* information, the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag is not
* required; if not specified, the new activity will be added to the
* task of the caller.
*
* <p>This method throws {@link android.content.ActivityNotFoundException}
* if there was no Activity found to run the given Intent.
*
* @param intent The intent to start.
*
* @throws android.content.ActivityNotFoundException
*
* @see #startActivityForResult
*/
@Override
public void startActivity(Intent intent) {
startActivityForResult(intent, -1);
}
public void startActivityForResult(Intent intent, int requestCode) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
这里,startActivity()的实现调用了Context中没有的startActivityForResult方法得以实现开启新的窗体的Activity的功能。
我们再看看我们平时用到的startService方法,非常遗憾我们没有在Activity当中找到startService的实现,但是我们继续往上找,找到了ContentWrapper时,我们找到了startService的实现
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
类似的Application,service等,都可以找到其相应的函数的实现。Context功能之一就是将常用的公共方法抽取出来,然后由各个组件实现,这真是第一句话的意思。
3、第二个作用
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,broadcasting和接收intents等等。其实该类为LONG型,类似Win32中的Handle句柄,很多方法需要通过
Context才能识别调用者的实例,比如说Toast的第一个参数就是Context,一般在Activity中我们直接用this代替,代表调用者的 实例为Activity,而到了一个button的onClick(View view)等方法时,我们用this时就会报错,所以我们可能使用ActivityName.this来解决,主要原因是因为实现Context的类主要有Android特有的几个模型,Activity、Service以及BroadcastReceiver。
对于以上几句话的理解,我们可以看看TextView的构造函数
可以看到起参数为Context但是我们在实际开发当中
TextView text1 = new TextView(this);
TextView text2 = new TextView(getApplication());
TextView text3 = new TextView(getApplicationContext());
这两种定义都可以实现。this表示这个类的某个实例,而getApplicationContext()得到的是Context(),两个风马牛不相及的事物为什么能放在TextView的构造函数里,而不报错呢,这就是Context的第二个作用,句柄。标识应用程序中的不同对象和同类对象中的不同的实例。
4、两种不同的Context
正如上段代码,getApplication();getApplicationContext();前者是在Activity当中定义的,而后者是在Context当中定义的。
两者的说明分别为:
这里,我们看到了两种不同的Context:Activity所拥有的Context和全局的Context。
这是两种不同的context,也是最常见的两种。第一种中context的生命周期与Application的生命周期相关的,context随着Application的销毁而销毁,伴随application的一生,与activity的生命周期无关。第二种中的context跟Activity的生命周期是相关的,但是对一个Application来说,Activity可以销毁几次,那么属于Activity的context就会销毁多次。至于用哪种context,得看应用场景,个人感觉用Activity的context好一点,不过也有的时候必须使用Application的context。application
context可以通过Context.getApplicationContext或者Activity.getApplication方法获取。
5、内存泄露
在android中context可以作很多操作,但是最主要的功能是加载和访问资源。在android中有两种context,一种是 application context,一种是activity context,通常我们在各种类和方法间传递的是activity context。比如一个activity的onCreate:
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this); //传递context给view control
label.setText("Leaks are bad");
setContentView(label);
}
把activity context传递给view,意味着view拥有一个指向activity的引用,进而引用activity占有的资源:view hierachy, resource等。这样如果context发生内存泄露的话,就会泄露很多内存。这里泄露的意思是gc没有办法回收activity的内存。Leaking
an entire activity是很容易的一件事。
当屏幕旋转的时候,系统会销毁当前的activity,保存状态信息,再创建一个新的。
比如我们写了一个应用程序,它需要加载一个很大的图片,我们不希望每次旋转屏 幕的时候都销毁这个图片,重新加载。实现这个要求的简单想法就是定义一个静态的Drawable,这样Activity 类创建销毁它始终保存在内存中。实现类似:
public class myactivity extends Activity {
private static Drawable sBackground;
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Leaks are bad");
if (sBackground == null) {
sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);//drawable attached to a view
setContentView(label);
}
}
这段程序看起来很简单,但是却问题很大。当屏幕旋转的时候会有leak(即gc没法销毁activity)。我们刚才说过,屏幕旋转的时候系统会销毁当前的activity。但是当drawable和view关联后,drawable保存了view的 reference,即sBackground保存了label的引用,而label保存了activity的引用。既然drawable不能销毁,它所
引用和间接引用的都不能销毁,这样系统就没有办法销毁当前的activity,于是造成了内存泄露。gc对这种类型的内存泄露是无能为力的。避免这种内存泄露的方法是避免activity中的任何对象的生命周期长过activity,避免由于对象对 activity的引用导致activity不能正常被销毁。我们可以使用application context。application context伴随application的一生,与activity的生命周期无关。application context可以通过Context.getApplicationContext或者Activity.getApplication方法获取。
6、避免context相关的内存泄露,记住以下几点:
- 不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身生命周期是一样的
- 对于生命周期长的对象,可以使用application context
- 避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变化
7、制造Application context的方法
Java里面通常是用一个static的变量(例如singleton之类的)来同步activity之间(程序里面类之间)的状态。在android里面比较靠谱的做法是用application
context来关联这些状态。
每个activity都是context,里面包含了运行时的状态。同样application也有一个context,android会保证这个context是唯一的实例。
做一个你自己的application context需要继承android.app.Application,然后在app的manifest里面说明这个类。android会自动帮你创建你这个类的实例,接着你用Context.getApplicationContext()方法就能在各个activity里面获得这个application context了。
class MyApp extends Application {
private String myState;
public String getState(){
return myState;
}
public void setState(String s){
myState = s;
}
}
class Blah extends Activity {
@Override
public void onCreate(Bundle b){
...
MyApp appState = ((MyApp)getApplicationContext());
String state = appState.getState();
...
}
}
小文章,边看边写,欢迎纠错。
分享到:
相关推荐
android context理解
大家好,今天给大家分享一下Android里的Context的一些用法. 这里大致可以分为两种:一是传递Context参数,二是调用全局的Context. 其实我们应用启动的时候会启动Application这个类,这个类是在AndroidManifest.xml...
以下分别通过Context认知角度,继承关系,对象创建等方面android中Context做了深入的解释,一起学习下。 1、Context认知。 Context译为场景,一个应用程序可以认为是一个工作环境,在这个工作环境中可以存在许多场景...
主要介绍了Android 中Context的使用方法详解的相关资料,希望通过本文大家能够理解掌握context的使用方法,需要的朋友可以参考下
NULL 博文链接:https://user334.iteye.com/blog/785948
Context中文意思是上下文,在小学语文课时,我们肯定接触过联系上下文理解词语的题目,“上下文”指的是语境,我们对语境的含义肯定是比较了解,一是小学刷那么多题目,二是现实生活中也常碰到,当你暗恋的对象对你...
第12章 理解ClassLoader chapter_13 第13章 热修复原理 chapter_14 第14章 Hook技术 chapter_15 第15章 插件化技术 本书内容 本书共分为17章,各章内容如下: 第1章介绍Android系统架构、系统源码目录和...
6.6.2 关于Android中的进程管理的介绍 6.6.3 AMS进程管理函数分析 6.6.4 AMS进程管理总结 6.7 App的 Crash处理 6.7.1 应用进程的Crash处理 6.7.2 AMS的handleApplicationCrash分析 6.7.3 AppDeathRecipient ...
贴出部分代码,以供参考: private static int mTileSize; protected static int mXTileCount; protected static int mYTileCount; protected static final int RED_STAR = 1...优化了这里的构造函数,更容易理解
----------------------------------- Android 编程基础 1 封面----------------------------------- Android 编程基础 2 开放手机联盟 --Open --Open --Open --Open Handset Handset Handset Handset Alliance ...
前言 Context,在翻译为上下文,也可以理解为环境,是提供一些程序的运行环境基础信息。...可以说Context是维持Android程序中各组件能够正常工作的一个核心功能类。 Context是个抽象类,下图取自网络,可以看
Android 提供了现成 android.os.PowerManager 类 , 类中 提供newWakeLock(int flags, String tag)方法 来取得 应用层的锁, 此函数的定义 frameworks/base/core/java/android/os/PowerManager.java 应用程序 在...
所以这篇文章我们一起深入的理解Android中的建造者模式。 建造者模式(Builder Pattern)也叫生成器模式,其定义如下: separate the construction of a complex object from its representation so that the same ...
本文所述为一个基础的Android图片浏览器代码,是仿写Google原版实现的,代码中实现了主要的实现过程和方法,具体的完善还需要自己添加,代码中有很多注释,可帮助新手们快速理解代码,使用了部分图像资源。 主要功能代码...
上面是我对贝塞尔曲线立即在数学中,可能理解是错误的,Android开发中不用去管什么公式, 用api就行了 2. Adroid贝塞尔曲线绘制 2.1. 二阶绘制 2.2. 三阶绘制 xml布局: Java代码实现: public class PathView...
android 中调用drawBitmap时理解dip(屏幕密度)和px(像素)的区别 SQLiteDatabase 的setTransactionSuccessful作用 终于弄明白 paddingleft margineleft layout_gravity 和gravity之间的区别 自定义控件时要注意的...
一、拟人化来理解android中的事件机制 其实android中的事件传递与处理机制跟我们生活中的事件处理是一样的。这里有一个生活中的例子,很能说明这个问题。阐述如下: 你是一个公司的员工,你的上头有一个主管,主管...