Context,what Context?
本文来源于:https://possiblemobile.com/2013/06/Context/
Context(以下用上下文代替)可能是Android应用程序中使用最多的元素……它也可能是被误用最多的元素。上下文对象是如此常见,并且传递得如此频繁,因此很容易创建您不打算创建的场景。加载资源、启动新活动、获取系统服务、获取内部文件路径和创建视图都需要用上下文来完成该任务。下面是一些技巧,这些技巧将会让您在应用程序中更加有效地利用上下文。下面让我们一起来了解一下。
一、上下文的类型
根据Android应用程序组件的不同,我们可以访问的上下文也略有不同:
- Application-是在应用程序进程中运行的单例实例。我们可以通过活动或服务中的getApplication()和从上下文继承的任何其他对象中的getApplicationContext()等方法访问它。无论访问的位置和方式如何,都会在流程中收到相同的实例
- Activity/Server - 继承或实现相同API的ContextWrapper,其所有方法调用代理到一个隐藏的内部上下文实例(也称为基本上下文)。每当框架创建一个新的Activity或Service实例时,它还会创建一个新的ContextImpl实例来完成任一组件将要包装的所有繁重工作。每个活动或服务及其对应的基本上下文中的每个实例都是惟一的。
- BroadcastReceiver - 本身并不是Context,但是 每当有新的广播事件进入时,框架 都会在onReceive()中向BroadcastReceiver传递一个Context。这个实例是一个ReceiverRestrictedContext,它禁用了两个主要功能; 调用registerReceiver()和bindService(),现有的BroadcastReceiver.onReceive()中不允许这两个函数。每次接收者处理广播时,传递给它的上下文都是一个新实例。
- ContentProvider - 也不是Context,但在创建时可以通过getContext()访问获取上下文实例。如果ContentProvider在调用者本地运行(即相同的应用程序进程),那么这实际上将返回相同的应用程序单例。但是,如果这两个进程位于不同的进程中,则这将是一个新创建的实例,表示运行提供程序的程序包。
二、使用方法
首先来解决在对象或类中保存对上下文的引用,以确保该对象或类的生命周期能够超出我们保存的实例的生命周期,创建一个自定义单例,需要Context加载资源或访问ContentProvider,并保存对该单例中当前Activity或Service的引用
错误的单例示范
这里有一个问题,我们并不知道Context来自何处,如果最终成为Activity或Service,则保持对该对象的引用是不安全的。这是一个问题,因为单例由封闭类中的单个静态引用管理。这意味着我们的对象以及它引用的所有其他对象永远不会被垃圾回收。如果这个Context是一个Activity,那么我们将会在内存中保留所有视图和与它关联的其他潜在大型对象; 造成内存泄漏。
为了防止这种情况,我们修改单例,以始终引用应用程序上下文:
正确的单例示范
现在我们的Context来自哪里并不重要,因为我们持有的引用是安全的。应用程序上下文本身就是一个单例,因此我们不会通过创建另一个静态引用来泄漏任何内容。另一个很好的例子是在运行的后台线程或挂起的处理程序中保存对上下文的引用。
上下文功能
对于给定的上下文对象,是否可以安全地采取的常见操作,取决于它最初来自何处。下面是应用程序接收上下文的常见位置表,以及在每种情况下它的用途:
表格中的数字注解:
- 应用程序可以从这里启动一个活动,但是它需要创建一个新任务。这可能适合特定的用法,它可能会在应用程序中创建非标准的回栈行为,通常不推荐这样使用。
- 它是可以使用的,但是布局膨胀将会使用您所运行的系统的默认主题来完成,而不是应用程序中自定义的主题。
- 允许你使用的前提是接收器为空,该空值用于获取Android 4.2及以上版本粘性广播的当前值。