Android / Java多线程 - 在主线程完成其工作之前线程不会继续

时间:2015-05-19 06:42:02

标签: java javascript android multithreading webview

标题可能看起来有点模糊,但我想不出另一个,所以我希望我能把问题弄清楚:

我正在使用Android WebView和JavascriptInterface。从我的应用程序(Java)到WebView(JavaScript)的通信就像这样完成:

webview.loadUrl("javascript:function()");

这是一个异步调用,之后应由JavaBridge-Thread处理。

另一种方式(Javascript to Java)可以从我的Javascript代码调用我的JavascriptInterface mainInterface。我可以在JavascriptInterface中调用用@JavascriptInterface声明的Java方法。 此调用也由JavaBridge-Thread执行。

在详细介绍之前,以下是重要的代码:

ModelActivity.java

public boolean loadPropertyIntoWebview(final String element, final String property, final String value){
    final int requestId = jsCallIndex.incrementAndGet();
    webview.loadUrl("javascript:setProperty('"+element+"', '"+property.toLowerCase()+"', '"+value+"', "+requestId+")");

    return waitForJsReturnValue(requestId, 1000);
}

private boolean waitForJsReturnValue(int index, int timeout){
    long start = System.currentTimeMillis();

    while(true){
        long elapsed = System.currentTimeMillis() - start;
        if(elapsed > timeout){
            System.out.println("JS RESPONSE TIMEOUT");
            break;
        }

        synchronized (jsReturnValueLock) {
            String value = jsReturnValues.remove(index);

            if(value != null){
                if(value.toLowerCase().equals("true")){
                    return true;
                }else{
                    System.out.println("JS BAD RESPONSE");
                    return false;
                }
            }

            long toWait = timeout - (System.currentTimeMillis() - start);
            if (toWait > 0)
                try {
                    System.out.println("WAIT NOW FOR "+toWait+" ms on index "+index);
                    jsReturnValueLock.wait(toWait);
                } catch (InterruptedException e) {
                    break;
                }
            else{
                System.out.println("JS RESPONSE TIMEOUT");
                break;
            }
        }
    }
    return false;
}

public void processJsReturnValue(int index, String value){
    System.out.println("RECEIVED ANSWER "+value+" for index "+index+" WAIT FOR UNLOCK");
    synchronized (jsReturnValueLock) {
        System.out.println("UNLOCKED FOR INDEX "+index);
        jsReturnValues.put(index, value);
        jsReturnValueLock.notifyAll();
    }
}

JavascriptInterface.java

@JavascriptInterface
public void onClick(String elementId, String property, String value){
    final String[] info = elementId.split("_");

    dbHandler.addOrUpdateOutVariable(Integer.parseInt(info[0]), Integer.parseInt(info[1]), property, value);

    ((ModelActivity)context).runOnUiThread(new Runnable() {

        @Override
        public void run() {
            actionManager.fireClickEvent(Integer.valueOf(info[0]), Integer.valueOf(info[1]));
        }
    });
}

@JavascriptInterface
public void processJsReturnValue(String index, String value){
    try{
        ((ModelActivity)context).processJsReturnValue(Integer.parseInt(index), value);
    }catch(NumberFormatException e){
        e.printStackTrace();            
    }
}

我基本上想要做的是从我的JavaScript函数setProperty()(ModelActivity - > loadPropertyIntoWebview)获取返回值。

在初始化期间,方法loadPropertyIntoWebview()从Main-Thread多次调用,并始终通过processJsReturnValue()函数从JavaBridge-Thread接收答案。

另一种不起作用的情况是用户在我的网页浏览中按下按钮,然后调用

onClick(String elementId, String property, String value)

在我的JavascriptInterface中。函数调用

actionManager.fireClickEvent(Integer.valueOf(info[0]), Integer.valueOf(info[1]));

经历了几个我无法详细解释的类和函数,但在最后一个实例中它会调用

loadPropertyIntoWebview(final String element, final String property, final String value)

这个调用也来自主线程,因为我在onClick函数中明确说过:

((ModelActivity)context).runOnUiThread(new Runnable() {

    @Override
    public void run() {
        actionManager.fireClickEvent(Integer.valueOf(info[0]), Integer.valueOf(info[1]));
    }
});

调试显示以下内容:

在启动期间和致电后

webview.loadUrl("javascript:setProperty('"+element+"', '"+property.toLowerCase()+"', '"+value+"', "+requestId+")");

JavaBridge-Thread immediatley返回processJsReturnValue()

通过用户调用时,它不会这样做。然后它将不会去那里,直到主线程完成我的timedout while(true)循环。

我希望整件事情不会太混乱,有人理解我的问题,甚至对这里出了什么问题有所了解。

1 个答案:

答案 0 :(得分:0)

尝试将onClick和processJsReturnValue分隔为两个不同的JavascriptInterface类,创建它们的实例并单独注册它们。不确定,但似乎现在他们互相阻止。