您的位置 首页 系统

Android_Context详解

Context对象是如此常见和传递使用,它可能会很容易产生并不是你预期的情形。加载资源、启动一个新的Activity、获取系统服务、获取内部文件路径以及

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]

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

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

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/xitong/322072.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部