前言
此文是flutter_hybird_webview 跨进程渲染的实践技术分享开发过程中的研究笔记之一,如有错误还望指出。
源码分析
public class WebView extends MockView {
...
}
public class MockView extends FrameLayout {
...
}
可以知道,webview
的模型及基本行为规范,是遵从view
的,那么我们可以推测其操作软键盘的方式与本地(app)
的操作方式可能是一致的,为此我们先来了解一下app
是如何拉起软键盘的。
关于MockView的个人理解及在开发中的应用,将会在其他文章做分享。
App 拉起软键盘流程
拉起软键盘一般如下:
private void test() {
//请求一下焦点
editText.requestFocus();
//获取 imm 并调用对应方法
InputMethodManager manager = ((InputMethodManager)getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE));
if (manager != null)
manager.showSoftInput(v, 0);
}
从上面的代码可以大致推出这是一个跨进程行为,内部流程大致如下:
- 通过getContext().getSystemService(Context.INPUT_METHOD_SERVICE))获取IMM
- IMM本身并不是输入进程的代理,它内部
IInputMethodManager
才是真正的binder
代理
//当调用manager.showSoftInput(v, 0);时
public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
// ...省略部分代码
synchronized (mH) {
if (mServedView != view && (mServedView == null
|| !mServedView.checkInputConnectionProxy(view))) {
return false;
}
try {
//IInputMethodManager 的实例
return mService.showSoftInput(mClient, flags, resultReceiver);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
3.随后,输入进程
会拉起软键盘,并将对应的的keyEvent
传回到app进程,最终通过dispatchKeyEvent(KeyEvent event)
方法,分发到顶部window
的decor view
并被内部view消费。
至此,对于软键盘(app端
)的拉起我们有了一个大致了解,基于此我们来分析一下webview
的拉起过程。
webview 拉起软键盘流程
简单地讲webview
的本质
是chromium
,而chromium的源码是非常庞大的, 直接去扒源码可以说是大海捞针。
其工作渲染流程,我将在其它文章做介绍
由上面一节我们知道webview
的行为与view
大致相同,那么我们可以尝试逆推,首先我们复写getSystemService
方法:
@Override
public Object getSystemService(@NonNull String name) {
if(name.equals(Context.INPUT_METHOD_SERVICE)) {
//在方法内部,我们输出当前线程的堆栈信息
inputToggleDelegate.inputServiceCall();
}
return super.getSystemService(name);
}
随后,我们打开一个带有输入框的网站,并点击输入框可以得到下面的log:
通过log
,可得软键盘的控制是通过ImeAdapterImpl.java – Chromium Code Search的updateState(...)
方法来实现的。
其内部会调用showSoftKeyboard()方法 :
private void showSoftKeyboard() {
if (!isValid()) return;
if (DEBUG_LOGS) Log.i(TAG, "showSoftKeyboard");
View containerView = getContainerView();
mInputMethodManagerWrapper.showSoftInput(containerView, 0, getNewShowKeyboardReceiver());
if (containerView.getResources().getConfiguration().keyboard
!= Configuration.KEYBOARD_NOKEYS) {
mWebContents.scrollFocusedEditableNodeIntoView();
}
}
接着看一下mInputMethodManagerWrapper.showSoftInput()
:
@Override
public void showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
//...省略部分代码
showSoftInputInternal(view, flags, resultReceiver);
}
private void showSoftInputInternal(View view, int flags, ResultReceiver resultReceiver) {
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); // crbug.com/616283
try {
//通过WindowAndroid的弱引用获得activity,并最终取得imm
InputMethodManager manager = getInputMethodManager();
if (manager != null) {
boolean result = manager.showSoftInput(view, flags, resultReceiver);
if (DEBUG_LOGS) Log.i(TAG, "showSoftInputInternal: " + view + ", " + result);
}
} finally {
StrictMode.setThreadPolicy(oldPolicy);
}
}
到了这里,就与我们上一节的流程汇合了,而后面的分发消费则是大同小异。
WebView拉起软键盘的流程分析到此便结束了,谢谢大家阅读。
原文地址:https://blog.csdn.net/ljq5945/article/details/122847297
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_11243.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!