当前位置: 代码迷 >> Android >> Android Framework系列之IMF(3)
  详细解决方案

Android Framework系列之IMF(3)

热度:25   发布时间:2016-05-01 16:01:07.0
Android Framework系列之IMF(三)

原创文章,转载请标注出处----

?

我们知道当一个编辑框获得焦点的时候,将会create一个新的IME客户端,那么IMF框架是怎样处理这个事件的呢?

?

首先调用EditText的构造函数EditTex->TextView->setText()???????????

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

?

->startInputInner

?

    void startInputInner() {        final View view;        synchronized (mH) {            view = mServedView;                        // Make sure we have a window token for the served view.            if (DEBUG) Log.v(TAG, "Starting input: view=" + view);            if (view == null) {                if (DEBUG) Log.v(TAG, "ABORT input: no served view!");                return;            }        }                // Now we need to get an input connection from the served view.        // This is complicated in a couple ways: we can't be holding our lock        // when calling out to the view, and we need to make sure we call into        // the view on the same thread that is driving its view hierarchy.        Handler vh = view.getHandler();        if (vh == null) {            // If the view doesn't have a handler, something has changed out            // from under us, so just bail.            if (DEBUG) Log.v(TAG, "ABORT input: no handler for view!");            return;        }        if (vh.getLooper() != Looper.myLooper()) {            // The view is running on a different thread than our own, so            // we need to reschedule our work for over there.            if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread");            vh.post(new Runnable() {                public void run() {                    startInputInner();                }            });            return;        }                // Okay we are now ready to call into the served view and have it        // do its stuff.        // Life is good: let's hook everything up!        EditorInfo tba = new EditorInfo();        tba.packageName = view.getContext().getPackageName();        tba.fieldId = view.getId();        InputConnection ic = view.onCreateInputConnection(tba); //create 新的InputConnection         if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);                synchronized (mH) {            // Now that we are locked again, validate that our state hasn't            // changed.            if (mServedView != view || !mServedConnecting) {                // Something else happened, so abort.                if (DEBUG) Log.v(TAG,                         "Starting input: finished by someone else (view="                        + mServedView + " conn=" + mServedConnecting + ")");                return;            }                        // If we already have a text box, then this view is already            // connected so we want to restart it.            final boolean initial = mCurrentTextBoxAttribute == null;                        // Hook 'em up and let 'er rip.            mCurrentTextBoxAttribute = tba;            mServedConnecting = false;            mServedInputConnection = ic;            IInputContext servedContext;            if (ic != null) {                mCursorSelStart = tba.initialSelStart;                mCursorSelEnd = tba.initialSelEnd;                mCursorCandStart = -1;                mCursorCandEnd = -1;                mCursorRect.setEmpty();                servedContext = new ControlledInputConnectionWrapper(vh.getLooper(), ic);            } else {                servedContext = null;            }                        try {                if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic="                        + ic + " tba=" + tba + " initial=" + initial);                InputBindResult res = mService.startInput(mClient,                        servedContext, tba, initial, mCurMethod == null); //启动IMEservice                if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);                if (res != null) {                    if (res.id != null) {                        mBindSequence = res.sequence;                        mCurMethod = res.method;                    } else {                        // This means there is no input method available.                        if (DEBUG) Log.v(TAG, "ABORT input: no input method!");                        return;                    }                }                if (mCurMethod != null && mCompletions != null) {                    try {                        mCurMethod.displayCompletions(mCompletions);                    } catch (RemoteException e) {                    }                }            } catch (RemoteException e) {                Log.w(TAG, "IME died: " + mCurId, e);            }        }    

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

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

 @Override public void onConfigurationChanged(Configuration newConfig) {        super.onConfigurationChanged(newConfig);                boolean visible = mWindowVisible;        int showFlags = mShowInputFlags;        boolean showingInput = mShowInputRequested;        CompletionInfo[] completions = mCurCompletions;        initViews();        mInputViewStarted = false;        mCandidatesViewStarted = false;        if (mInputStarted) {            doStartInput(getCurrentInputConnection(),                    getCurrentInputEditorInfo(), true);  //调用startinput,创建IME的input        }        if (visible) {            if (showingInput) {                // If we were last showing the soft keyboard, try to do so again.                if (onShowInputRequested(showFlags, true)) {                    showWindow(true);                    if (completions != null) {                        mCurCompletions = completions;                        onDisplayCompletions(completions);                    }                } else {                    hideWindow();                }            } else if (mCandidatesVisibility == View.VISIBLE) {                // If the candidates are currently visible, make sure the                // window is shown for them.                showWindow(false);            } else {                // Otherwise hide the window.                hideWindow();            }        }    }

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

onStartInputView中会handle各种IME的event并进一步调用IME自身的onCreate函数,做进一步的初始化以及receiver的rigister。

?

  相关解决方案