您的位置:首页 > 移动开发 > Android开发

Android 4.2 SetContentView 流程分析(二)

2013-01-02 16:40 316 查看
(2)

[ActivityThread.java]
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,  boolean reallyResume) {
//1. 藉由所传入的token跟clearHide信息执行Resume state的流程之后取
//得ActivityClientRecord物件.
ActivityClientRecord r = performResumeActivity(token, clearHide);
if (r != null) {
//2. 由所得到的ActivityClientRecord取得activity对象
final Activity a = r.activity;
//...
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
//3. 取得前面所建立的DecoreView
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
//4. 取得前面所建立的 WindowManagerImpl
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
//5. 设定WindowManager.LayoutParams的属性.
l.type =  WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
//6. 利用WindowManagerImpl依照
//WindowManager.LayoutParams的属性来为DecoreView增加一个
//view的纪录.
wm.addView(decor, l);
}
} else if (!willBeVisible) {
//当Activity是处于Invisible state时,就将ActivityClientRecord物件的
//hideForNow属性设定为true.代表目前的window是不可见的.
r.hideForNow = true;
}

} else {
// 只要在resume state中一发生exception就马上终止activity的lifecycle.
}
}
这一段程序代码带出了一个关键程序代码,wm.addView , 就由addView 这个function开始分析

[WindowManagerImpl.java]
@Override
public void addView(View view, ViewGroup.LayoutParams params) {
// private final WindowManagerGlobal mGlobal =
//WindowManagerGlobal.getInstance(); 是一个singleton的物件.
mGlobal.addView(view, params, mDisplay, mParentWindow);
}

[WindowManagerGlobal.java]
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
//1. 检查传入的参数是否有值,没有的话就发生exception. 保护之后
//的流程出错.是属于一种保护式程序设计.
if (view == null) {
throw new IllegalArgumentException("view must not be null");
}
if (display == null) {
throw new IllegalArgumentException("display must not be null");
}
if (!(params instanceof WindowManager.LayoutParams)) {
throw new IllegalArgumentException("Params must be
WindowManager.LayoutParams");
}
final WindowManager.LayoutParams wparams =
(WindowManager.LayoutParams)params;
if (parentWindow != null) {
parentWindow.adjustLayoutParamsForSubWindow(wparams);
}

ViewRootImpl root;
View panelParentView = null;
//2. 开始进入lock阶段以保护以下流程一次只能有一个thread执行或
//是确保执行流程一定要完成才能再次的执行.
synchronized (mLock) {
//3. 启动监控者只要用来监控系统属性变化
//4. 建立一个新的ViewRootImpl对象
root = new ViewRootImpl(view.getContext(), display);    (2-1)
//5. 设定View的layout参数,这里的View是DecoreView, layout
//参数是handleResumeActivity函数中第五个步骤的
//WindowManager.LayoutParams 属性设定.
view.setLayoutParams(wparams);

//...
}

try {
//6. 利用ViewRootImpl对象来设定目前的画面.
root.setView(view, wparams, panelParentView);      (2-2)
} catch (RuntimeException e) {
//一发生exception,马上清理目前相关View资源
}

}


(2-1)

[ViewRootImpl.java]
public ViewRootImpl(Context context, Display display) {
//...
//详见以下分析(2-1-1)
// final IWindowSession mWindowSession;
mWindowSession =
WindowManagerGlobal.getWindowSession(context.getMainLooper());
//...
//详见以下分析(2-1-2)
//final W mWindow;
mWindow = new W(this);

}
(2-1-1)

[WindowManagerGlobal.java]
public static IWindowSession getWindowSession(Looper mainLooper) {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
//1. 由Main looper取得 InputMethodManager对象.
InputMethodManager imm =
InputMethodManager.getInstance(mainLooper);
//2. 取得WindowManagerService的Proxy.
IWindowManager windowManager =
getWindowManagerService();
//3. 利用WindowManagerService Proxy去开启Session.
//此session的建立目的是将WindowManagerService和
//InputMethodManager的inputContext(DecoreView)
//作IPC (Binder),之后得到session的handler.
sWindowSession = windowManager.openSession(
imm.getClient(), imm.getInputContext());
float animatorScale =
windowManager.getAnimationScale(2);
ValueAnimator.setDurationScale(animatorScale);
} catch (RemoteException e) {
Log.e(TAG, "Failed to open window session", e);
}
}
return sWindowSession;
}
}
(2-1-2)

[ViewRootImpl.java]
static class W extends IWindow.Stub {
private final WeakReference<ViewRootImpl> mViewAncestor;
private final IWindowSession mWindowSession;

W(ViewRootImpl viewAncestor) {
//这里只有将ViewRootImpl参考对象转成一个软对象参考
//mViewAncestor, 除了方便作GC处理,其他就没甚么用处了, 在
//JAVA中的对象参考有分四个类别.都是跟GC有关的.祥建请参
//考Java书籍.
mViewAncestor = new
WeakReference<ViewRootImpl>(viewAncestor);
mWindowSession = viewAncestor.mWindowSession;
}

//...
}


由(2-1-1)跟(2-1-2)的分析, 可以知道ViewRootImpl利用Binder机制将WindowManagerService 和 DecoreView建立一个session. 接下来继续分析(2-2) root.setView的流程

(2-2)

[ViewRootImpl.java]
public void setView(View view,
WindowManager.LayoutParams attrs,
View panelParentView) {
//第一个 view的参数是一个 DecoreView
//...
//保存
mView = view;
//...
//在View加入Windows Manager service前先排程第一个Layout,目的
//用来确保从系统接收到其他新的event之前可以做session的relayout
//功能.
requestLayout();   (2-2-1)

//...
//详见以下分析
res = sWindowSession.add(mWindow, mSeq, mWindowAttributes,
getHostVisibility(),
mAttachInfo.mContentInsets,
mInputChannel);   (2-2-2)
//...
}

(2-2-1)
public void requestLayout() {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}

void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
//停止后续的消息处理功能
mTraversalBarrier = mHandler.getLooper().postSyncBarrier();
// Choreographer设置了CALLBACK类型为TRAVERSAL的处理对象,
//即mTraversalRunnable.Choreographer 是Android 4.1之后才有
//的新类别,主要的功用是用来处理视讯不流畅的问题.
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL,
mTraversalRunnable, null);
scheduleConsumeBatchedInput();
}
}

final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}

void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
//恢复后续的所有讯息事件处理.
mHandler.getLooper().removeSyncBarrier(mTraversalBarrier);

if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}

Trace.traceBegin(Trace.TRACE_TAG_VIEW, "performTraversals");
try {
//开始布局并且绘画显示画面.
performTraversals();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}

if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}


(2-2-2)

我们在前面知道sWindowSession 是由ViewRootImpl 和WindowManagerService 所建立出来的一个Session. 所以实做可以去Session 中找.

[Session.java]
public int add(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, Rect outContentInsets, InputChannel
outInputChannel) {
// final WindowManagerService mService;
return mService.addWindow(this, window, seq, attrs, viewVisibility,
outContentInsets, outInputChannel);
}
[WindowManagerService.java]
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility,
Rect outContentInsets, InputChannel outInputChannel) {
//1. 检查layout属性是否为layout window type.
int res = mPolicy.checkAddPermission(attrs);
if (res != WindowManagerImpl.ADD_OKAY) {
return res;
}

WindowState attachedWindow = null;
WindowState win = null;
//...
//2. 新增一个 WindowState类型对象.
win = new WindowState(this, session, client, token,
attachedWindow, seq, attrs, viewVisibility);

res = WindowManagerImpl.ADD_OKAY;
//...
//3. 详见分析如下:
win.attach();
// mWindowMap是一个hash table,其形态如下:
// final HashMap<IBinder, WindowState> mWindowMap
//4. 将新产生的WindowState搭配一个新的IBinder放入Hash table
mWindowMap.put(client.asBinder(), win);
//…

Binder.restoreCallingIdentity(origId);
return res;
}

[WindowState.java]
void attach() {
//mSession 保存的是一个 sWindowSession对象. 在建构
//WindowState 对象就保存了.
mSession.windowAddedLocked();
}

[Session.java]
void windowAddedLocked() {
if (mSurfaceSession == null) {
//1. 详见分析如下
mSurfaceSession = new SurfaceSession();
//2. 利用STL中的set观念来记录SurfaceSession被产生了几次.
//用来确保每增加一次Window就会有一个SurfaceSession来控制.
mService.mSessions.add(this);
}
mNumWindow++;
}

[SurfaceSession.java]
/** Create a new connection with the surface flinger. */
public SurfaceSession() {
mNativeClient = nativeCreate();    // nativeCreate是一个 native function.
}
private static native int nativeCreate();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐