源码视角下深入剖析Android应用启动与事件处理机制

概述

在Android开发领域,深入理解应用启动与事件处理机制是进阶的关键。接下来,我们将结合相关流程图,从源码层面详细解读这一复杂过程。

一、AMS驱动应用启动的源码剖析

当点击应用图标启动应用时,AMS的attachApp方法被调用,这一过程在Binder线程中执行。在ActivityManagerService.java源码中,attachApp会与ActivityThread进行交互。例如,ActivityThread中的attach方法会被远程调用,它会将应用进程与AMS进行关联,完成进程的初始化工作。

// ActivityManagerService部分代码示例
public final void attachApp(int pid) {
    // 查找对应的应用进程记录
    ProcessRecord app = getProcessRecordLocked(pid, null, false);
    if (app != null) {
        try {
            // 通过Binder调用ActivityThread的attach方法
            app.thread.attach(false, mCoreSettingsObserver.getCoreSettingsLocked());
        } catch (RemoteException ex) {
            // 处理异常情况
        }
    }
}

AMS在启动Launcher应用进程时,会检查Activity栈中已有的Activity。这涉及到ActivityStackSupervisor类,它负责管理Activity栈。startSpecificActivityLocked方法会判断栈中是否有可复用的Activity,若有则直接启动,避免重复创建,提高启动效率。

// ActivityStackSupervisor部分代码示例
private void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
    ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true);
    if (app != null && app.thread != null) {
        try {
            realStartActivityLocked(r, app, andResume, checkConfig);
        } catch (RemoteException e) {
            // 处理异常
        }
    } else {
        // 启动新的应用进程
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
}

二、Activity创建与初始化的源码流程

Activity创建时,首先创建PhoneWindow。在Activity.javaattach方法中,会实例化PhoneWindow,并建立Activity与PhoneWindow的关联。

// Activity.java部分代码示例
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, ActivityConfigCallback activityConfigCallback) {
    attachBaseContext(context);
    mFragments.attachHost(null /*parent*/);
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    // 其他初始化操作
}

接着,Activity.onCreate方法被调用,开发者在该方法中进行初始化操作。ActivityThread中的handleLaunchActivity方法会触发ActivityonCreate

// ActivityThread部分代码示例
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 创建Activity实例
    Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
        // 调用Activity的onCreate方法
        r.createdConfig = new Configuration(mConfiguration);
        Bundle oldState = r.state;
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished &&!r.startsNotResumed, r.lastProcessedSeq, false);
    }
}

Activity.setContentView会调用PhoneWindow.setContentView。在PhoneWindow中,setContentView会将布局资源解析为视图层级结构。

// PhoneWindow.java部分代码示例
@Override
public void setContentView(int layoutResID) {
    if (mContentParent == null) {
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }
    // 将布局资源填充到mContentParent中
    LayoutInflater.from(mContext).inflate(layoutResID, mContentParent);
    // 其他操作
}

三、视图与窗口交互及布局请求的源码分析

ViewRootImpl.setView将视图树与窗口关联。在ViewRootImpl的构造函数中,会初始化一些关键变量,setView方法会将视图添加到窗口中,并开始准备布局。

// ViewRootImpl.java部分代码示例
public ViewRootImpl(Context context, Display display) {
    mContext = context;
    mWindowSession = WindowManagerGlobal.getWindowSession();
    // 其他初始化操作
}

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    synchronized (this) {
        if (mView == null) {
            mView = view;
            // 向窗口会话添加窗口
            try {
                mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                        getHostVisibility(), mDisplay.getDisplayId(),
                        mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                        mAttachInfo.mOutsets, mInputChannel);
            } catch (RemoteException e) {
                // 处理异常
            }
            // 启动布局流程
            requestLayout();
        }
    }
}

ViewRootImpl.requestLayout发起布局请求,它会检查是否处于布局中,若未处于布局中,则会通过scheduleTraversals方法安排一次遍历。

// ViewRootImpl.java部分代码示例
@Override
public void requestLayout() {
    if (!mHandlingLayoutInLayoutRequest) {
        checkThread();
        mLayoutRequested = true;
        scheduleTraversals();
    }
}

系统发出VSync信号后,FrameDisplayEventReceiver.onVsync被调用,它会触发Choreographer.doFrameChoreographer类负责协调动画、输入和绘制等操作。

// Choreographer.java部分代码示例
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
        implements Runnable {
    @Override
    public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
        // 将时间戳转换为合适的格式
        long now = System.nanoTime();
        if (timestampNanos > now) {
            timestampNanos = now;
        }
        if (mHavePendingVsync) {
            Log.w(TAG, "Already have a pending vsync event.  There should only be "
                    + "one at a time.");
        }
        mHavePendingVsync = true;
        mTimestampNanos = timestampNanos;
        mFrame = frame;
        // 将自身添加到主线程消息队列中
        Message msg = Message.obtain(mHandler, this);
        msg.setAsynchronous(true);
        mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
    }
}

Choreographer.doFrame中,会调用ViewRootImpl.enqueueInputEvent将输入事件加入队列。

// Choreographer.java部分代码示例
void doFrame(long frameTimeNanos, int frame) {
    // 计算时间差
    final long startNanos;
    if (DEBUG_FRAMES) {
        startNanos = System.nanoTime();
    }
    try {
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");
        // 处理输入事件
        if (mInputEventReceiver != null) {
            mInputEventReceiver.consumeEvents();
        }
        // 调用ViewRootImpl的相关方法处理事件
        for (int i = 0; i < mCallbackQueues.length; i++) {
            final CallbackRecord callbacks = mCallbackQueues[i].extractDueCallbacksLocked(frameTimeNanos);
            if (callbacks != null) {
                executeCallbacks(callbacks);
            }
        }
        // 处理动画和绘制
        doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
        doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
    }
}

四、事件处理责任链模式的源码实现

ViewRootImpl.doTraversal中,会按照责任链模式处理事件。InputStage是责任链中的节点,NativePreImeInputStageEarlyPostImeInputStageNativePostImeInputStage等都继承自InputStage

// ViewRootImpl.java部分代码示例
private void doTraversal() {
    if (mTraversalScheduled) {
        mTraversalScheduled = false;
        mBatchingInput = false;
        // 处理输入事件
        if (mPendingInputEvent != null) {
            handleInputEvent(mPendingInputEvent);
            mPendingInputEvent = null;
        }
        // 开始遍历
        performTraversals();
    }
}

// InputStage.java部分代码示例
public abstract class InputStage {
    protected final InputStage mNext;
    public InputStage(InputStage next) {
        mNext = next;
    }
    public void onProcess(QueuedInputEvent q) {
        if (mNext != null) {
            mNext.onProcess(q);
        }
    }
}

当事件到达NativePreImeInputStage时,它会处理与输入法相关的预处理工作。若该阶段未处理完事件,则会传递给下一个阶段EarlyPostImeInputStage,依此类推,直到事件被处理。

// NativePreImeInputStage.java部分代码示例
public class NativePreImeInputStage extends InputStage {
    public NativePreImeInputStage(InputStage next) {
        super(next);
    }
    @Override
    public void onProcess(QueuedInputEvent q) {
        // 处理输入法相关的预处理
        if (!q.mEvent.isConsumed()) {
            forward(q);
        } else {
            finish(q);
        }
    }
}

五、总结与实践意义

通过对源码的深入解读,我们清晰地了解了Android应用启动与事件处理的全过程。从AMS的调度,到Activity的创建与初始化,再到视图与窗口的交互以及事件处理的责任链模式,每一个环节都紧密协作。
对于开发者来说,掌握这些原理有助于在开发过程中优化应用性能,例如在Activity启动时合理复用资源,避免不必要的创建操作;在事件处理时,能够更精准地定位问题,提高应用的稳定性和响应速度。同时,这也为我们深入研究Android系统源码、定制化开发以及解决复杂的兼容性问题提供了坚实的理论基础。希望本文能帮助大家在Android开发道路上更上一层楼,不断探索和创新。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容