Android四大组件之Activity(七)——新创建的进程Android Context

本文探讨了Android中Context的使用场景,包括启动Activity、Service、发送广播等,并解析了Context类图,强调ContextImpl和ContextWrapper在其中的作用。文章指出,Application、Activity和Service通过attach()方法与ContextImpl建立联系,而真正执行Context功能的是ContextImpl。同时,解释了为何不直接使用ContextImpl以及四大组件与Application的关系。

1、使用的是Android 7.1.2的源代码:

https://pan.baidu.com/s/1XcVD68cC_2wKtm8jJkdNQA
przv

2、感谢IT先森的系列博客:

Android应用进程创建流程大揭秘
Android四大组件之bindService源码实现详解
Android四大组件之Activity启动流程源码实现详解概要
Activity启动流程(一)发起端进程请求启动目标Activity
Activity启动流程(二)system_server进程处理启动Activity请求
Activity启动流程(三)-Activity Task调度算法复盘分析
Activity启动流程(四)-Pause前台显示Activity,Resume目标Activity
Activity启动流程(五)请求并创建目标Activity进程
Activity启动流程(六)注册目标Activity进程到system_server进程以及创建目标Activity进程Application
Activity启动流程(七)初始化目标Activity并执行相关生命周期流程

1、Context的使用场景

  • 启动Activity(startActivityXXX(…)方法族)
  • 启动/停止Service(startServiceXXX(…)/stopServiceXXX(…)方法族)
  • 绑定/解绑Service(bindServiceXXX(…)/unbindService(…)方法族)
  • 发送广播(sendBroadcastXXX(…)/sendOrderedBroadcastXXX(…)方法族)
  • 注册/注销广播(registerReceiverXXX(…)/unregisterReceiver(…)方法族)
  • 获取ContentResolver(getContentResolver(…))
  • 获取类加载器 (getClassLoader(…))
  • 数据库(SQLite)相关,包括打开数据库、删除数据库、获取数据库路径等(openOrCreateDatabase(…)方法族)
  • 获取各种资源相关方法(getResources()/getString(…)/getColor(…)系列方法族)
  • 文件,包括获取缓存文件夹、删除文件、SharedPreference 相关等功能(getSharedPreferences(…)等系列方法族)

四大组件以及各种资源的操作都离不开Context。

但是Context类是一个抽象类。

2、Context类图

在这里插入图片描述

  • Context有两个直接继承子类:ContextImpl和ContextWrapper,ContextWrapper又通过mBase指向了ContextImpl,即ContextWrapper的核心工作都是交给ContextImpl来完成的,两者是代理模式。
  • Application/Activity/Service通过attach()调用父类ContextWrapper的attachBaseContext(),从而设置父类成员变量mBase为ContextImpl对象,所以说真正执行Context使命的是ContextImpl。
public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback {
        
       		final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window) {
          		 attachBaseContext(context);
          		 ··· ···
            }
		}
public class ContextThemeWrapper extends ContextWrapper {
    ··· ···
   @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(newBase);
    }
  }
public class ContextWrapper extends Context {
	Context mBase;
    public ContextWrapper(Context base) {
        mBase = base;
    }
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }
    ··· ···
}

注意:

一般情况下,使用代理,而不直接使用某个对象,目的可能有两个:1、定制自己的行为;2、不影响原对象。

1、对于Service和Application而言,不直接继承ContextImpl,是担心用户修改了ContextImpl而导致错误的发生。
2、对于Activity而言,除了担心用户的修改之外,ContextImpl和Activity本身对于Resource和Theme的相关行为是不同的。

  • Android同一应用中的四大组件都属于同一个Application,其中
    1)Activity/Service,通过调用其方法getApplication(),可主动获取当前所在的mApplication,而且是由LoadedApk.makeApplication()过程所初始化的
    2)Receiver,是通过其方法onReceive()的第一个参数指向通当前所在Application,也就是只有接收到广播的时候才能拿到当前的Application对象
    3)provider,目前没有提供直接获取当前所在Application的方法, 但可通过getContext()可以获取当前的ContextImpl。
### Android 四大组件详解 #### 1. **Activity** ActivityAndroid 应用中最基础的组件之一,它代表了一个可视化的界面,用户可以通过这个界面与应用程序进行交互。每个 Activity 都会在屏幕上显示一个窗口,并负责处理所有的窗口事件[^4]。 从外部视角看,Activity 占据整个屏幕区域,可以包含各种 UI 控件(如按钮、文本框等)。从内部实现角度来看,Activity 的主要职责包括管理界面的状态、保存数据以便恢复、管理和协调生命周期阶段以及与其他 Activity 进行导航和通信。 以下是 Activity 生命周期的关键部分: - `onCreate()`:当 Activity创建时调用。 - `onStart()` 和 `onResume()`:分别表示 Activity 可见并与用户互动。 - `onPause()`、`onStop()` 和 `onDestroy()`:用于释放资源或清理操作。 ```java public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 设置布局文件 } } ``` #### 2. **Service** Service 组件是一个运行在后台的任务执行器,它可以用来完成那些不需要与用户直接交互的工作。例如播放音乐、下载文件或者定期同步数据等任务都可以由 Service 来完成[^4]。 Service 不依赖于任何特定的 UI 或者前台展示,因此即使用户的设备锁屏或者切换到其他应用,Service 仍然能够继续工作。有两种类型的 Service: - 前台 Service (Foreground Service): 提供更高的优先级,通常伴随通知栏图标一起使用。 - 后台 Service (Background Service): 执行低优先级的操作,在某些版本的 Android 中可能受到系统限制。 下面是一段简单的 Service 实现代码: ```java public class MyService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("MyService", "Service started"); return START_STICKY; } @Nullable @Override public IBinder onBind(Intent intent) { return null; // 如果不绑定,则返回null } } ``` #### 3. **Broadcast Receiver** Broadcast Receiver 是一种轻量级的消息处理器,允许开发者监听来自操作系统或其他应用发出的各种广播消息。这些消息可能是关于电池电量变化的通知、网络连接状态改变或者是自定义的应用间通讯信号等等[^1]。 通过继承 `BroadcastReceiver` 类并覆写其核心方法 `onReceive()`,就可以捕获指定类型的广播事件。此外,广播接收器还可以分为两种注册方式——静态注册(在 `AndroidManifest.xml` 文件中声明)和动态注册(通过 Java/Kotlin 编程接口手动设置)[^2]。 这里给出一个典型的例子来演示如何构建自己的广播接收器: ```java // 定义广播接收器类 public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if ("android.intent.action.BOOT_COMPLETED".equals(action)) { Toast.makeText(context, "Boot Completed!", Toast.LENGTH_LONG).show(); } } } // 动态注册该接收器 IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED); registerReceiver(new MyReceiver(), filter); ``` #### 4. **Content Provider** Content Provider 主要被设计成跨进程共享数据的一种机制,使得不同 App 之间能方便地存取彼此的数据源。比如联系人列表就是典型的一个场景,多个第三方软件都希望访问手机内置地址簿里的记录信息[^1]。 每一个 Content URI 对应着某个具体表结构下的字段集合,遵循统一的标准格式 scheme://authority/path/[id]?parameters=value... 。其中 authority 参数决定了哪个 content provider 将会被激活去解析请求路径 path 下面的内容 id 则进一步定位到了某条具体的记录项之上。 以下是如何查询 Contacts 数据库的例子: ```java Uri uri = ContactsContract.Contacts.CONTENT_URI; String[] projection = {ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME}; Cursor cursor = getContentResolver().query(uri, projection, null, null, null); if(cursor != null && cursor.moveToFirst()) { do{ long contactId = cursor.getLong(0); String name = cursor.getString(1); } while(cursor.moveToNext()); } finally { if(cursor!=null){ cursor.close(); } } ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值