Content是什么?Android中的Content、Activity、Application 有什么区别?

本文详细解释了Android系统中Context和Application的概念与作用。Context作为系统操作和常量的抽象类,通过ContextImpl实现了对系统组件的具体操作。Application则是在Activity启动过程中创建,并通过Context完成一系列操作。

Context是什么?

根据个人理解Context这个“上下文”是Android 系统的一个应用信息的描述类,也是对一些基础操作的抽象类。包含了比如StartActivity、StartService、registerReceiver等操作的抽象,同时提供了一些系统的配置信息,常量信息。Context本身不做任何操作,通过阅读源码我们知道,Context它有两个直接子类一个ContextImpl、一个ContextWrapper。ContextWrapper对Context进行了一层包装,内部通过一个mBase来调用Context实现的方法。真正实现了Context的就是ContextImpl,在它内部做了对系统启动,Activity启动,服务启动关系等的操作。

ContextWrapper内部的mBase对象实际上就是ComtextImpl对象的实例。在ActivityThread类中Activity启动流程中调用handleLaunchActivity()方法的时候会创建一个ContextImpl对象,同时通过classLoader类加载的方式创建完成Activity,调用Activity的attach()方法传递了刚刚创建的ContextImpl对象,在attach方法中会调用一个attachBaseContext(context),而Activity继承了ContextThemeWrapper,ContextThemeWrapper继承了ContextWrapper,最终通过super.attachBaseContext()把ContextImpl传递到了ContextWrapper中。

对于Service也是同样的过程,在startService的时候最后在ActivtyThread类中,调用handleCreateService(),在这个方法创建了ContextImpl,通过classLoader创建了Service对象,最后调用了Service的attach()方法把ContextImpl传递给Service然后调用attachBaseContext最后传递给了ContextWrapper类。

Application是什么?

前面讲了在ActivityThreadhandleLaunchActivity会创建Activity,同时这里也会创建Application的对象。在这里调用了ActivityClientRecord对象的LoadedApk对象的makeApplication方法来创建一个Application。最后又调用了Instrumentation的makeApplication方法通过classLoader的方式创建,创建成功后调用Application的attach(context)方法传递了前面刚刚创建的ContextImpl对象给Application,所以通过Applicaiton我们能完成Context的一些操作。同样在attach中会调用ContextWrapper的attachBaseContext方法赋值。

前面说创建完成Activity后会调用其attach方法,这里也会把Application传递给Activity。我们在Activity中经常调用一个getApplication方法获取Application,这个getApplication是Activity的方法,就是返回了刚刚通过LoadedApk的makeApplication创建传递来的Application对象。

在开发中我们还会用到一个getApplicationContext(),这个方法也是Context的方法。我们在Activity中调用的时候访问了ContextWrapper的方法,最后交给mBase来实现。

 

看下mBase也就是ContextImpl的getApplicaitonContext方法实现:

ContextImpl中判断了两个来源:

查看mPackageInfo.getApplication()方法,直接返回了mApplication。而这个mApplication的赋值来自于LoadedApk类的对象mPackageInfo的makeApplication方法。

查看mMainThread.getApplication();

查看mInitialApplication的赋值,来到了handleBindApplication()方法中,依然调用了makeApplication创建Application,并赋值。

而在makeApplication方法中看到,首先判断了mApplication是否为空,不为空直接返回。

也就是说mApplication这是一个单例对象。

最终我们知道了getApplication和getApplicationContext其实返回的都是makeApplication创建的对象。只是创建的时机不同,如果已经创建了就不同重复,返回同一个对象

LoginActivityMainActivity中分别调用getApplicationgetApplicationContext测试返回的对象是不是同一个:

输出结果:

由输出结果可以看出不同的两个Activity页面getApplicationgetApplicationContext返回的对象是同一个。

最后总结

Context是一个抽象类,定义了系统的一些操作和常量,Context有两个直接子类ContextWrapper和ContextImpl,其中ContextImpl是真正的实现类,实现了对系统组件的操作。ContextWrapper拥有ContextImpl的一个引用。

ContextWrapper有三个直接子类ContextThemeWrapper、Application和Service。其中ContextThemeWrapper来处理一些有关Theme的逻辑,ContextThemeWrapper有一个子类Activity。

Android 中,**Application Context(`Application.getApplicationContext()`)可以正常访问 `ContentProvider`**,因为 `ContentProvider` 的设计本身就是跨进程/组件的数据共享机制,不依赖任务栈(Task)或 UI 上下文。以下是详细说明: --- ### **1. 直接使用 Application Context 访问 ContentProvider** ```java // 示例:通过 Application Context 查询 ContentProvider Cursor cursor = getApplicationContext().getContentResolver().query( Uri.parse("content://com.example.provider/data"), null, // 查询列 null, // WHERE 条件 null, // WHERE 参数 null // 排序 ); ``` - **合法性**: `ContentResolver` 的操作(如 `query`、`insert`、`update`、`delete`)仅依赖权限和 URI 有效性,与 Context 类型无关。 --- ### **2. 与 Activity 启动的区别** | **操作** | **依赖任务栈** | **Application Context 是否支持** | **限制条件** | |-------------------|---------------|----------------------------------|----------------------------------| | 启动 Activity | 是 | 需 `FLAG_ACTIVITY_NEW_TASK` | 后台限制(Android 10+) | | 访问 ContentProvider | 否 | **直接支持** | 需声明权限或 URI 权限 | --- ### **3. 注意事项** - **权限要求**: - 如果 `ContentProvider` 声明了权限(如 `android:readPermission`),调用方需在 `AndroidManifest.xml` 中声明对应权限。 - 跨进程访问时需确保 Provider 已正确导出(`android:exported`)。 - **线程安全**: `ContentProvider` 的 CRUD 方法默认运行在调用者线程,**主线程直接访问可能导致 ANR**。建议异步操作: ```kotlin lifecycleScope.launch(Dispatchers.IO) { val cursor = contentResolver.query(...) // 处理数据 } ``` --- ### **4. 特殊场景:通过 ContentProvider 间接启动 Activity** 如果需要在 `ContentProvider` 中启动 Activity(如跳转授权页面),仍需遵循 Activity 的 Context 规则: ```java // 在 ContentProvider 中启动 Activity需添加 FLAG_ACTIVITY_NEW_TASK Intent intent = new Intent(getContext(), AuthActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); getContext().startActivity(intent); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值