Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android Framework系列之IMF(三)

Android Framework系列之IMF(三)

編輯:Android開發實例

我們知道當一個編輯框獲得焦點的時候,將會create一個新的IME客戶端,那麼IMF框架是怎樣處理這個事件的呢?

 

首先調用EditText的構造函數EditTex->TextView->setText()           

 

  1. InputMethodManager imm = InputMethodManager.peekInstance();  
  2. if (imm != null) imm.restartInput(this); 

->startInputInner

 

  1. void startInputInner() {  
  2.     final View view;  
  3.     synchronized (mH) {  
  4.         view = mServedView;  
  5.           
  6.         // Make sure we have a window token for the served view.  
  7.         if (DEBUG) Log.v(TAG, "Starting input: view=" + view);  
  8.         if (view == null) {  
  9.             if (DEBUG) Log.v(TAG, "ABORT input: no served view!");  
  10.             return;  
  11.         }  
  12.     }  
  13.       
  14.     // Now we need to get an input connection from the served view.  
  15.     // This is complicated in a couple ways: we can't be holding our lock  
  16.     // when calling out to the view, and we need to make sure we call into  
  17.     // the view on the same thread that is driving its view hierarchy.  
  18.     Handler vh = view.getHandler();  
  19.     if (vh == null) {  
  20.         // If the view doesn't have a handler, something has changed out  
  21.         // from under us, so just bail.  
  22.         if (DEBUG) Log.v(TAG, "ABORT input: no handler for view!");  
  23.         return;  
  24.     }  
  25.     if (vh.getLooper() != Looper.myLooper()) {  
  26.         // The view is running on a different thread than our own, so  
  27.         // we need to reschedule our work for over there.  
  28.         if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread");  
  29.         vh.post(new Runnable() {  
  30.             public void run() {  
  31.                 startInputInner();  
  32.             }  
  33.         });  
  34.         return;  
  35.     }  
  36.       
  37.     // Okay we are now ready to call into the served view and have it  
  38.     // do its stuff.  
  39.     // Life is good: let's hook everything up!  
  40.     EditorInfo tba = new EditorInfo();  
  41.     tba.packageName = view.getContext().getPackageName();  
  42.     tba.fieldId = view.getId();  
  43.     InputConnection ic = view.onCreateInputConnection(tba); //create 新的InputConnection   
  44.     if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);  
  45.       
  46.     synchronized (mH) {  
  47.         // Now that we are locked again, validate that our state hasn't  
  48.         // changed.  
  49.         if (mServedView != view || !mServedConnecting) {  
  50.             // Something else happened, so abort.  
  51.             if (DEBUG) Log.v(TAG,   
  52.                     "Starting input: finished by someone else (view=" 
  53.                     + mServedView + " conn=" + mServedConnecting + ")");  
  54.             return;  
  55.         }  
  56.           
  57.         // If we already have a text box, then this view is already  
  58.         // connected so we want to restart it.  
  59.         final boolean initial = mCurrentTextBoxAttribute == null;  
  60.           
  61.         // Hook 'em up and let 'er rip.  
  62.         mCurrentTextBoxAttribute = tba;  
  63.         mServedConnecting = false;  
  64.         mServedInputConnection = ic;  
  65.         IInputContext servedContext;  
  66.         if (ic != null) {  
  67.             mCursorSelStart = tba.initialSelStart;  
  68.             mCursorSelEnd = tba.initialSelEnd;  
  69.             mCursorCandStart = -1;  
  70.             mCursorCandEnd = -1;  
  71.             mCursorRect.setEmpty();  
  72.             servedContext = new ControlledInputConnectionWrapper(vh.getLooper(), ic);  
  73.         } else {  
  74.             servedContext = null;  
  75.         }  
  76.           
  77.         try {  
  78.             if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic=" 
  79.                     + ic + " tba=" + tba + " initial=" + initial);  
  80.             InputBindResult res = mService.startInput(mClient,  
  81.                     servedContext, tba, initial, mCurMethod == null); //啟動IMEservice  
  82.             if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);  
  83.             if (res != null) {  
  84.                 if (res.id != null) {  
  85.                     mBindSequence = res.sequence;  
  86.                     mCurMethod = res.method;  
  87.                 } else {  
  88.                     // This means there is no input method available.  
  89.                     if (DEBUG) Log.v(TAG, "ABORT input: no input method!");  
  90.                     return;  
  91.                 }  
  92.             }  
  93.             if (mCurMethod != null && mCompletions != null) {  
  94.                 try {  
  95.                     mCurMethod.displayCompletions(mCompletions);  
  96.                 } catch (RemoteException e) {  
  97.                 }  
  98.             }  
  99.         } catch (RemoteException e) {  
  100.             Log.w(TAG, "IME died: " + mCurId, e);  
  101.         }  
  102.     }  

 那麼到了IME部分的流程又是如何的呢?

首先收到configure change的event調用onConfigurationChanged->inputmethodservice.onConfigurationChanged(conf)

 

  1. @Override public void onConfigurationChanged(Configuration newConfig) {  
  2.        super.onConfigurationChanged(newConfig);  
  3.          
  4.        boolean visible = mWindowVisible;  
  5.        int showFlags = mShowInputFlags;  
  6.        boolean showingInput = mShowInputRequested;  
  7.        CompletionInfo[] completions = mCurCompletions;  
  8.        initViews();  
  9.        mInputViewStarted = false;  
  10.        mCandidatesViewStarted = false;  
  11.        if (mInputStarted) {  
  12.            doStartInput(getCurrentInputConnection(),  
  13.                    getCurrentInputEditorInfo(), true);  //調用startinput,創建IME的input  
  14.        }  
  15.        if (visible) {  
  16.            if (showingInput) {  
  17.                // If we were last showing the soft keyboard, try to do so again.  
  18.                if (onShowInputRequested(showFlags, true)) {  
  19.                    showWindow(true);  
  20.                    if (completions != null) {  
  21.                        mCurCompletions = completions;  
  22.                        onDisplayCompletions(completions);  
  23.                    }  
  24.                } else {  
  25.                    hideWindow();  
  26.                }  
  27.            } else if (mCandidatesVisibility == View.VISIBLE) {  
  28.                // If the candidates are currently visible, make sure the  
  29.                // window is shown for them.  
  30.                showWindow(false);  
  31.            } else {  
  32.                // Otherwise hide the window.  
  33.                hideWindow();  
  34.            }  
  35.        }  
  36.    } 

doStartInput->initialize->onInitializeInterface->onStartInput->onStartInputView.

onStartInputView中會handle各種IME的event並進一步調用IME自身的onCreate函數,做進一步的初始化以及receiver的rigister。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved