一、Context 基础概念

1、什么是Context

1) Context是一个抽象类,其通用实现在ContextImpl类中。

2) Context:是一个访问application环境全局信息的接口,通过它可以访问application的资源和相关的类,其主要功能如下:

• 启动Activity
        • 启动和停止Service
        • 发送广播消息(Intent)
        • 注册广播消息(Intent)接收者
        • 可以访问APK中各种资源(如Resources和AssetManager等)
        • 可以访问Package的相关信息
        • APK的各种权限管理

从以上分析可以看出,Context就是一个对APK包无所不知的大管家,大家需要什么,直接问它就可以了。

 3) Context 与View 的关系
        View与Context(或Activity)的关系类似于明星与经纪人的关系,所以创建View时,必须明确指定其Context(即经纪人或大管家),否则View就成不了明星。

另外有一个简单的问题是,一个应用程序App中存在多少个Context实例对象呢?

Context,中文直译为“上下文”,SDK中对其说明如下:

Interface to global information about an application environment. This is an abstract class whose implementationis provided by the Android system. It allows access to application-specific resources and classes, as well as up-callsfor application-level operations such as launching activities, broadcasting and receiving intents, etc

从上可知一下三点,即:

1、它描述的是一个应用程序环境的信息,即上下文

2、该类是一个抽象(abstract class)类,Android提供了该抽象类的具体实现类(后面我们会讲到是ContextIml类)。

3、通过它我们可以获取应用程序的资源和类,也包括一些应用级别操作,例如:启动一个Activity,发送广播,接受Intent信息等。

应用程序创建Context实例的情况有如下几种情况:

1、创建Application 对象时, 而且整个App共一个Application对象

2、创建Service对象时

3、创建Activity对象时

因此应用程序App共有的Context数目公式为:总Context实例个数 = Service个数 + Activity个数 + 1(Application对应的Context实例)

2、 Context 类结构

可以看到Activity、Service、Application都是Context的子类;

也就是说,Android系统的角度来理解:Context是一个场景,代表与操作系统的交互的一种过程。从程序的角度上来理解:Context是个抽象类,而Activity、Service、Application等都是该类的一个实现。

在仔细看一下上图:Activity、Service、Application都是继承自ContextWrapper,而ContextWrapper内部会包含一个base context,由这个base context去实现了绝大多数的方法。

二、具体创建Context的时机

 1、创建Application对象的时机

每个应用程序在第一次启动时,都会首先创建Application对象。如果对应用程序启动一个Activity(startActivity)流程比较清楚的话,创建Application的时机在创建handleBindApplication()方法中。

2、创建Activity对象的时机

通过startActivity() 或startActivityForResult() 请求启动一个Activity时,如果系统检测需要新建一个Activity对象时,就会回调handleLaunchActivity()方法,该方法继而调用performLaunchActivity()方法,去创建一个Activity实例,并且回调onCreate(),onStart()方法等。

3、创建Service对象的时机

     通过startService或者bindService时,如果系统检测到需要新创建一个Service实例,就会回调handleCreateService()方法,完成相关数据操作。

三、Context 的具体使用     

Android中context可以作很多操作,但是最主要的功能是加载和访问资源。在android中常用两种context,一种是application context,一种是activity context,通常我们在各种类和方法间传递的是activity context。

继承关系:

区别联系:

[java] view plaincopy
  1. public class MyActivity extends Activity {
  2. public void method() {
  3. mContext = this; // since Activity extends Context
  4. mContext = getApplicationContext();
  5. mContext = getBaseContext();
  6. }
  7. }

this 是Activity 的实例,扩展了Context,其生命周期是Activity 创建到销毁。getApplicationContext()返回应用的上下文,生命周期是整个应用,应用摧毁它才摧毁。Activity.this的context 返回当前activity的上下文,属于activity ,activity摧毁他就摧毁getBaseContext() 返回由构造函数指定或setBaseContext()设置的上下文,SDK文档很少,不推荐使用搞清楚了生命周期就会在使用过程中犯错误,比如有一个全局的数据操作类用到了context,这个时候就要getApplicationContext 而不是用ACtivity,这就保证了数据库的操作与activity无关(不会一直引用Activity的资源,防止内存泄漏)。

应用场景:

比如一个activity的onCreate:

[java] view plaincopy
  1. protected void onCreate(Bundle state) {
  2. super.onCreate(state);
  3. TextView label = new TextView(this);
  4. label.setText("Leaks are bad");
  5. setContentView(label);
  6. }

把activity context传递给view,意味着view拥有一个指向activity的引用,进而引用activity占有的资源:view hierachy, resource等。这样如果context发生内存泄露的话,就会泄露很多内存。这里泄露的意思是gc没有办法回收activity的内存。

Leaking an entire activity是很容易的一件事。当屏幕旋转的时候,系统会销毁当前的activity,保存状态信息,再创建一个新的activity。

比如我们写了一个应用程序,它需要加载一个很大的图片,我们不希望每次旋转屏幕的时候都销毁这个图片重新加载。

实现这个要求的简单想法就是定义一个静态的Drawable,这样Activity类创建销毁它始终保存在内存中。实现示例:

[java] view plaincopy
  1. public class myactivity extends Activity {
  2. private static Drawable sBackground;
  3. protected void onCreate(Bundle state) {
  4. super.onCreate(state);
  5. TextView label = new TextView(this);
  6. label.setText("Leaks are bad");
  7. if (sBackground == null) {
  8. sBackground = getDrawable(R.drawable.large_bitmap);
  9. }
  10. label.setBackgroundDrawable(sBackground);//drawable attached to a view
  11. setContentView(label);
  12. }

这段程序看起来很简单,但是却问题很大。当屏幕旋转的时候会有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.getApplicationContext()方法获取。

定制一个自己的Application:首先创建一个MyApplication类继承自Application

[java] view plaincopy
  1. public class MyApplication extends Application{
  2. private static Context context;
  3. public void onCreate(){
  4. context=getApplicationContext();
  5. }
  6. public static Context getContext(){
  7. return context;
  8. }
  9. }
  10. <p> </p>

注意:当程序启动的时候应该初始化MyApplication类,而不是默认的Application类。在AndroidMainifest.xml文件的标签下进行指定就可以了。

android:name="com.example.hl.MyApplication"

这样就已经实现了一种全局获取Context的机制,之后想在项目中使用Application的Context时,只需调用一下MyApplication.getContext()就可以了。

避免context相关的内存泄露,记住以下几点:
1. 不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身生命周期是一样的
2. 对于生命周期长的对象,可以使用application context
3. 避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变化

Android 基础—— 对Context的理解与使用技巧相关推荐

  1. Android基础--tools:context=.TestActivity作用

    最近学习JetPack,看到这么一句话,其实以前也有,那么记录一下到底什么意思: Android开发中在布局文件里面都会有如下面的内容: <LinearLayoutxmlns:android=& ...

  2. Android中Context 的理解

    这里记录Context的原因是新来的同事问我Android Context 怎样理解,我是这样说的,Context 英文是上下文,它是一个抽象的类,加入在MainActivity 中,Context ...

  3. Android源码分析-全面理解Context

    前言 Context在android中的作用不言而喻,当我们访问当前应用的资源,启动一个新的activity的时候都需要提供Context,而这个Context到底是什么呢,这个问题好像很好回答又好像 ...

  4. Android基础新手教程——3.4 TouchListener PK OnTouchEvent + 多点触碰

    Android基础新手教程--3.4 TouchListener PK OnTouchEvent + 多点触碰 标签(空格分隔): Android基础新手教程 本节引言: 如题,本节给大家带来的是To ...

  5. Android基础新手教程——4.1.3 Activity登堂入室

    Android基础新手教程--4.1.3 Activity登堂入室 标签(空格分隔): Android基础新手教程 本节引言: 好的,在学习了两节的Activity后相信大家已经知道怎样去使用Acti ...

  6. Android基础四大组件详解

    Android四大组件详解 博主接触Android开发将近一年,从最初的JavaSE开始,到Android基础,一直学的糊糊涂涂,最近想整理一番 android基础, 顺便把自己的学习开发经验分享给大 ...

  7. Android 面试系列(一)Android 基础

    文章目录 序言 四大组件 Activity Activity 生命周期 onStart() 与 onResume() 区别? Activity 启动模式 launchMode 使用 Intent 标记 ...

  8. Android基础与手机历史

    智能的机操作系统经过多盘厮杀,到现在形成了三足鼎立之势:Android.iOS.Windows phone 8三者一统天下.而其他的诸如Symbian S60, UIQ, Windows Mobile ...

  9. Android基础知识【项目实训-实现二级导航“今日活动”及读取数据库】【5】

    [该项目实训是Android基础知识的一个综合练习,特别提示:项目中会用到一些图片素材,都是随意整理的,稍后会上传一个资源,包含该事项项目的基本功能,也含有图片素材] [项目题目]:校园订餐App设计 ...

最新文章

  1. 被“钱”困住的开源开发者们!
  2. kettle性能及效率提升_开发人员掌握了这个技术,SQL效率会有几百倍的性能提升...
  3. Linux服务器init 5启动图形界面,报错Retrigger failed udev events的解决方法
  4. 判断android应用程序是否已安装
  5. Swift中文教程(二十一) 协议
  6. Redis集群之官方集群
  7. ‘分享到’侧边栏制作
  8. day12【过渡】SpringCloud
  9. 2017.5.26暴力赛解题报告
  10. #STM32学习#6D加速度传感器测量风机震动
  11. 【机器学习】特征工程的最佳实践
  12. ssm酒店预订系统(ssm酒店管理系统民宿预订)ssm酒店客房预订系统宾馆JSP客房预订系统
  13. 大数据促进中小企业快递航运战略三种方法
  14. wps 2003 给WPS设置保护眼睛的淡绿色呢?
  15. python下载安装教程电脑版,python下载好了怎么使用
  16. UML一篇文章就学通!
  17. .NET MVC 后台接受base64的上传图片
  18. sql面试题(学生表_课程表_成绩表_教师表)
  19. SCI/ISTP和EI论文检索号IDS number和收录号查询方法
  20. Oracle 下载Windows、Linux

热门文章

  1. c++11:智能指针
  2. WPR-007:WPF中窗体的透明设置
  3. Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?...
  4. Dynamips结合VMware搭建站点到站点×××环境
  5. 研究者展示黑客通过GPU绕过防毒软件查杀的方法
  6. 数据科学还是计算机科学_您应该拥有数据科学博客的3个原因
  7. 深入理解InnoDB(1)—行的存储结构
  8. leetcode51. N 皇后(回溯算法)
  9. leetcode1221. 分割平衡字符串(贪心算法)
  10. leetcode1091. 二进制矩阵中的最短路径(bfs)