1 Android 输入法框架源码分析总结

1 IMF主要包含三个部分
1.ager(IMM)运行于客户端进程
- -Input(IMM)是负责管理其他部分交互的中心,以-side API的形式存在于每一个应用上下文中,同时和rvice(IMMF)进行通信,用来沟通管理所有进程间交互的全局系统服务,可以通过.()来获取一个的实例 。
2. (IMS)运行于输入法进程
3.rvice (IMMS)运行于系统进程,负责管理系统所有输入法
获取焦点
请求绑定解绑
显示输入法
输入法框架

1  Android 输入法框架源码分析总结

文章插图
2创建
每个程序都会有一个 实例,IMM是程序和IMMS通信的接口,IMM实例在初始化的时候被创建 , imm = .();
// ViewRootImpl.javapublic final class ViewRootImpl implements ViewParent,View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {public ViewRootImpl(Context context, Display display) {...mWindowSession = WindowManagerGlobal.getWindowSession();...}// WindowManagerGlobal.javapublic static IWindowSession getWindowSession() {synchronized (WindowManagerGlobal.class) {if (sWindowSession == null) {try {// 生成 InputMethodManager 实例InputMethodManager imm = InputMethodManager.getInstance();IWindowManager windowManager = getWindowManagerService();sWindowSession = windowManager.openSession(new IWindowSessionCallback.Stub() {@Overridepublic void onAnimatorScaleChanged(float scale) {ValueAnimator.setDurationScale(scale);}},imm.getClient(), imm.getInputContext());} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}return sWindowSession;}}// InputMethodManager.java/*** Retrieve the global InputMethodManager instance, creating it if it* doesn't already exist.* @hide*/public static InputMethodManager getInstance() {synchronized (InputMethodManager.class) {if (sInstance == null) {try {sInstance = new InputMethodManager(service, Looper.getMainLooper());} cathch () {throw new IllegalStateException(e);}}return sInstance;}}
3 程序获取焦点
1  Android 输入法框架源码分析总结

文章插图
// **WindowManagerService.java**private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {//计算焦点windowWindowState newFocus = computeFocusedWindowLocked();if (mCurrentFocus != newFocus) {//焦点window发生变化,post一个message来通知程序焦点发生变化了mH.removeMessages(H.REPORT_FOCUS_CHANGE);mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);return true;}return false;}private WindowState computeFocusedWindowLocked() {if (mAnimator.mUniverseBackground != null&& mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {return mAnimator.mUniverseBackground.mWin;}final int displayCount = mDisplayContents.size();for (int i = 0; i < displayCount; i++) {final DisplayContent displayContent = mDisplayContents.valueAt(i);WindowState win = findFocusedWindowLocked(displayContent);if (win != null) {return win;}}return null;}//该函数就是找出最top的可以接收按键事件的window,这个window就获得焦点private WindowState findFocusedWindowLocked(DisplayContent displayContent) {final WindowList windows = displayContent.getWindowList();for (int i = windows.size() - 1; i >= 0; i--) {final WindowState win = windows.get(i);//是否为activity的windowAppWindowToken wtoken = win.mAppToken;//重要函数,window是否可以获取焦点if (!win.canReceiveKeys()) {continue;}// mFocusedApp是最top的activity ,下面逻辑是为了确保焦点window的app//必须是焦点程序之上,所以这个逻辑其实并没有多大作用,只是为了检测出//错误if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&mFocusedApp != null) {ArrayList tasks = displayContent.getTasks();for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {AppTokenList tokens = tasks.get(taskNdx).mAppTokens;int tokenNdx = tokens.size() - 1;for ( ; tokenNdx >= 0; --tokenNdx) {final AppWindowToken token = tokens.get(tokenNdx);if (wtoken == token) {break;}if (mFocusedApp == token) {return null;}}}}return win;}return null;}public final boolean canReceiveKeys() {return isVisibleOrAdding()&& (mViewVisibility == View.VISIBLE)&& ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);}//由于输入法的window带有FLAG_NOT_FOCUSABLE, 从上可见其不可能是焦点window//接下来系统开始通知程序端哪个window获得了焦点 。final class H extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case REPORT_FOCUS_CHANGE: {WindowState lastFocus;WindowState newFocus;synchronized(mWindowMap) {lastFocus = mLastFocus;newFocus = mCurrentFocus;if (lastFocus == newFocus) {// Focus is not changing, so nothing to do.return;}mLastFocus = newFocus;}if (newFocus != null) {//通知新的焦点程序其获得了焦点newFocus.reportFocusChangedSerialized(true, mInTouchMode);notifyFocusChanged();}if (lastFocus != null) {//通知老的焦点程序其获得了焦点lastFocus.reportFocusChangedSerialized(false, mInTouchMode);}} break;}public void reportFocusChangedSerialized(boolean focused, boolean inTouchMode) {try {//这个就是通过Binder告知client其获得或失去了焦点mClient.windowFocusChanged(focused, inTouchMode);} catch (RemoteException e) {}}