Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/404.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 后台线程冻结WebView_Javascript_Java_Android_Multithreading_Webview - Fatal编程技术网

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是单线程的。