《Android开发艺术探索》之学习笔记(九)四大组件的工作过程

这篇博客详细探讨了Android开发中的四大组件——Activity、Service、BroadcastReceiver和ContentProvider的工作过程。Activity作为用户界面组件,Service用于后台任务,BroadcastReceiver实现跨组件消息传递,而ContentProvider则用于数据共享。文章通过图表解析了各组件的启动、绑定和服务生命周期等关键步骤。
摘要由CSDN通过智能技术生成

四大组件概述

  • Activity,是一种展示型组件,用于向用户展示UI。它只有一种运行模式:处于启动状态。
  • Service,是一种计算型组件,用于在后台执行一系列计算任务。它有两种状态:启动状态和绑定状态。Service是运行在主线程的,因此耗时的任务需要在工作线程去完成。Service处于绑定状态时,它内部同样可以进行后台计算。
  • BroadCastReceiver,是一种消息行组件,用于在不同的组件甚至不同应用间传递消息。静态注册在应用安装时会被系统解析,不需要应用启动就能收到相应的广播;动态注册必须要应用启动后才能收到广播。
  • ContentProvider,是一种数据共享型组件,用于向其他组件甚至其他应用共享数据。它对数据集合的具体实现没有要求,可以是数据库,List、Map甚至文件等。它内部的insert、delete、update和query方法需要处理好线程同步,因为这几个方法是运行在Binder线程池中的。ContentProvider不需要手动停止。

Activity的工作过程

一张图说明Activity的启动流程:
这里写图片描述

performLaunchActivity这个方法主要完成如下几件事:
1、从ActivityClientRecord中获取待启动的Activity的组件信息

ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
   r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
           Context.CONTEXT_INCLUDE_CODE);
}

ComponentName component = r.intent.getComponent();
if (component == null) {
   component = r.intent.resolveActivity(
       mInitialApplication.getPackageManager());
   r.intent.setComponent(component);
}

if (r.activityInfo.targetActivity != null) {
   component = new ComponentName(r.activityInfo.packageName,
           r.activityInfo.targetActivity);
}

2、通过Instrumention的newActivity方法使用类加载器创建Activity对象

Activity activity = null;
try {
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    activity = mInstrumentation.newActivity(
            cl, component.getClassName(), r.intent);
    StrictMode.incrementExpectedActivityCount(activity.getClass());
    r.intent.setExtrasClassLoader(cl);
    r.intent.prepareToEnterProcess();
    if (r.state != null) {
        r.state.setClassLoader(cl);
    }
} catch (Exception e) {
    if (!mInstrumentation.onException(activity, e)) {
        throw new RuntimeException(
            "Unable to instantiate activity " + component
            + ": " + e.toString(), e);
    }
}

3、通过LoadedApk的makeApplication方法来尝试创建Application对象
LoadedApk.calss被标记为@hide类,源码在sdk/sources/android-22/android/app目录下

public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    if (mApplication != null) {
        return mApplication;
    }

    Application app = null;

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";
    }

    try {
        java.lang.ClassLoader cl = getClassLoader();
        if (!mPackageName.equals("android")) {
            initializeJavaContextClassLoader();
        }
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        if (!mActivityThread.mInstrumentation.onException(app, e)) {
            throw new RuntimeException(
                "Unable to instantiate application " + appClass
                + ": " + e.toString(), e);
        }
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    if (instrumentation != null) {
        try {
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            if (!instrumentation.onException(app, e)) {
                throw new RuntimeException(
                    "Unable to create application " + app.getClass().getName()
                    + ": " + e.toString(), e);
            }
        }
    }

    // Rewrite the R 'constants' for all library apks.
    SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
            .getAssignedPackageIdentifiers();
    final int N = packageIdentifiers.size();
    for (int i = 0; i < N; i++) {
        final int id = packageIdentifiers.keyAt(i);
        if (id == 0x01 || id == 0x7f) {
            continue;
        }

        rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
    }

    return app;
}

Application创建完毕后,系统会通过Instrumention的callApplicationOncreate来调用Application的onCreate方法

4、创建ContextImpl对象并通过Activity发attach方法来完成一些重要数据的初始化
5、调用Activity的onCreate方法

Service的工作过程

Service的启动过程

一张图说明Service的启动流程:
这里写图片描述

handleCreateService方法主要完成如下几件事:
1、通过类加载器创建Service的实例
2、创建Application对象并调用其onCreate方法
3、创建ContextImpl对象并通过Service发attach方法建立二者之间的关系
4、调用Service的onCreate方法并将Service对象存储到ActivityThread中的一个列表中。ActivityThread通过handleServiceArgs方法调用Service的onStarCommand方法

Service的绑定过程

一张图说明Service的绑定过程:
这里写图片描述

handleBindService方法主要完成如下几件事:
1、根据Service的token取出Service对象,调用Service的onBind方法
2、通过ActivityManagerService调用publishService方法通知客户端已经成功连接Service

BroadcastReceiver的工作过程

Activity、Service、ContentProvider和BroadcastReceiver的静态注册都是在应用安装时由PackageManagerService解析注册的。

BroadcastReceiver的注册过程

这里写图片描述

BroadcastReceiver的发送和接收过程

自Android3.1开始,系统为Intent新增了两个标志,并为所有广播默认添加 FLAG_EXCLUDE_STOPPED_PACKAGES 标志,防止无意间或者在不必要的时候唤醒已经停止的APP,这个特性同样会影响开机广播

  • FLAG_INCLUDE_STOPPED_PACKAGES
    表示包含已经停止的APP,这个时候广播会发送到已经停止的APP
  • FLAG_EXCLUDE_STOPPED_PACKAGES
    表示不包含已经停止的APP,这个时候广播不会发送给已经停止的APP

当两个标志共存时,以 FLAG_INCLUDE_STOPPED_PACKAGES 为准

这里写图片描述

ContentProvider的工作过程

当ContentProvider所在的进程启动时,ContentProvider会同时启动并被发布到ActivityManagerService中,这个时候ContentProvider的onCreate要先于Application的onCreate执行

这里写图片描述

ActivityThread的handleBindApplication方法最终完成Application和ContentProvider的创建,步骤如下:

  • 创建ContextImpl和Instrumention
  • 创建Application对象
  • 启动当前进程的ContentProvider并调用其onCreate方法
  • 调用Application的onCreate方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值