Android4.4之Input模組筆記,android4.4input

來源:互聯網
上載者:User

Android4.4之Input模組筆記,android4.4input

在InputReader從EventHub中擷取輸入事件,包含觸控螢幕事件、物理按鍵事件等,然後轉交給InputDispatcher線程,InputDispatcher經過篩選,過濾輸入事件。對於觸摸事件通過調用findTouchedWindowTargetsLocked()函數找到合適的InputTarget,然後通過dispatchEventLocked()->prepareDispatchCycleLocked()->enqueueDispatchEntriesLocked()->enqueueDispatchEntryLocked()->  connection->outboundQueue.enqueueAtTail(dispatchEntry)添加到與InputTarget一一對應的connection中的一個隊列中。如果之前該隊列無資料,並且當前觸摸事件已成功加入該隊列,則繼續調用startDispatchCycleLocked()函數進行分發處理。在startDispatchCycleLocked()中,有一個while迴圈,該迴圈從connection->outboundQueue隊列中取出輸入事件,如果該輸入事件是按鍵(key)事件,則調用connection->inputPublisher.publishKeyEvent()函數,如果是觸摸事件則調用connection->inputPublisher.publishMotionEvent()。publishKeyEvent()和publishMotionEvent()都是調用mChannel->sendMessage()將輸入事件發送出去。mChannel是一個C++層InputChannel對象,該對象的賦值過程如下:registerInputChannel()->new Connection->Connection()建構函式->InputPublisher()建構函式。事實上,在registerInputChannel()被調用之前,ViewRootImple在增加一個視窗時調用ViewRootImpl.setView()->mWindowSession.addToDisplay()-WindowManagerService.addWindow(),在addWindow()中會建立一對InputChannel(Nativie層),實際上是建立一對Socket,服務端InputChanel被WMS註冊到InputDispatcher中,用戶端InputChannel被返回給ViewRootImpl,ViewRootImpl將用戶端InputChannel作為參數new一個InputEventReceiver對象,在InputEventReceiver()建構函式中繼續調用nativeInit()函數來建立一個native層的NativeInputEventReceiver對象,前面建立的用戶端InputChannel會儲存在該對象中。

總結:WMS會調用native層介面建立一對通訊端,服務端儲存在InputDispatcher中,用戶端儲存在NativeInputEventReceiver中(android_view_inputEventReceiver.cpp)。

很容易想到輸入事件是從InputDispatcher流向NativeInputEventReceiver中。在建立一個native層的NativeInputEventReceiver對象後會立即調用NativeInputEventReceiver->initialize(),該函數調用mMessageQueue->getLooper()->addFd(fd,0, events, this, NULL)將用戶端socket控制代碼添加到Looper的輪詢隊列中,參數this指向NativeInputEventReceiver本身,意味著只要服務端InputDispatcher發送輸入事件,用戶端收到這個事件,就調用NativeInputEventReceiver的某個函數,具體調用哪個函數,自然是NativeInputEventReceiver實現了LooperCallback的介面函數handleEvent()。但此時收到的事件只是代表socket用戶端有事件來,並沒有把具體的事件讀取出來,這點需要注意。

總結:用戶端收到輸入事件,即調用NativeInputEventReceiver->handleEvent()函數。

在handleEvent()函數中,繼續調用consumeEvents()->mInputConsumer.consume()->mChannel->receiveMessage(&mMsg)將具體輸入事件讀取出來,然後調用env->CallVoidMethod(receiverObj.get(), gInputEventReceiverClassInfo.dispatchInputEvent,seq, inputEventObj),可以知道native層讀取輸入事件後,然後會回調java層InputEventReceiver.java中的dispatchInputEvent()函數。事實上,

dispatchInputEvent繼續調用onInputEvent(event);此時可能並不調用InputEventReceiver類中的onInputEvent()方法,而是調用子類onInputEvent()方法。在ViewRootImpl中存在WindowInputEventReceiver類型變數mInputEventReceiver,WindowInputEventReceiver類繼承InputEventReceiver,並實現onInputEvent()方法由此可得出結論:native層socket用戶端讀取輸入事件,最終調用InputEventReceiver類子類的onInputEvent()方法,ViewRootImpl繼承InputEventReceiver,因此ViewRootImpl.onInputEvent()將被調用。

總結:對於一般的觸控螢幕事件最終處理者是ViewRootImpl類,對於IME則處理者是IInputMethodSessionWrapper類,當然WMS是不會處理這些輸入事件的。

繼續研究ViewRootImpl.onInputEvent()函數,onInputEvent()->doProcessInputEvents()->deliverInputEvent(),deliverInputEvent()函數中會調用stage.deliver(q),stage是mFirstPostImeInputStage 或 mFirstInputStage,這個兩個InputStage對象在setView中賦值。InputStage類設計就是責任鏈模式。因為觸摸事件是要分發到具體的View上來,所以對於一般的觸摸事件最後是傳遞到ViewPostImeInputStage類中來處理,處理函數是processPointerEvent(q),這個函數調用mView.dispatchPointerEvent(event)將事件分發出去,mView具體是什麼呢?mView其實就是DecorView,每一個視窗有且僅有一個DecorView,且處在最頂層,由於DecorView未重寫dispatchPointerEvent(),所以調用還是父類View類的dispatchPointerEvent()方法。

public final boolean dispatchPointerEvent(MotionEvent event) {        if (event.isTouchEvent()) {            return dispatchTouchEvent(event);        } else {            return dispatchGenericMotionEvent(event);        }    }
該方法繼續調用dispatchTouchEvent(event),DecorView重新了該方法:

<span style="font-family:Microsoft YaHei;font-size:18px;">@Override        public boolean dispatchTouchEvent(MotionEvent ev) {            final Callback cb = getCallback();            return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchTouchEvent(ev)                    : super.dispatchTouchEvent(ev);        }</span>

getCallback()函數擷取apk註冊的用於攔截按鍵、觸摸等事件的回呼函數。一般window不會攔截處理觸摸事件,所以會繼續調用super.dispatchTouchEvent(ev),即父類ViewGroup的dispatchTouchEvent()函數,在該函數中尋找到對應的View再繼續調用dispatchTransformedTouchEvent()

<span style="font-family:Microsoft YaHei;font-size:18px;">                   for (int i = childrenCount - 1; i >= 0; i--) {                            final int childIndex = customOrder ?                                    getChildDrawingOrder(childrenCount, i) : i;                            final View child = children[childIndex];                            if (!canViewReceivePointerEvents(child)                                    || !isTransformedTouchPointInView(x, y, child, null)) {                                continue;                            }                            newTouchTarget = getTouchTarget(child);                            if (newTouchTarget != null) {                                // Child is already receiving touch within its bounds.                                // Give it the new pointer in addition to the ones it is handling.                                newTouchTarget.pointerIdBits |= idBitsToAssign;                                break;                            }                            resetCancelNextUpFlag(child);                            if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {                                // Child wants to receive touch within its bounds.                                mLastTouchDownTime = ev.getDownTime();                                mLastTouchDownIndex = childIndex;                                mLastTouchDownX = ev.getX();                                mLastTouchDownY = ev.getY();                                newTouchTarget = addTouchTarget(child, idBitsToAssign);                                alreadyDispatchedToNewTouchTarget = true;                                break;                            }                       }</span>
具體的分發規則可自行研究代碼。


android開發所有的環境搭建完成,為何AVD中的target只有android44不可以選其他的

開啟你的sdkManage,把其他版本的sdk也下載下來就好了.估計你當時就只下載了4.4的
 
android開發中input type問題

本來就支援加號或減號
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.