后台线程冻结了WebView

时间:2017-04-06 09:01:46

标签: javascript java android multithreading webview

我将JavaScript接口注入我的WebView,一旦我找到我在JavaScript中定义的原生方法,如果冻结了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";
        }
    }
}

1 个答案:

答案 0 :(得分:0)

更新

使用以下javascript代码调用此代码:

var response = webCallHandler.jsToAndroidNativeFunc(request.data);

这正是因为javascript is single-threaded而导致用户界面冻结的原因。我们必须使用回调进行异步调用。就像Ajax一样。

原始答案

我不知道js android界面。我所知道的是你的功能正在等待答案。即Future.get()是阻止功能。摘录自API

  

如果需要等待计算完成,然后检索   结果。

我建议将此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.
    }