01-25-2013 07:08 AM - edited 01-25-2013 07:09 AM
Hi everyone,
I've run into a problem that I can't seem to wrap my head around. At this point, i think it's a bug. I've created a self-contained sample of the problem. You can check out the source code here: https://github.com/HorizonXP/dynamic_sheet_bug
You can download a signed BAR to your Dev Alpha here: https://s3.amazonaws.com/www.xitijpatel.com/static
What you'll see is that the QML creates a sheet via the ComponentDefinition createObject function. It connects a few signals up to it, and opens it, allowing the user to interact with it. When the user presses a button, a signal is sent that ultimately results in a SystemToast being shown.
If you left the Destroy? checkbox unchecked, you'll notice nothing wrong. However, hit the Cancel button on the sheet, and reopen the sheet, and then hit the button again, and you'll see 2 duplicate SystemToasts. If you repeat this cycle, you'll see even more SystemToasts.
If at this point, you go back to the main page and select the Destroy? checkbox, and perform one more cycle of opening the sheet, showing the SystemToast, and closing the sheet, you'll find that the QML freezes upon pressing the Button on the sheet, and the app freezes and crashes. You may see a few SystemToasts pop up.
What this demonstrates is that if you simply .close() a sheet, it's kept in memory and is still able to receive signals. If you look at the code, you'll see that explicitly disconnecting the signals does nothing.
It seems that you need to destory the sheet. However, doing so results in a crash of the app.
Looking for help, insights, and guidance here. This one's been really bugging me. Thanks!
main.qml
import bb.cascades 1.0
import "../tart.js" as Tart
NavigationPane {
id: root
signal updateLabelText(string text)
property variant settingsPage;
property variant helpPage;
property variant dynamicSheet;
property bool destroyIt: false;
Menu.definition: AppMenuDefinition {
id: appMenu
}
MainPage { id: mainPage }
attachedObjects: [
ComponentDefinition {
id: settingsDef;
source: "asset:///SettingsPage.qml"
},
ComponentDefinition {
id: helpDef;
source: "asset:///HelpPage.qml"
},
ComponentDefinition {
id: dynSheet
source: "asset:///DynSheet.qml"
}
]
onCreationCompleted: {
Tart.init(_tart, Application);
Tart.register(root);
Tart.send('uiReady');
mainPage.openDynamicSheet.connect(handleOpenNewShe et);
mainPage.changeDestroy.connect(handleChangeDestroy );
appMenu.triggerSettingsPage.connect(handleTriggerS ettingsPage);
appMenu.triggerHelpPage.connect(handleTriggerHelpP age);
}
onPopTransitionEnded: {
if (page == settingsPage) {
Application.menuEnabled = true;
settingsPage = undefined;
} else if (page == helpPage) {
Application.menuEnabled = true;
helpPage = undefined;
}
page.destroy()
}
function onMsgFromPython(data) {
updateLabelText(data.text);
}
function handleTriggerSettingsPage() {
settingsPage = settingsDef.createObject();
push(settingsPage);
}
function handleTriggerHelpPage() {
helpPage = helpDef.createObject();
push(helpPage);
}
function handleOpenNewSheet() {
dynamicSheet = dynSheet.createObject();
updateLabelText.connect(dynamicSheet.updateToastTe xt);
dynamicSheet.clicked.connect(handleSheetClicked);
dynamicSheet.closed.connect(handleSheetClosed);
dynamicSheet.open();
}
function handleSheetClicked() {
Tart.send('sendZeeMsg');
}
function handleSheetClosed() {
updateLabelText.disconnect(dynamicSheet.updateToas tText);
dynamicSheet.clicked.disconnect(handleSheetClicked );
dynamicSheet.closed.disconnect(handleSheetClosed);
if (destroyIt) {
dynamicSheet.destroy(); // This is the culprit line.
}
}
function handleChangeDestroy(checked) {
console.log("handleChangeDestroy", checked);
destroyIt = checked;
}
}
MainPage.qml
import bb.cascades 1.0
Page {
signal openDynamicSheet();
signal changeDestroy(bool checked);
Container {
layout: DockLayout {}
Container {
horizontalAlignment: HorizontalAlignment.Center
verticalAlignment: VerticalAlignment.Center
layout: StackLayout{
orientation: LayoutOrientation.TopToBottom
}
Button {
id: button
text: "Click to open sheet."
onClicked: {
openDynamicSheet();
}
}
CheckBox {
text: "Destroy?"
onCheckedChanged: {
console.log("checkbox", checked);
changeDestroy(checked);
}
}
}
}
}
DynSheet.qml
import bb.cascades 1.0
import bb.system 1.0
Sheet {
id: sheet
signal updateToastText(string text);
signal clicked();
onUpdateToastText: {
toast.body = text;
toast.show();
}
Page {
titleBar: TitleBar {
dismissAction: ActionItem {
title: "Cancel"
onTriggered: {
sheet.close();
}
}
}
Container {
layout: DockLayout {}
attachedObjects: [
SystemToast {
id: toast
}
]
Button {
text: "Send Zee Message!"
onClicked: {
sheet.clicked();
}
}
}
}
}
01-27-2013 03:12 PM
01-27-2013 04:31 PM
I always close() my sheets before destroying them
(Note that dynamically created sheets can probably be dispensed with anway, now that the Sheet bugs have been fixed)
sheet.close();
sheet.destroy();
01-27-2013 04:37 PM
01-28-2013 01:18 AM
this should work...did you try putting logs to see if the destroy() method is actually being called? it could be another code somewhere else that is crashing and hence not calling the destroy method.
destroy() works fine on sheets on the onClosed signal...i do it all the time, and works great!
i will also point out the disconnects in your closed slot, you might want to try commenting these out to see if it works. had issues with disconnecting a slot from a signal that is currently being executed before!
01-29-2013 02:27 PM
This looks like a bug. I've logged it in Issue Tracker here: Destroying dynamically created sheets not working
Thank you for providing such a detailed report!
01-29-2013 03:45 PM
Thanks Mark for logging it for me.
I'll test it out again tomorrow once we have release software, and see how it goes. I'm hoping it'll be resolved magically, but if not, I'll have to adjust how I invoke these sheets. My original hope was to invoke them dynamically to minimize memory usage. Might have to forego that.
02-17-2013 03:00 AM
has this been fixed yet in the builds
still having a problem destroy my sheets
03-27-2013 06:11 PM
04-08-2013 06:10 AM
Thanks Mark Sohm for logging this as an official bug. Does anyone know if this has been fixed?
And for those apps that need to create Sheets dynamically, is there a workaround? Or is the only available solution simply not deleting dynamically created Sheets thereby causing a memory leak?