【问题标题】:Background thread freezes WebView后台线程冻结 WebView
【发布时间】:2017-09-01 04:58:27
【问题描述】:

我将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";
        }
    }
}

【问题讨论】:

    标签: javascript java android multithreading webview


    【解决方案1】:

    更新

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

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

    这正是导致 UI 冻结的原因,因为 javascript is single-threaded。我们必须使用回调进行异步调用。就像阿贾克斯一样。

    原答案

    我不知道js android 界面。我所知道的是您的功能正在等待答案。 IE。 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.
        }
    

    【讨论】:

    • 不幸的是,这个 jsToAndroidNativeFunc 必须返回响应并且不能为空。我注入 webview 的 javascript 等待响应:var response = webCallHandler.jsToAndroidNativeFunc(request.data);"
    • this answer 他们解决了类似的问题:Android webview + 回调。另一方面,正是这个等待的 js 代码让你的应用程序冻结。底线:javascript 是单线程的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-31
    • 2021-02-17
    • 1970-01-01
    相关资源
    最近更新 更多