- com.grabeco 는 application 의 activity 이다.
- source version : 4.2.2 r1 source
Stack trace
onOptionsItemSelected():106, MainActivity {com.grabeco}
onMenuItemSelected():2548, Activity {android.app}
onMenuItemSelected():366, FragmentActivity {android.support.v4.app}
superOnMenuItemSelected():232, ActionBarActivity {android.support.v7.app}
onMenuItemSelected():159, ActionBarActivityDelegateICS {android.support.v7.app}
onMenuItemSelected():130, ActionBarActivity {android.support.v7.app}
onMenuItemSelected():295, ActionBarActivityDelegateICS$WindowCallbackWrapper {android.support.v7.app}
onMenuItemSelected():980, PhoneWindow {com.android.internal.policy.impl}
dispatchMenuItemSelected():735, MenuBuilder {com.android.internal.view.menu}
invoke():149, MenuItemImpl {com.android.internal.view.menu}
performItemAction():874, MenuBuilder {com.android.internal.view.menu}
onItemClick():156, MenuPopupHelper {com.android.internal.view.menu}
performItemClick():298, AdapterView {android.widget}
performItemClick():1100, AbsListView {android.widget}
run():2749, AbsListView$PerformClick {android.widget}
run():3423, AbsListView$1 {android.widget}
handleCallback():725, Handler {android.os}
dispatchMessage():92, Handler {android.os}
loop():137, Looper {android.os}
main():5041, ActivityThread {android.app}
Flow with Code snippet
public static void main(String[] args) { ... Looper.prepareMainLooper(); .. Looper.loop(); public static void loop() { final Looper me = myLooper(); ... final MessageQueue queue = me.mQueue; ... for (;;) { Message msg = queue.next(); // might block ... msg.target.dispatchMessage(msg); ... msg.recycle(); } public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } private static void handleCallback(Message message) { message.callback.run(); } android.widget.AbsListView public boolean onTouchEvent(MotionEvent ev) { ... case MotionEvent.ACTION_UP: { switch (mTouchMode) { case TOUCH_MODE_DOWN: case TOUCH_MODE_TAP: case TOUCH_MODE_DONE_WAITING: if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) { ... if (!mDataChanged && mAdapter.isEnabled(motionPosition)) { mTouchModeReset = new Runnable() { @Override public void run() { mTouchMode = TOUCH_MODE_REST; child.setPressed(false); setPressed(false); if (!mDataChanged) { performClick.run(); } } }; postDelayed(mTouchModeReset, ViewConfiguration.getPressedStateDuration()); } ... } private class PerformClick extends WindowRunnnable implements Runnable { public void run() { ... if (adapter != null && mItemCount > 0 && motionPosition != INVALID_POSITION && motionPosition < adapter.getCount() && sameWindow()) { final View view = getChildAt(motionPosition - mFirstPosition); if (view != null) { performItemClick(view, motionPosition, adapter.getItemId(motionPosition)); } } } ... } public boolean performItemClick(View view, int position, long id) { ... boolean dispatchItemClick = true; ... if (dispatchItemClick) { handled |= super.performItemClick(view, position, id); } return handled; } public boolean performItemClick(View view, int position, long id) { if (mOnItemClickListener != null) { playSoundEffect(SoundEffectConstants.CLICK); if (view != null) { view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); } mOnItemClickListener.onItemClick(this, view, position, id); return true; } return false; } public void onItemClick(AdapterView<?> parent, View view, int position, long id) { MenuAdapter adapter = mAdapter; adapter.mAdapterMenu.performItemAction(adapter.getItem(position), 0); } public boolean performItemAction(MenuItem item, int flags) { MenuItemImpl itemImpl = (MenuItemImpl) item; if (itemImpl == null || !itemImpl.isEnabled()) { return false; } boolean invoked = itemImpl.invoke(); ... } public boolean invoke() { if (mClickListener != null && mClickListener.onMenuItemClick(this)) { return true; } if (mMenu.dispatchMenuItemSelected(mMenu.getRootMenu(), this)) { return true; } ... } boolean dispatchMenuItemSelected(MenuBuilder menu, MenuItem item) { return mCallback != null && mCallback.onMenuItemSelected(menu, item); } public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { final PanelFeatureState panel = findMenuPanel(menu.getRootMenu()); if (panel != null) { return cb.onMenuItemSelected(panel.featureId, item); } } return false; } ... android.app.Activity public boolean onMenuItemSelected(int featureId, MenuItem item) { switch (featureId) { case Window.FEATURE_OPTIONS_PANEL: // Put event logging here so it gets called even if subclass // doesn't call through to superclass's implmeentation of each // of these methods below EventLog.writeEvent(50000, 0, item.getTitleCondensed()); if (onOptionsItemSelected(item)) { return true; } ... }
Looper 와 message queue
ref.1 의 그림을 보면, looper 와 message queue 의 관계를 좀 더 잘 이해할 수 있다. 대략적으로 이해한 바를 적어본다면,- looper 는 일 처리를 하는 곳이고,
- message queue 는 event 가 발생할 때 event 를 looper 에 전달하기 위한 통로이다.
정도가 되겠다.
댓글 없음:
댓글 쓰기