博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android2.2源码初探
阅读量:6376 次
发布时间:2019-06-23

本文共 9165 字,大约阅读时间需要 30 分钟。

由于代码中涉及到UI的布局,不得已看android源码。

源码系android-8即2.2

从调试环境看最初调用NativeStart.java中的main函数,经过底层的若干次调用,途经ActivityThread.java中的main函数调用,代码如下:

public static final void main(String[] args) {
SamplingProfilerIntegration.start();
 
Process.setArgV0("
");
 
Looper.prepareMainLooper();
 
ActivityThread thread = new ActivityThread();
thread.attach(false);
 
Looper.loop();
 
if (Process.supportsProcesses()) {
throw new RuntimeException("Main thread loop unexpectedly exited");
}
 
thread.detach();
String name = (thread.mInitialApplication != null)
? thread.mInitialApplication.getPackageName()
: "
";
Slog.i(TAG, "Main thread of " + name + " is now exiting");
}

这儿应是程序的起点,Looper.loop()展示的为相关的消息处理机制。使得程序不像普通的main函数一样立刻就结束了。

Looper.java中loop()就是一个消息循环,代码如下:

/**
*  Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next(); // might block
//if (!me.mRun) {
//    break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to    " + msg.target + " "
+ msg.callback);
msg.recycle();
}
}
}

顺便把怎样结束消息循环的代码也贴出来,方便对照消息开始的地方。

public void quit() {
Message msg = Message.obtain();
// NOTE: By enqueueing directly into the message queue, the
// message is left with a null target.  This is how we know it is
// a quit message.
mQueue.enqueueMessage(msg, 0);
}

接着看Handler.java

/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}

 

handleMessage()我们在写消息处理的时候经常用到,看ViewRoot.java中,

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case View.AttachInfo.INVALIDATE_MSG:
((View) msg.obj).invalidate();
break;
case View.AttachInfo.INVALIDATE_RECT_MSG:
final View.AttachInfo.InvalidateInfo info = (View.AttachInfo.InvalidateInfo) msg.obj;
info.target.invalidate(info.left, info.top, info.right, info.bottom);
info.release();
break;
case DO_TRAVERSAL:
if (mProfile) {
Debug.startMethodTracing("ViewRoot");
}
 
performTraversals();
 
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
break;
case FINISHED_EVENT:
handleFinishedEvent(msg.arg1, msg.arg2 != 0);
break;
case DISPATCH_KEY:
if (LOCAL_LOGV) Log.v(
"ViewRoot", "Dispatching key "
+ msg.obj + " to " + mView);
deliverKeyEvent((KeyEvent)msg.obj, true);
break;
case DISPATCH_POINTER: {
MotionEvent event = (MotionEvent)msg.obj;
boolean callWhenDone = msg.arg1 != 0;
 
if (event == null) {
try {
long timeBeforeGettingEvents;
if (MEASURE_LATENCY) {
timeBeforeGettingEvents = System.nanoTime();
}
 
event = sWindowSession.getPendingPointerMove(mWindow);
 
if (MEASURE_LATENCY && event != null) {
lt.sample("9 Client got events      ", System.nanoTime() - event.getEventTimeNano());
lt.sample("8 Client getting events  ", timeBeforeGettingEvents - event.getEventTimeNano());
}
} catch (RemoteException e) {
}
callWhenDone = false;
}
if (event != null && mTranslator != null) {
mTranslator.translateEventInScreenToAppWindow(event);
}
try {
boolean handled;
if (mView != null && mAdded && event != null) {
 
// enter touch mode on the down
boolean isDown = event.getAction() == MotionEvent.ACTION_DOWN;
if (isDown) {
ensureTouchMode(true);
}
if(Config.LOGV) {
captureMotionLog("captureDispatchPointer", event);
}
if (mCurScrollY != 0) {
event.offsetLocation(0, mCurScrollY);
}
if (MEASURE_LATENCY) {
lt.sample("A Dispatching TouchEvents", System.nanoTime() - event.getEventTimeNano());
}
handled = mView.dispatchTouchEvent(event);
if (MEASURE_LATENCY) {
lt.sample("B Dispatched TouchEvents ", System.nanoTime() - event.getEventTimeNano());
}
if (!handled && isDown) {
int edgeSlop = mViewConfiguration.getScaledEdgeSlop();
 
final int edgeFlags = event.getEdgeFlags();
int direction = View.FOCUS_UP;
int x = (int)event.getX();
int y = (int)event.getY();
final int[] deltas = new int[2];
 
if ((edgeFlags & MotionEvent.EDGE_TOP) != 0) {
direction = View.FOCUS_DOWN;
if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
deltas[0] = edgeSlop;
x += edgeSlop;
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
deltas[0] = -edgeSlop;
x -= edgeSlop;
}
} else if ((edgeFlags & MotionEvent.EDGE_BOTTOM) != 0) {
direction = View.FOCUS_UP;
if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
deltas[0] = edgeSlop;
x += edgeSlop;
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
deltas[0] = -edgeSlop;
x -= edgeSlop;
}
} else if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
direction = View.FOCUS_RIGHT;
} else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
direction = View.FOCUS_LEFT;
}
 
if (edgeFlags != 0 && mView instanceof ViewGroup) {
View nearest = FocusFinder.getInstance().findNearestTouchable(
((ViewGroup) mView), x, y, direction, deltas);
if (nearest != null) {
event.offsetLocation(deltas[0], deltas[1]);
event.setEdgeFlags(0);
mView.dispatchTouchEvent(event);
}
}
}
}
} finally {
if (callWhenDone) {
try {
sWindowSession.finishKey(mWindow);
} catch (RemoteException e) {
}
}
if (event != null) {
event.recycle();
}
if (LOCAL_LOGV || WATCH_POINTER) Log.i(TAG, "Done dispatching!");
// Let the exception fall through -- the looper will catch
// it and take care of the bad app for us.
}
} break;
case DISPATCH_TRACKBALL:
deliverTrackballEvent((MotionEvent)msg.obj, msg.arg1 != 0);
break;
case DISPATCH_APP_VISIBILITY:
handleAppVisibility(msg.arg1 != 0);
break;
case DISPATCH_GET_NEW_SURFACE:
handleGetNewSurface();
break;
case RESIZED:
ResizedInfo ri = (ResizedInfo)msg.obj;
 
if (mWinFrame.width() == msg.arg1 && mWinFrame.height() == msg.arg2
&& mPendingContentInsets.equals(ri.coveredInsets)
&& mPendingVisibleInsets.equals(ri.visibleInsets)
&& ((ResizedInfo)msg.obj).newConfig == null) {
break;
}
// fall through...
case RESIZED_REPORT:
if (mAdded) {
Configuration config = ((ResizedInfo)msg.obj).newConfig;
if (config != null) {
updateConfiguration(config, false);
}
mWinFrame.left = 0;
mWinFrame.right = msg.arg1;
mWinFrame.top = 0;
mWinFrame.bottom = msg.arg2;
mPendingContentInsets.set(((ResizedInfo)msg.obj).coveredInsets);
mPendingVisibleInsets.set(((ResizedInfo)msg.obj).visibleInsets);
if (msg.what == RESIZED_REPORT) {
mReportNextDraw = true;
}
 
if (mView != null) {
forceLayout(mView);
}
requestLayout();
}
break;
case WINDOW_FOCUS_CHANGED: {
if (mAdded) {
boolean hasWindowFocus = msg.arg1 != 0;
mAttachInfo.mHasWindowFocus = hasWindowFocus;
if (hasWindowFocus) {
boolean inTouchMode = msg.arg2 != 0;
ensureTouchModeLocally(inTouchMode);
 
if (mGlWanted) {
checkEglErrors();
// we lost the gl context, so recreate it.
if (mGlWanted && !mUseGL) {
initializeGL();
if (mGlCanvas != null) {
float appScale = mAttachInfo.mApplicationScale;
mGlCanvas.setViewport(
(int) (mWidth * appScale + 0.5f),
(int) (mHeight * appScale + 0.5f));
}
}
}
}
 
mLastWasImTarget = WindowManager.LayoutParams
.mayUseInputMethod(mWindowAttributes.flags);
 
InputMethodManager imm = InputMethodManager.peekInstance();
if (mView != null) {
if (hasWindowFocus && imm != null && mLastWasImTarget) {
imm.startGettingWindowFocus(mView);
}
mAttachInfo.mKeyDispatchState.reset();
mView.dispatchWindowFocusChanged(hasWindowFocus);
}
 
// Note: must be done after the focus change callbacks,
// so all of the view state is set up correctly.
if (hasWindowFocus) {
if (imm != null && mLastWasImTarget) {
imm.onWindowFocus(mView, mView.findFocus(),
mWindowAttributes.softInputMode,
!mHasHadWindowFocus, mWindowAttributes.flags);
}
// Clear the forward bit.  We can just do this directly, since
// the window manager doesn't care about it.
mWindowAttributes.softInputMode &=
~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
((WindowManager.LayoutParams)mView.getLayoutParams())
.softInputMode &=
~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
mHasHadWindowFocus = true;
}
 
if (hasWindowFocus && mView != null) {
sendAccessibilityEvents();
}
}
} break;
case DIE:
doDie();
break;
case DISPATCH_KEY_FROM_IME: {
if (LOCAL_LOGV) Log.v(
"ViewRoot", "Dispatching key "
+ msg.obj + " from IME to " + mView);
KeyEvent event = (KeyEvent)msg.obj;
if ((event.getFlags()&KeyEvent.FLAG_FROM_SYSTEM) != 0) {
// The IME is trying to say this event is from the
// system!  Bad bad bad!
event = KeyEvent.changeFlags(event,
event.getFlags()&~KeyEvent.FLAG_FROM_SYSTEM);
}
deliverKeyEventToViewHierarchy((KeyEvent)msg.obj, false);
} break;
case FINISH_INPUT_CONNECTION: {
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null) {
imm.reportFinishInputConnection((InputConnection)msg.obj);
}
} break;
case CHECK_FOCUS: {
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null) {
imm.checkFocus();
}
} break;
case CLOSE_SYSTEM_DIALOGS: {
if (mView != null) {
mView.onCloseSystemDialogs((String)msg.obj);
}
} break;
}
}

转载地址:http://cgvqa.baihongyu.com/

你可能感兴趣的文章
QT 4.8 静态库编译方法
查看>>
小程序授权代码示例
查看>>
WinForm中重绘TabControl选项卡标题
查看>>
实验五 数据结构综合应用
查看>>
Error instantiating class com.eaju.pojo.UserInfo with invalid types () or values ()
查看>>
unable to load default svn client
查看>>
数据库相关
查看>>
后缀数组 POJ 1743 Musical Theme
查看>>
python基础——认识(if __name__ == ‘__main__’:)
查看>>
SQL逻辑读变成零
查看>>
css方法 - 移动端h5在iphonex的适配
查看>>
Web前端开发的基本要求和认识
查看>>
20161103学习笔记
查看>>
Kafka分区原理图
查看>>
多行省略号
查看>>
Centos 打开80端口
查看>>
【OCP题库-12c】最新CUUG OCP 071考试题库(70题)
查看>>
基于GTID多源复制扩展
查看>>
用SignalR 2.0开发客服系统[系列2:实现聊天室]
查看>>
08面向对象强化
查看>>