Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/473.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
Android中的JavascriptInterface';s WebView:对JS的多次调用导致死锁_Javascript_Android_Webview - Fatal编程技术网

Android中的JavascriptInterface';s WebView:对JS的多次调用导致死锁

Android中的JavascriptInterface';s WebView:对JS的多次调用导致死锁,javascript,android,webview,Javascript,Android,Webview,这是我使用的全部Java代码。我将在下面更详细地解释 public class Test7 extends Activity { //debug private final static String TAG = "JSInterface"; private WebView wv; private class JSInterface { private WebView wv; // Variables to manage in

这是我使用的全部Java代码。我将在下面更详细地解释

public class Test7 extends Activity {
    //debug
    private final static String TAG = "JSInterface";

    private WebView wv;

    private class JSInterface {
        private WebView wv;

        // Variables to manage interfacing with JS
        private String returnValue;
        private boolean canReadReturnValue;
        private Lock lockOnJS;
        private Condition condVarOnJS;

        public JSInterface (WebView wv) {
            this.wv = wv;       
            this.canReadReturnValue = false;
            this.lockOnJS = new ReentrantLock();
            this.condVarOnJS = lockOnJS.newCondition();
        }

        public void setReturnValue(String ret) {
            lockOnJS.lock();
            returnValue = ret;
            canReadReturnValue = true;
            condVarOnJS.signal();
            lockOnJS.unlock();
            Log.d(TAG, "returnValue = " + returnValue);
        }

        public String getReturnValue() {
            Log.d(TAG, "enter in getReturnValue");
            lockOnJS.lock();
            while (!canReadReturnValue) {
                try {
                    Log.d(TAG, "get wait...");
                    condVarOnJS.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            lockOnJS.unlock();
            Log.d(TAG, "returnValue: " + returnValue);
            return returnValue;
        }

        public String getNewString() {
            wv.loadUrl("javascript:JSInterface.setReturnValue(createNewString())");         
            return getReturnValue();
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        wv = (WebView) findViewById(R.id.webView1);
        wv.getSettings().setJavaScriptEnabled(true);
        wv.addJavascriptInterface(new JSInterface(wv), "JSInterface");
        wv.loadUrl("file:///android_asset/prova7.html");
    }

    public void button1(View v) {
        wv.loadUrl("javascript:func('1')");
    }
}
而且看起来效果不错

你可以看到我有一个按钮(我们可以称之为button1),点击它,它试图执行一个JS方法,名为func()

public void button1(View v) {
    wv.loadUrl("javascript:func('1')");
}
在这个JS方法中,我必须调用另一个Java方法。代码如下:

function func(id) {
    document.getElementById(id).innerHTML = JSInterface.getNewString();
}
function createNewString() {
    return "my New String";
}
我需要将JSInterface.getNewString()的结果返回给innerHTML变量

JSInterface.getNewString()的代码如下:

public String getNewString() {
    wv.loadUrl("javascript:JSInterface.setReturnValue(createNewString())");         
    return getReturnValue();
}
您可以看到,我使用方法
setReturnValue
getReturnValue
返回另一个JS方法返回的值。代码如下:

function func(id) {
    document.getElementById(id).innerHTML = JSInterface.getNewString();
}
function createNewString() {
    return "my New String";
}
问题是,当我试图设置returnValue时,函数createNewString从未执行过!如果我添加一个console.log()行,我的logCat将不显示任何内容


我不明白为什么会发生这种情况。

在Internet Explorer中,我发现了同样的问题。您可以像这样使用setTimeout:

function func(id) {
    setTimeout(
        function(){
            document.getElementById(id).innerHTML = JSInterface.getNewString();
        }, 
        500);
} 

我在代码中实现了您想要的功能,对我来说,createNewString()被调用

我将显示我使用的代码

在爪哇 ,

在HTML中

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
   <script>
function inform(){
    alert('et');

   document.getElementById('myText').value=window.demo.videoPlay();
   alert('et');
 }
function createNewString() {
    return "my New String";
}
</script>
</head>
<body onload="init()">
<form>
<input type='text' id='myText' />
<input type="button" name="test" value="Click me" onclick="inform()">
</form>
</body>
</html> 
videoPlay从JS调用,createnewString()也从java调用到JS,但它会在设置之前返回值,因为我不知道使用lock的目的是什么,甚至我尝试过使用lock,就像你那样,它会打印出来

 11-08 19:18:17.155: INFO/System.out(847): videoPlay
    11-08 19:18:17.165: INFO/System.out(847): getnull

使用lock函数回调也会以错误的方式工作,您需要处理锁

所有javascript和从javascript调用的JSInterface方法都在Android
WebView
中的单个线程上运行。因此,当您在
condVarOnJS.await()中等待时,不能执行任何javascript,因为它是在同一个线程上执行的

此外,应用程序中的所有webview实例共享相同的javascript线程