Javascript 后台线程冻结WebView
我将Javascript 后台线程冻结WebView,javascript,java,android,multithreading,webview,Javascript,Java,Android,Multithreading,Webview,我将JavaScript接口注入我的WebView,一旦我使用了我在JavaScript中定义的本机方法,if就会冻结WebView,直到我返回一个值。 例如: 在本例中,WebView被卡住8秒。我还仔细检查了它不是主线程,而且它确实不是主线程,所以我不明白为什么它会冻结WebView myWebView.addJavascriptInterface( new WebViewHandler.JavaScriptInterface(), "webCallHandler" ); public c
JavaScript
接口注入我的WebView
,一旦我使用了我在JavaScript
中定义的本机方法,if就会冻结WebView
,直到我返回一个值。
例如:
在本例中,WebView
被卡住8秒。我还仔细检查了它不是主线程,而且它确实不是主线程,所以我不明白为什么它会冻结WebView
myWebView.addJavascriptInterface( new WebViewHandler.JavaScriptInterface(), "webCallHandler" );
public class JavaScriptInterface
{
@JavascriptInterface
public String jsToAndroidNativeFunc(String Data)
{
Callable<String> task = new Callable<String>() {
@Override
public String call() throws Exception {
try {
if( Looper.getMainLooper() == Looper.myLooper() )
Log.d("TAG","Main Thread");
else
Log.d("TAG","Not Main Thread");
TimeUnit.SECONDS.sleep(8); // the webview is now stuck during these 8 seconds
return "123";
}
catch (InterruptedException e) {
throw new IllegalStateException("task interrupted", e);
}
}
};
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<String> future = executor.submit(task);
try {
return future.get();
}
catch (InterruptedException e) {
e.printStackTrace();
return "111";
} catch (ExecutionException e) {
e.printStackTrace();
return "111";
}
}
}
myWebView.addJavascriptInterface(新的WebViewHandler.JavaScriptInterface(),“webCallHandler”);
公共类JavaScriptInterface
{
@JavascriptInterface
公共字符串jsToAndroidNativeFunc(字符串数据)
{
可调用任务=新的可调用任务(){
@凌驾
公共字符串调用()引发异常{
试一试{
if(Looper.getMainLooper()==Looper.myLooper())
Log.d(“标签”、“主线程”);
其他的
Log.d(“标记”,“非主线程”);
TimeUnit.SECONDS.sleep(8);//webview现在在这8秒内被卡住
返回“123”;
}
捕捉(中断异常e){
抛出新的非法状态异常(“任务中断”,e);
}
}
};
ExecutorService executor=Executors.newFixedThreadPool(1);
未来=执行者提交(任务);
试一试{
返回future.get();
}
捕捉(中断异常e){
e、 printStackTrace();
返回“111”;
}捕获(执行例外){
e、 printStackTrace();
返回“111”;
}
}
}
更新
此代码由以下javascript代码调用:
var response = webCallHandler.jsToAndroidNativeFunc(request.data);
这正是使UI冻结的原因。我们必须使用回调进行异步调用。就像Ajax一样
原始答案
我不知道js android界面。我只知道你的函数正在等待答案。也就是说,Future.get()
是一个阻塞函数。摘自:
如有必要,等待计算完成,然后检索
它的结果
我建议将此jsToAndroidNativeFunc
设置为无效,并添加一些回调。此外,我建议在方法之外定义一个执行器。例如,在课堂或应用程序级别:
public class JavaScriptInterface
{
private final ExecutorService EXECUTOR = Executors.newFixedThreadPool(1);
@JavascriptInterface
public void jsToAndroidNativeFunc(String Data, Callback callback)
// I just made up the Callback class. There must be a way to do so with webview too.
{
Callable<String> task = new Callable<String>() {
@Override
public String call() throws Exception {
try {
// ...
callback.call("123"); // no return, but call the js callback
}
catch (InterruptedException e) {
throw new IllegalStateException("task interrupted", e);
}
}
};
EXECUTOR.submit(task); // using the static executor
// no Future, no return either. Js side will execute asynchronously.
}
公共类JavaScriptInterface
{
private final EXECUTOR服务EXECUTOR=Executors.newFixedThreadPool(1);
@JavascriptInterface
public void jsToAndroidNativeFunc(字符串数据,回调)
//我刚刚创建了回调类。在webview中也必须有这样的方法。
{
可调用任务=新的可调用任务(){
@凌驾
公共字符串调用()引发异常{
试一试{
// ...
callback.call(“123”);//不返回,但调用js回调
}
捕捉(中断异常e){
抛出新的非法状态异常(“任务中断”,e);
}
}
};
提交(任务);//使用静态执行器
//没有未来,也没有返回。Js端将异步执行。
}
不幸的是,此jsToAndroidNativeFunc必须返回一个响应,并且不能无效。我注入到webview的javascript等待该响应:var response=webCallHandler.jsToAndroidNativeFunc(request.data);“
他们解决了类似的问题:Android webview+回调。另一方面,正是这些等待的js代码让你的应用程序冻结。底线:javascript是单线程的。