Android开发艺术探索(九)

四大组件的运行状态

Android的四大组件中除了BroadcastReceiver以外,其他三种必须在AndroidMainfest清单文件中注册。对于BroadcastReceiver既可以在AndroidMainfest注册,也可以通过代码来注册。

从调用方式上来说:Activity、Service和BroadcastReceiver需要借助Intent,而ContentProvider则无需借助Intent。
Activity

Activity是一种展示型组件,用于向用户直接的展示一个界面,并且可以接受用户的输入信息从而进行交互。

Service

Service是一种计算型组件,用于在后台执行一系列计算任务。Service本身是运行在UI线程中的,所以做一些耗时计算时,需要开启子线程。Service有两种状态:
1、启动状态
2、绑定状态

BroadcastReceiver

BroadcastReceiver是一种消息型组件,用于在不同的组件乃至不同的应用之间传递消息。
广播注册有两种方式,
动态注册通过Context.registerReceiver()来实现,必须要应用启动才能注册;
静态注册则在AndroidManifest文件中进行,应用安装时会被系统解析,不需要启动应用就可接收广播。

ContentProvider

ContentProvider是一种数据共享型组件,用于向其他组件乃至其他应用共享数据。

本章所讲四大组件的工作过程稍微有些难,需要看源码理解。

Activity的工作过程

比如我们启动一个新的Activity:

 startActivity(new Intent(this,ActivityA.class));

startActivity有好多种重载方式,但是它们最终会调用startActivityForResult方法;

 public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                mStartedActivity = true;
            }
            cancelInputsAndStartExitTransition(options);
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

上面这段代码中,mParent代表ActivityGrou。mMainThread.getApplicationThread()这个参数返回的是一个ApplicationThread对象。ApplicationThread又是ActivityThread的内部类。

ApplicationThread继承自ApplicationThreadNative,ApplicationThreadNative继承了Binder又实现了IApplicationThread接口。所以说ApplicationThread本质是一个Binder对象。

 public ApplicationThread getApplicationThread()
    {
        return mAppThread;
    }
/**继承自ApplicationThreadNative*/
private class ApplicationThread extends ApplicationThreadNative{}

/**继承自Binder同时实现IApplicationThread */
public abstract class ApplicationThreadNative extends Binder
        implements IApplicationThread {}

//所以说ApplicationThread 本质上是一个Binder对象。

这里我们来看一个很重要的类ActivityThread,在Activity启动过程中发挥很重要的作用:

public final class ActivityThread {
public static final String TAG = "ActivityThread";
final ApplicationThread mAppThread = new ApplicationThread();
/**ActivityThread的内部类*/
private class ApplicationThread extends ApplicationThreadNative {
/**这里将代码进行了精简*/
 @Override
        public final void scheduleLaunchActivity(.....) {
        /**发送消息启动ACT*/
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }
}
/***/
private class H extends Handler {
    public static final int LAUNCH_ACTIVITY         = 100;
 public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                            /**处理消息,调用handleLaunchActivity方法*/
                    handleLaunchActivity(r, null);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
  }
}
/**获取ApplicationThread 对象*/
public ApplicationThread getApplicationThread(){
    return mAppThread;
}
  private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
       //这里代码也进行了精简
        /**在这里调用了performLaunchActivity方法完成Act的创建和启动*/
        Activity a = performLaunchActivity(r, customIntent);
        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            /**在这里调用ACT的onResume方法*/
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);
            if (!r.activity.mFinished && r.startsNotResumed) {
                try {
                    r.activity.mCalled = false;
                    mInstrumentation.callActivityOnPause(r.activity);
                    if (r.isPreHoneycomb()) {
                        r.state = oldState;
                    }
                    if (!r.activity.mCalled) {
                        throw new SuperNotCalledException();
                    }
                } catch (SuperNotCalledException e) {
                    throw e;
                } catch (Exception e) {
                    if (!mInstrumentation.onException(r.activity, e)) {
                        throw new RuntimeException(
                                "Unable to pause activity "
                                + r.intent.getComponent().toShortString()
                                + ": " + e.toString(), e);
                    }
                }
                r.paused = true;
            }
        } else {
            try {
                ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
            } catch (RemoteException ex) {
            }
        }
    }
}

performLaunchActivity这个方法主要完成了以下几件事情:具体参考源码
1、从ActiivtyClientRecore中获取待启动Activity的组件信息
2、通过Instrumentation的newActiivty方法使用类加载器创建Activity对象
3、通过LoadedApk的makeApplication方法来尝试创建Application对象。
4、创建ContextImpl对象并通过Activity的attach方法来完成一些重要数据的初始化
5、调用Activity的工作过程

我们接着来看mInstrumentation.execStartActivity方法中,启动Activity的真正实现由ApplicationThreadNative.getDefalut()的startActivity方法来完成。ApplicationThreadNative.getDefalut()方法中返回的是IActivityManager接口对象。因此具体实现为AMS。

ActivityManagerService(AMS)继承自ActivityManagerNative,ActivityManagerNative又继承自Binder并且实现了IActivityManager接口,所以AMS本质上也是一个Binder。

/**ActivityManagerNative 抽象类*/
public abstract class ActivityManagerNative extends Binder implements IActivityManager{
 static public IActivityManager getDefault() {
        return gDefault.get();
    }
}

/**ActivityManagerService类 */
public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback{
        /**精简代码*/
     /**在这类调用startActivityAsUser方法*/
     @Override
    public final int startActivity(IApplicationThread caller, ..., Bundle options) {
        return startActivityAsUser(caller, ...,UserHandle.getCallingUserId());
    }
    /**这里启动调用了ActivityStackSupervisor的startActivityMayWait方法*/
     @Override
    public final int startActivityAsUser(IApplicationThread caller,..., int userId) {
        return mStackSupervisor.startActivityMayWait(caller,..., null);
    }
}

这里来看一张整理的图吧:
Activity启动流程

Service的工作过程

通过Context的startService方法启动一个Service,如下:

  Intent it=new Intent(this,MyService.class);
        startService(it);

通过Context的bindService方法即可以绑定的方式启动一个Service,如下:

Intent it=new Intent(this,MyService.class);
        bindService(it,mServiceConnection,BIND_AUTO_CREATE);

Service的启动过程
Service的启动时从ContextWrapper的startActivity开始的。mBase类型是ContextImpl,Activity被创建时会通过attach方法将一个ContextImpl对象关联起来。

/**mBase类型是ContextImpl,*/
    @Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }

在ContextImpl中,startService方法会调用startServiceCommon方法,而startServiceCommon方法又会通过ActivityManagerNative.getDefault()这个对象来启动一个服务。

Service的绑定过程
和Service的启动过程一样,Service的绑定也是从ContextWrapper开始的。ContextImpl的bindService方法最终会调用自己的bindServiceCommen方法。

剩下的过程呢,跟Activity是类似的,就不在具体解释了。可以看源码喽!

BroadcasrReceiver的工作过程

BroadcasrReceiver的工作过程,主要包含两方面的内容,一个是广播的注册过程,另一个是广播的发送和接收过程。

广播的注册过程
广播的注册分为静态注册和动态注册,其中静态注册的广播在应用安装时由系统自动完成注册,具体来说是由PMS(PackageManagerService)来完成整个注册过程的,除了广播意外,其他三大组件也都是在应用安装时由PMS解析并注册的。

广播的动态注册
广播的动态注册是从ContextWrapper的registerReceive方法开始的,和Activity以及Service一样。ContextWrapper并没有做实际的工作,而是将注册过程交给了ContextImpl。

   @Override
    public Intent registerReceiver(
        BroadcastReceiver receiver, IntentFilter filter) {
        return mBase.registerReceiver(receiver, filter);
    }

ContextImpl的registerReceiver方法调用了自己的registerReceiverInternal方法。

在registerReceiverInternal方法中,系统首先从mPackageInfo获取到了IIntentReceive对象,然后再采用跨进程的凡事向AMS发送广播注册的请求。

之所以采用 IIntentReceive而不是直接采用BroadcasrReceiver,是因为注册过程是一个进程间通讯的过程,而BroadcasrReceive作为Android的一个组件是不能直接跨进程传递的,所以需要通过IIntentReceive来中转。

方法最后返回了ActivityManagerNative.getDefault().registerReceiver()方法,显然注册过程又交给了AMS。在registerReceiver()方法中会把远程的InnerReceiver对象以及IntentFilter对象存储起来,这样就完成广播注册的过程。

广播的发送和接收过程
广播的发送和接收,其本质是一个过程的两个阶段,这里从广播的发送说起:

广播的发送开始于ContextWrapper的sendBroadcast方法,之所以不是Context,是因为Context中的sendBroadcast是一个抽象方法。

和广播的注册过程一样, ContextWrapper的sendBroadcast方法仍然什么都不做,只把事情交给ContextImpl去处理。

1、 ContextImpl也是几乎什么事情都没干,直接向AMS发起了一个异步请求用于发送广播。在AMS的broadcaseIntent方法中去发送广播。
2、 broadcaseIntent中调用了broadcaseIntentLocked方法,broadcaseIntentLocked方法内部,会根据intent-fitter查找出匹配的广播接收者并经过一系列的条件过滤。最终会将满足条件的广播接受者添加到BroadQueue中,接着BroadQueue就会将广播发送给相应的广播接受者。

3、BroadQueue的scheduleBroadcasrLocked方法并没有立即发送广播,而是发送完了一个BROADCAST_INTENT_MSG类型的消息,收到消息后会调用processNextBroadcast方法。

4、 processNextBroadcast方法中通过deliverToRegisteredReceiverLocked方法来实现的,它将一个广播发送个一个特定的接收者,内部调用了performReceiveLocked方法来完成具体的发送过程。

5、performReceiveLocked内部又调用了Application的scheduleRegisteredReceiver,通过InnerReceiver实现广播的接收。
.
6、InnerReceiver的performReceive方法会调用LoadedAok.ReceiverDispatcher的PerformReceive方法。
.
7、PerformReceive中会通过ActivityThread的post方法来执行Args中的逻辑。而Args是ActivityThread的一个Handler,在mH的handlerMessage方法中,看到onReceive方法执行了,也就是说已经接收到了广播。

ContentProvider的工作过程

ContentProvider是一种内容共享型组件,它通过Binder向其他组件乃至其他应用提供应用数据。当CotnentProvider所在的进程启动时,ContentProvider会同时启动并被发布到AMS中,这个时候onCreate要先于Application的onCreate而执行。

启动过程

1、 当一个应用启动时,入口方法为ActivityThread的main方法,main方法是一个静态方法。在main方法中会创建ActivityThread的实例并创建主线程的消息队列,然后再ActivityThread的attach方法中会远程调用AMS的attachApplication方法并将ApplicationThread对象提供给AMS。

ApplicationThread是一个Binder对象,它的Binder接口是IApplicationThread,主要用于ApplicationThread和AMS之间的通信。

2、在AMS的attachApplication方法中,会调用ApplicationThread的bindApplication方法,这个过程是跨进程完成的,bindApplication的逻辑会经过ApplicationThread中的mH handler切换到ActivityThread中执行。具体的方法是handlerBindApplication。
3、在handlerBindApplication方法中,ActivityThread会创建Application对象并加载ContentProvider,需要注意的是ActivityThread会先加载ContentProvider,然后再调用Application的onCreate方法。

具体实现过程请参照源码!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值