这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战 | 创作学习持续成长,夺宝闯关赢大奖
前情提要,本篇文章源码分析较多,介意的朋友请绕行。
前言
作为一个Android开发,Android的各个流程应该尽可能的熟悉 ,View更是很重要的一个,这样才能在平时的工作中事半功倍,这篇文章也是我对Android的一个探索,分享给大家 。
开始
我们从ActivityThread接管启动开始
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
// TODO(lifecycler): Recycle locally scheduled transactions.
break;
TransactionExecutor.java
public void execute(ClientTransaction transaction) {
...
executeCallbacks(transaction);
executeLifecycleState(transaction);
mPendingActions.clear();
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}
@VisibleForTesting
public void executeCallbacks(ClientTransaction transaction) {
...
final IBinder token = transaction.getActivityToken();
ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
...
final int size = callbacks.size();
for (int i = 0; i < size; ++i) {
final ClientTransactionItem item = callbacks.get(i);
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item);
final int postExecutionState = item.getPostExecutionState();
final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
item.getPostExecutionState());
if (closestPreExecutionState != UNDEFINED) {
//重点方法
cycleToPath(r, closestPreExecutionState, transaction);
}
...
}
}
Android会为每个Activity生成一个Record描述类 ,内部放了关于Activity的所有信息 。
private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
ClientTransaction transaction) {
...
performLifecycleSequence(r, path, transaction);
}
这个path里其实放了Activity当前的一个状态 。
相信看到这里,就熟悉了 。
private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
ClientTransaction transaction) {
final int size = path.size();
//遍历当前的状态 依次执行
for (int i = 0, state; i < size; i++) {
state = path.get(i);
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Transitioning activity: "
+ getShortActivityName(r.token, mTransactionHandler)
+ " to state: " + getStateName(state));
}
switch (state) {
//我们先分析这个
case ON_CREATE:
mTransactionHandler.handleLaunchActivity(r, mPendingActions,
null /* customIntent */);
break;
case ON_START:
mTransactionHandler.handleStartActivity(r.token, mPendingActions);
break;
case ON_RESUME:
mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
break;
case ON_PAUSE:
mTransactionHandler.handlePauseActivity(r.token, false /* finished */,
false /* userLeaving */, 0 /* configChanges */, mPendingActions,
"LIFECYCLER_PAUSE_ACTIVITY");
break;
case ON_STOP:
mTransactionHandler.handleStopActivity(r.token, 0 /* configChanges */,
mPendingActions, false /* finalStateRequest */,
"LIFECYCLER_STOP_ACTIVITY");
break;
case ON_DESTROY:
mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
0 /* configChanges */, false /* getNonConfigInstance */,
"performLifecycleSequence. cycling to:" + path.get(size - 1));
break;
case ON_RESTART:
mTransactionHandler.performRestartActivity(r.token, false /* start */);
break;
default:
throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
}
}
}
这里是Activity的生命周期的回调 ,这里有一个问题: 为什么要用Handler发送这个回调?
因为
ApplicationThread是一个Binder,它的调用逻辑运行在Binder线程池中,所以这里需要用Handler将代码的逻辑切换到主线程中。
这里是不是Binder线程池的创建时机忘记了 ?
在zygortInit (java)中fork的形式创建 SystemServer, 并且开启Binder线程池 。
ActivityThread.java
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
//WindowManagerGlobal 进行初始化 ,当调用addView的时候 其实用的是他的方法
WindowManagerGlobal.initialize();
//获取要启动的Activity
final Activity a = performLaunchActivity(r, customIntent);
...
return a;
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
...
//为这个Activity创建上下文环境
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
//新建Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
...
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
// Activity resources must be initialized with the same loaders as the
// application context.
appContext.getResources().addLoaders(
app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
appContext.setOuterContext(activity);
//这里进行PhoneWindow的创建
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
r.assistToken);
...
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
//这里onCreate方法回调
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
}
//设置状态 这里猜想与Lifecycle有关 ,紧接着需要跟一下了
r.setState(ON_CREATE);
...
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
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, IBinder assistToken) {
//将上下文 ContextImpl交给 ContextWrapper
attachBaseContext(context);
...
//创建PhoneWindow
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(mWindowControllerCallback);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
... //一顿赋值操作
//这里设置了WindowManager 它是ViewManager的子类
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
mWindow.setColorMode(info.colorMode);
mWindow.setPreferMinimalPostProcessing(
(info.flags & ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING) != 0);
...
}
attach 走完之后会走 callActivityOnCreate方法 进行onCreate的回调
Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
Activity.java
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
dispatchActivityPreCreated(icicle);
mCanEnterPictureInPicture = true;
// initialize mIsInMultiWindowMode and mIsInPictureInPictureMode before onCreate
final int windowingMode = getResources().getConfiguration().windowConfiguration
.getWindowingMode();
mIsInMultiWindowMode = inMultiWindowMode(windowingMode);
mIsInPictureInPictureMode = windowingMode == WINDOWING_MODE_PINNED;
restoreHasCurrentPermissionRequest(icicle);
//在这里进行回调
if (persistentState != null) {
onCreate(icicle, persistentState);
} else {
onCreate(icicle);
}
EventLogTags.writeWmOnCreateCalled(mIdent, getComponentName().getClassName(),
"performCreate");
mActivityTransitionState.readState(icicle);
mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
com.android.internal.R.styleable.Window_windowNoDisplay, false);
mFragments.dispatchActivityCreated();
mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
dispatchActivityPostCreated(icicle);
}
MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//到达了这里 设置布局文件
setContentView(R.layout.activity_main)
}
主线
PhoneWindow.java
public void setContentView(int layoutResID) {
if (mContentParent == null) {
//这里创建DecorView 每一个布局对应一个DecorView
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets();
...
}
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
//创建DecorView
mDecor = generateDecor(-1);
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} else {
//将DecorView与PhoneWindow绑定
mDecor.setWindow(this);
}
if (mContentParent == null) {
//解析布局
mContentParent = generateLayout(mDecor);
...
}
}
我们再来看一看generateLayout
protected ViewGroup generateLayout(DecorView decor) {
// Apply data from current theme.
TypedArray a = getWindowStyle();
WindowManager.LayoutParams params = getAttributes();
...
int layoutResource;
int features = getLocalFeatures();
// System.out.println("Features: 0x" + Integer.toHexString(features));
if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
R.attr.dialogTitleIconsDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = R.layout.screen_title_icons;
}
// XXX Remove this once action bar supports these features.
removeFeature(FEATURE_ACTION_BAR);
// System.out.println("Title Icons!");
} else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
&& (features & (1 << FEATURE_ACTION_BAR)) == 0) {
// Special case for a window with only a progress bar (and title).
// XXX Need to have a no-title version of embedded windows.
layoutResource = R.layout.screen_progress;
// System.out.println("Progress!");
} else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
// Special case for a window with a custom title.
// If the window is floating, we need a dialog layout
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
R.attr.dialogCustomTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = R.layout.screen_custom_title;
}
// XXX Remove this once action bar supports these features.
removeFeature(FEATURE_ACTION_BAR);
} else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
// If no other features and not embedded, only need a title.
// If the window is floating, we need a dialog layout
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
R.attr.dialogTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
layoutResource = a.getResourceId(
R.styleable.Window_windowActionBarFullscreenDecorLayout,
R.layout.screen_action_bar);
} else {
layoutResource = R.layout.screen_title;
}
// System.out.println("Title!");
} else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
layoutResource = R.layout.screen_simple_overlay_action_mode;
} else {
// Embedded, so no decoration is needed.
layoutResource = R.layout.screen_simple;
// System.out.println("Simple!");
}
mDecor.startChanging();
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
//这里是我们自己的布局文件
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
...
return contentParent;
}
然后就是start
public void handleStartActivity(IBinder token, PendingTransactionActions pendingActions) {
...
//设置Activity状态为可见
updateVisibility(r, true /* show */);
mSomeActivitiesChanged = true;
}
后面就是 resume
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
...
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
//设置状态不可见
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
//ViewRootImpl 是addView的时候进行创建的
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
//这里将decorView 交给WindowManager处理 真正的开始绘制
wm.addView(decor, l);
} else {
// The activity will get a callback for this {@link LayoutParams} change
// earlier. However, at that time the decor will not be set (this is set
// in this method), so no action will be taken. This call ensures the
// callback occurs with the decor set.
a.onWindowAttributesChanged(l);
}
}
// If the window has already been added, but during resume
// we started another activity, then don't yet make the
// window visible.
} else if (!willBeVisible) {
if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
...
}
WindowManagerImpl.java
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
mContext.getUserId());
}
WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow, int userId) {
...
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
...
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
...
//创建了ViewRootImpl (每一次addView创建一次)
root = new ViewRootImpl(view.getContext(), display);
//设置参数
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// do this last because it fires off messages to start doing things
try {
//交给ViewRootImpl
root.setView(view, wparams, panelParentView, userId);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
看到这里我们了解到一个东西 ,一个Activity对应个一个PhoneWindow,对应一个DecorView,
而同时每次addView都会有一个ViewRootImpl生成
ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
int userId) {
requestLayout();
...
}
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
@UnsupportedAppUsage
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
//开启同步屏障 优先处理帧消息
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
//编舞者出场
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
我们看一个编舞者发送给的这个runnable是什么
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
//删除垂直同步
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
//分发消息
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
private void performTraversals() {
...
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
...
if (didLayout) {
performLayout(lp, mWidth, mHeight);
}
...
performDraw();
}
看到测量->布局->绘制这里应该就明白了Android的界面的一个绘制流程是什么样的了。
这里我们简单看一下编舞者 是如何巡回不断地读取的 。
这里有一篇比较好的文章Choreographer 解析
Choreographer
Choreographer 请求Vsync
Choreographer.java
public void postCallback(int callbackType, Runnable action, Object token) {
postCallbackDelayed(callbackType, action, token, 0);
}
private void postCallbackDelayedInternal(int callbackType,
Object action, Object token, long delayMillis) {
synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
//将消息加入到queues中
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
//如果是不延时的
if (dueTime <= now) {
//开始帧率计算
scheduleFrameLocked(now);
} else {
//延时用Handler发出
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
}
}
}
private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
//使用垂直同步 默认是使用的
if (USE_VSYNC) {
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame on vsync.");
}
// If running on the Looper thread, then schedule the vsync immediately,
// otherwise post a message to schedule the vsync from the UI thread
// as soon as possible.
//如果是在主线程则直接执行 ,否则由Handler发送到主线程执行
if (isRunningOnLooperThreadLocked()) {
scheduleVsyncLocked();
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMessageAtFrontOfQueue(msg);
}
} else {
//如果不使用则由handler处理分发
final long nextFrameTime = Math.max(
mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
}
Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextFrameTime);
}
}
}
涉及到了同步屏障的知识,那什么是同步屏障呢 ? 同步屏障的原理是什么呢 ?
这里卖个关子 ,下篇文章分析Handler的时候我们具体分析 。
到此为止新的类出来了
private void scheduleVsyncLocked() {
mDisplayEventReceiver.scheduleVsync();
}
DisplayEventReceiver.java
public void scheduleVsync() {
if (mReceiverPtr == 0) {
Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
+ "receiver has already been disposed.");
} else {
//请求 Vsync
nativeScheduleVsync(mReceiverPtr);
}
}
Choreographer 收到Vsync (垂直同步信号)
// Called from native code.
@SuppressWarnings("unused")
@UnsupportedAppUsage
private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame) {
onVsync(timestampNanos, physicalDisplayId, frame);
}
实现在其子类中
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {
private boolean mHavePendingVsync;
private long mTimestampNanos;
private int mFrame;
public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
super(looper, vsyncSource, CONFIG_CHANGED_EVENT_SUPPRESS);
}
@Override
public void onVsync(long timestampNanos, long physicalDisplayId, int frame) {
mTimestampNanos = timestampNanos;
mFrame = frame;
Message msg = Message.obtain(mHandler, this);
//设置消息为异步消息 这里一般是用到了同步屏障 ,保证 该消息的优先执行
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
@Override
public void run() {
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame);
}
}
Handler发送自身 ,接着就是run方法执行 。
void doFrame(long frameTimeNanos, int frame) {
final long startNanos;
synchronized (mLock) {
if (!mFrameScheduled) {
return; // no work to do
}
long intendedFrameTimeNanos = frameTimeNanos;
startNanos = System.nanoTime();
final long jitterNanos = startNanos - frameTimeNanos;
if (jitterNanos >= mFrameIntervalNanos) {
final long skippedFrames = jitterNanos / mFrameIntervalNanos;
if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
Log.i(TAG, "Skipped " + skippedFrames + " frames! "
+ "The application may be doing too much work on its main thread.");
}
final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
//对消息时间进行纠正
frameTimeNanos = startNanos - lastFrameOffset;
}
//这个条件为 当前的帧时间是否小于最后一次的帧率时间
if (frameTimeNanos < mLastFrameTimeNanos) {
if (DEBUG_JANK) {
Log.d(TAG, "Frame time appears to be going backwards. May be due to a "
+ "previously skipped frame. Waiting for next vsync.");
}
scheduleVsyncLocked();
return;
}
if (mFPSDivisor > 1) {
long timeSinceVsync = frameTimeNanos - mLastFrameTimeNanos;
if (timeSinceVsync < (mFrameIntervalNanos * mFPSDivisor) && timeSinceVsync > 0) {
scheduleVsyncLocked();
return;
}
}
mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
mFrameScheduled = false;
mLastFrameTimeNanos = frameTimeNanos;
}
try {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");
AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
mFrameInfo.markInputHandlingStart();
//这里进行回调
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
mFrameInfo.markAnimationsStart();
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameTimeNanos);
mFrameInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
} finally {
AnimationUtils.unlockAnimationClock();
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
void doCallbacks(int callbackType, long frameTimeNanos) {
CallbackRecord callbacks;
synchronized (mLock) {
// We use "now" to determine when callbacks become due because it's possible
// for earlier processing phases in a frame to post callbacks that should run
// in a following phase, such as an input event that causes an animation to start.
final long now = System.nanoTime();
//取出所有的CallbackRecord
callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(
now / TimeUtils.NANOS_PER_MS);
}
try {
for (CallbackRecord c = callbacks; c != null; c = c.next) {
if (DEBUG_FRAMES) {
Log.d(TAG, "RunCallback: type=" + callbackType
+ ", action=" + c.action + ", token=" + c.token
+ ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime));
}
//遍历执行 run 方法
c.run(frameTimeNanos);
}
} finally {
synchronized (mLock) {
mCallbacksRunning = false;
do {
final CallbackRecord next = callbacks.next;
recycleCallbackLocked(callbacks);
callbacks = next;
} while (callbacks != null);
}
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
CallbackRecord.java
@UnsupportedAppUsage
public void run(long frameTimeNanos) {
if (token == FRAME_CALLBACK_TOKEN) {
//回调给注册的类 ,会回调doFrame
((FrameCallback)action).doFrame(frameTimeNanos);
} else {
((Runnable)action).run();
}
}
这里可以看到正是因为Choreographer的存在,一遍一遍的刷新我们的界面,才能实现我们的很多复杂的动画 ,交互效果。
总结来说 Choreographer 一次请求 一次接收 ,不请求就不接受 。
Android 每个页面编舞者也就是在刚开始执行一次 因为onDraw会重复绘制 ,除非有动画 会一直执行
总结
本文从Activity与界面的绑定到界面的绘制流程依次进行了分析,但也只是在基础层次的 ,Android在FrameWork层同样的做了很多的努力,日后我们慢慢的进行分析 。
文章中如果有问题的地方,欢迎大家多多评论指正,另外还是希望得到大家的点赞支持