Android 理解Context

文章目录

  • Android 理解Context
    • Context是什么
      • Activity能直接new吗?
    • Context结构和源码
    • 一个程序有几个Context
    • Context的作用
    • Context作用域
    • 获取Context
    • getApplication()和getApplicationContext()区别
    • Context引起的内存泄露
      • 错误的单例模式
      • View持有Activity应用
      • 正确使用Context

Android 理解Context

Context是什么

Context可以理解为“上下文”或”环境“,它提供了访问系统服务及系统资源的功能,Context 参与加载资源、启动Activity、启动Service、获取系统服务/应用资源、创建View、数据库等操作。

通俗来讲:一个Android应用程序可以理解为一个部电影,Activity、Service、BroadcastReceiver、ContentProvider四大组件可以理解为电影中的四个主演。他们是由剧组(Android系统)一开始就制定好的,整部戏都是围绕这四位主演的,所以这四位主演不能随便在街上拉个人(new一个对象)就能演的,有了演员就需要摄像机拍摄,他们通过镜头(Context)将戏传递给观众,也就是说四大组件必须要在Context环境下运行,而其他的如Button、TextView、LinearLayout这些控件可以理解为配角,没有那么重要(可以new一个对象),

Activity能直接new吗?

不能,Android的应用模型是基于组件的应用设计模式,组件的运行必须要一个完整的Android工程环境,只有在这个环境下,Activity、Service等系统组件才能正常运行。

Context结构和源码

在这里插入图片描述

Context源码:

public abstract class Context {// 作用1:获取应用相关信息public abstract ApplicationInfo getApplicationInfo();public abstract String getPackageName();public abstract Looper getMainLooper();public abstract int checkPermission(@NonNull String permission, int pid, int uid);// 作用2:获取系统/应用资源// 如 AssetManager、PackageManager、Resources、System Service 以及 color、string、drawable 等public abstract AssetManager getAssets();public abstract Resources getResources();public abstract PackageManager getPackageManager();public abstract Context getApplicationContext();public abstract ClassLoader getClassLoader();public final @Nullable <T> T getSystemService(@NonNull Class<T> serviceClass) { ... }public final String getString(@StringRes int resId) { ... }public final int getColor(@ColorRes int id) { ... }public final Drawable getDrawable(@DrawableRes int id) { ... }public abstract Resources.Theme getTheme();public abstract void setTheme(@StyleRes int resid);public final TypedArray obtainStyledAttributes(@StyleableRes int[] attrs) { ... }// 作用3:四大组件之间的交互// 如启动 Activity、Broadcast、Service,获取 ContentResolver 等public abstract void startActivity(@RequiresPermission Intent intent);public abstract void sendBroadcast(@RequiresPermission Intent intent);public abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver,IntentFilter filter);public abstract void unregisterReceiver(BroadcastReceiver receiver);public abstract ComponentName startService(Intent service);public abstract boolean stopService(Intent service);public abstract boolean bindService(@RequiresPermission Intent service,@NonNull ServiceConnection conn, @BindServiceFlags int flags);public abstract void unbindService(@NonNull ServiceConnection conn);public abstract ContentResolver getContentResolver();// 作用4:文件相关// 如:获取缓存文件夹、删除文件、SharedPreference 相关等public abstract File getSharedPreferencesPath(String name);public abstract File getDataDir();public abstract boolean deleteFile(String name);public abstract File getExternalFilesDir(@Nullable String type);public abstract File getCacheDir();...public abstract SharedPreferences getSharedPreferences(String name, @PreferencesMode int mode);public abstract boolean deleteSharedPreferences(String name);// 作用5:数据库// 如打开数据库、删除数据库、获取数据库路径等public abstract SQLiteDatabase openOrCreateDatabase(...);public abstract boolean deleteDatabase(String name);public abstract File getDatabasePath(String name);...
}

Context是一个抽象类,提供了关于应用环境全局信息的信息,Android提供该抽象类的具体实现类,可以通过它获取应用程序的资源和启动Activity、发送广播等。

Context有两个实现子类:ContextImpl类和ContextWrapper类。

ContextWrapper类,如其名所言,是一个包装类,内部必须包含一个真正的Context引用,调用ContextWrapper的方法都会被指向真正的Context对。

ContextThemeWrapper类,如起名所言,内部包含了与Theme(主题)相关的信息,这里的Theme就是定义在Androidmanifest.xml中主题,只有Activity才能定义主题,Servier是不需要主题的,所以Service直接继承自ContextWrapper,Application也同理。

ContextImpl类是真正实现了Context中的所有方法,应用程序中所调用的各种Context类方法都来自该类。

总的来讲:Context是一个抽象类,有两个子类,ContextImpl是具体实现类,ContextWrapper是包装类,Activity、Service、Application虽然都继承自ContextWrapper,但是在初始化是都会创建ContextImpl对象,有ContextImpl实现Context中的方法。

一个程序有几个Context

Context数量 = Activity数量 + Service数量 + 1

为什么没有BroadcastReceiver和ContentProvider,这是因为它们都不是Context的子类,所持有的Context对象是从其他地方传过来的。

Context的作用

弹出Toast、启动Activity、启动Service、发送广播、操作数据库等。

Context作用域

Context作用域ApplicationActivityService
Show a DialogNoYesNo
Start an Activity不推荐Yes不推荐
Layout Inflation不推荐Yes不推荐
Start a ServiceYesYesYes
Send a BroadcastYesYesYes
Register Broadcast ReceiverYesYesYes
Load Resource ValuesYesYesYes

启动Activity、弹出Dialog,必须使用Activity类型的Context。这是因为Android系统出于安全考虑,不允许Activity或Dialog凭空出现,一个Activity的启动必须建立在另一个Activity的基础上,也就是Activity任务栈。

启动Activity也可以使用Application的Context,但是需要将启动模式改为singleTask。

加载布局推荐使用Activity的Context,Application和Service当然也是合法的,但是会使用系统默认的主题样式。

总而言之,Activity的Context作用域最广,这是因为Activity继承自ContextThemeWrapper,ContextThemeWrapper在ContextWrapper的基础上做了一些扩展,而Appliaction和Service继承自ContextWrapper。凡是和UI相关的都应该使用Activity的Context。

获取Context

获取Context对象的四种方法:

View#getContext():通过View获取Context对象,也就是Activity对象。

Activity#getApplicationContext():获取Application的Context。

ContextWrapper#getBaseContext():获取ContextWrapper进行装饰前的Context。

Activity#this:获取Activity对象。

getApplication()和getApplicationContext()区别

其实都是同一个对象,但是作用域不同。

getApplication()表示获取一个Application,而Application本身就是一个Context,可以在Activity、Service中使用

getApplicationContext()表示获取一个Application的Context,可以在BroadcastReceiver中使用

比如可以通过BroadcastReiver中的Context获取Application对象。

public class MyReceiver extends BroadcastReceiver{@OverridepublicvoidonReceive(Contextcontext,Intentintent){Application myApp = (Application)context.getApplicationContext();}
}

Context引起的内存泄露

错误的单例模式

public class Singleton {private static Singleton instance;private Context mContext;private Singleton(Context context) {this.mContext = context;}public static Singleton getInstance(Context context) {if (instance == null) {instance = new Singleton(context);}return instance;}
}

这个单例模式,instance作为静态变量,生命周期长于普通对象,如果使用Activity的Context,会导致Activity一直被持有,即使Activity被销毁了,这样会导致内存泄露。

View持有Activity应用

public class MainActivity extends Activity {private static Drawable mDrawable;@Overrideprotected void onCreate(Bundle saveInstanceState) {super.onCreate(saveInstanceState);setContentView(R.layout.activity_main);ImageView iv = new ImageView(this);mDrawable = getResources().getDrawable(R.drawable.ic_launcher);iv.setImageDrawable(mDrawable);}
}

mDrawable对象是一个静态变量会常驻内存,持有Activity的Context,即使Activity被销毁了也不会被回收,因此造成内存泄露。

正确使用Context

  • 生命周期长的对象,优先使用Application的Context。
  • UI相关的场景,推荐使用Activity的Context。
  • 尽量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用;如果需要使用静态内部类,应该将外部实例使用作为弱引用持有。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/310257.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

据报道,微软的下一代 Surface 笔记本电脑将是其首款真正的“人工智能 PC”

明年&#xff0c;微软计划推出 Surface Laptop 6和 Surface Pro 10&#xff0c;这两款设备将提供 Arm 和 Intel 两种处理器选项。不愿意透露姓名的不透露姓名人士透露&#xff0c;这些新设备将引入先进的人工智能功能&#xff0c;包括配备下一代神经处理单元 (NPU)。据悉&#…

助力打造智慧数字课堂,基于YOLOv8全系列【n/s/m/l/x】不同参数量级模型开发构建教学课堂场景下学生课堂行为检测识别分析系统

近年来&#xff0c;随着行为检测技术的发展&#xff0c;分析学生在课堂视频中的行为&#xff0c;以获取他们的课堂状态和学习表现信息已经成为可能。这项技术对学校的教师、管理人员、学生和家长都非常重要。使用深度学习方法自动检测学生的课堂行为是分析学生课堂表现和提高教…

智能分析网关V4+太阳能供电模式,搭建鱼塘养殖远程视频监控方案

一、行业背景 传统的鱼塘养殖模式由于养殖区域面积大、管理难度高&#xff0c;经常会出现偷钓者、盗窃鱼苗、非法入侵等监管难题&#xff0c;给养殖户带来了不小的经济损失。为了解决这些问题&#xff0c;搭建鱼塘远程监控系统成为了必要之举。通过远程监控系统&#xff0c;管…

C#语言发展历程(1-7)

一、类型发展 C#1中是没有泛型的 在C#2中在逐渐推出泛型。C#2还引入了可空类型。 示例&#xff1a;C#泛型&#xff08;详解&#xff09;-CSDN博客 1 C#3&#xff1a;引入了匿名类型、和隐式的局部变量&#xff08;var&#xff09; 匿名类型&#xff1a;我们主要是使用在LIN…

PHP序列化总结3--反序列化的简单利用及案例分析

反序列化中生成对象里面的值&#xff0c;是由反序列化里面的值决定&#xff0c;与原类中预定义的值的值无关&#xff0c;穷反序列化的对象可以使用类中的变量和方法 案例分析 反序列化中的值可以覆盖原类中的值 我们创建一个对象&#xff0c;对象创建的时候触发了construct方…

中间人攻击是什么,会产生哪些危害,如何有效防止中间人攻击

简介 中间人攻击&#xff08;Man-in-the-Middle Attack&#xff0c;简称MITM攻击&#xff09;是一种网络攻击&#xff0c;其原理是攻击者通过各种技术手段将受攻击者控制的一台计算机虚拟放置在网络连接中的两台通信计算机之间&#xff0c;这台计算机称为“中间人”。在攻击过…

Spark编程实验四:Spark Streaming编程

目录 一、目的与要求 二、实验内容 三、实验步骤 1、利用Spark Streaming对三种类型的基本数据源的数据进行处理 2、利用Spark Streaming对Kafka高级数据源的数据进行处理 3、完成DStream的两种有状态转换操作 4、把DStream的数据输出保存到文本文件或MySQL数据库中 四…

NModbus-一个C#的Modbus协议库实现

NModbus-一个基于C#实现的Modbus通信协议库 最近在学习C#的时候&#xff0c;因为之前做过环保设备时使用C做过环保设备采集使用到了Modbus协议&#xff0c;当时看了一下基于C语言开发的libmodbus库。所以特意搜索看了一下C#下有什么Modbus协议库&#xff0c;在Github上面找了一…

[蓝桥杯2020国赛]答疑

答疑 题目描述 有 n 位同学同时找老师答疑。每位同学都预先估计了自己答疑的时间。 老师可以安排答疑的顺序&#xff0c;同学们要依次进入老师办公室答疑。 一位同学答疑的过程如下&#xff1a; 首先进入办公室&#xff0c;编号为 i 的同学需要 si​ 毫秒的时间。然后同学问…

After Effects 2021 for Mac(AE 2021)

After Effects 2021是一款由Adobe公司开发的视频特效和动态图形制作软件&#xff0c;它主要用于电影、电视和网络视频的后期制作。该软件可以帮助用户创建各种令人惊叹的视觉效果&#xff0c;包括动态图形、文字特效、粒子系统、3D渲染等。 After Effects 2021提供了数百种特效…

dash 中的模式匹配回调函数Pattern-Matching Callbacks 8

模式匹配 模式匹配回调选择器 MATCH、ALL 和 ALLSMALLER 允许您编写可以响应或更新任意或动态数量组件的回调函数。 此示例呈现任意数量的 dcc. Dropdown 元素&#xff0c;并且只要任何 dcc. Dropdown 元素发生更改&#xff0c;就会触发回调。尝试添加几个下拉菜单并选择它们的…

TCP/IP的五层网络模型

目录 封装&#xff08;打包快递&#xff09; 6.1应用层 6.2传输层 6.3网络层 6.4数据链路层 6.5物理层 分用&#xff08;拆快递&#xff09; 6.5物理层 6.4数据链路层 6.3网络层 6.2传输层 6.1应用层 封装&#xff08;打包快递&#xff09; 6.1应用层 此时做的数据…