webview和Ti.App.addEventListener导致崩溃的问题

时间:2015-04-12 19:00:34

标签: android events webview titanium

请原谅这里的丑陋代码,就像我可以用来重现我的错误的实际代码的最简单版本一样。我基本上使用钛金属中的WebView打开一个本地保存的.htm文件,以便我可以利用HTML5图形功能。我在做什么工作得很好。问题是我需要将一些数据传递给htm文件,我正在按照文档推荐的那样做 - 使用Ti.App.fireEvent - 这样可以...一次。但是如果我离开窗口然后再次导航它会失败并给我一个NS_ERROR_NOT_AVAILABLE。我已经在firefox中尝试了这个代码作为Web预览,并在Android设备和模拟器上尝试了相同的问题。显然有一些问题,如果视图被回调,它没有加载相同的方式,我猜它被拉回堆栈,这是搞乱'加载'事件监听器或东西,但我不知道如何修复它。以下是我的代码的简化版本,仅用于演示此问题:

app.js

Titanium.UI.setBackgroundColor('#000');

var win = Ti.UI.createWindow({
    layout: 'vertical',
});

var wv = Ti.UI.createWebView({
    url: 'test.htm',
    height: '50%'
});

var but = Ti.UI.createButton({
    width: 100,
    height: 50,
    title: 'Press',
});

var wvopen = false;

but.addEventListener('click', function() {
    if (wvopen === false) {
        win.add(wv);
        wvopen = true;
    } else {
        win.remove(wv);
        wvopen = false;
    }

});

wv.addEventListener('load', function() {
   Ti.App.fireEvent('go'); 
});

win.add(but);
win.open();

.htm文件:

test.htm

<!doctype html>
<html>
<head>
    <title>Test</title>
</head>
<body>
    <p>A Little Test</p>
    <script>
        var Ti = window.parent.Ti;
        Ti.App.addEventListener('go', function(){
            alert(1);
        });
    </script>
</body>
</html>

2 个答案:

答案 0 :(得分:0)

试试这个,

but.addEventListener('click', function() {
   if (wvopen === false) {
      win.add(wv);
      wvopen = true;
   } else {
      win.remove(wv);
      wv.release();
      wvopen = false;
   }
});

答案 1 :(得分:0)

我最终找到了答案。它是在文档中,但实现问题实际上是什么以及它为什么会发生并不总是很简单所以我觉得值得我自己在这里回答别人使用。

关键是:

&#34;请记住,应用级事件是全局的,这意味着它们会在您的应用运行的整个过程中保持在上下文中(除非您将其删除)。这也意味着他们引用的任何对象也会在您的应用运行时保留在范围内。这可以防止这些对象被垃圾收集。有关详细信息,请参阅“管理内存和查找泄漏”一章。&#34;

~Titanium docs。

link:https://wiki.appcelerator.org/display/guides2/Event+Handling#EventHandling-Application-LevelEvents

所以基本上事件监听器即使没有加载也会存在,你试图删除它所在的上下文。因此,您必须删除事件侦听器并使保留它的视图无效。

在实践中,实施可能会有所不同,具体取决于您的具体情况,但这是我想出的。

NB ...可能有更有效的方法来执行此操作,在这种情况下请告诉我。

app.js

 /*
 * Build window and buttons
 */

var win = Ti.UI.createWindow({
    layout: 'vertical',
    backgroundColor:'black'
});


var but = Ti.UI.createButton({
    top: 20,
    width: 200,
    height: 50,
    title: 'Toggle WV',
});

var but2 = Ti.UI.createButton({
    top: 20,
    width: 200,
    height: 50,
    title: 'Fire Event'
});

var wv;
function newWv(){
    wv = Ti.UI.createWebView({
        top:20,
        right: 20,
        left: 20,
        height: '50%',
        url: 'test.htm',
    });
}

win.add(but);
win.add(but2);

/*
 * Main functionality goes here of tests goes here.
 */
var isVisible = false;


but.addEventListener('click', function() {
    if (isVisible) {
        win.remove(wv);
        Ti.App.fireEvent('close');
        wv = null;
        isVisible = false;
    } else {
        newWv();
        win.add(wv);
        isVisible = true;
    }    
});

but2.addEventListener('click', function() {
    try{
        Ti.App.fireEvent('go'); 
    } catch(e) {
        alert(e);
    }
});

win.open({modal:true});

然后在htm文件中进行了一些更改:

test.htm

<!doctype html>
<html>
<head>
    <title>Test</title>
</head>
<body>
    <p>A Little Test</p>
    <script>
        var Ti = window.parent.Ti;
        var go = function() {
            alert('called by Titanium app');
        };
        var close = function() {
            Ti.App.removeEventListener('go',go);
            Ti.App.removeEventListener('close',close);
        };
        window.addEventListener('load', function() {
            Ti.App.addEventListener('go', go);
            Ti.App.addEventListener('close', close);
        }); 

    </script>
</body>
</html>