Android开发艺术探索(九)

来源:互联网 发布:杂交水稻种植面积 知乎 编辑:程序博客网 时间:2024/05/17 23:19

四大组件的运行状态

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