Hi all,
I need your advice on using WebSockets from QML.
So I have made a QML client for a web site (using their JSON API, as you do).
That website has several “Rooms”, i.e. chat rooms. These support updates and sending of messages using a WebSocket.
My application starts up, and loads a summary information via XHR, lets say a “Lobby”.
The Lobby data consists of a list of the rooms, which has things like
- room UUID
- room display name
- room URI
- room latest message
I load and display this, and allow the user to click on any “room summary” to open the chat proper. This will push a new Page onto the stack.
I can now use the UUID and URI properties to open a WebSocket, which will receive any new messages.
The user may navigate back into the Lobby at any time, and I would like to keep the socket active so I can alert the user when new messages arrive.
Questions:
- If a Websocket is created in RoomPage.qml, it will be destroyed when that page is popped form the stack, correct?
- If I instantiate the WebSocket in LobbyPage, and hand over the object as a property to RoomPage, will it survive the navigation back? (See example below)?
- As the room summary is element of a ListView, I run the risk of it being destroyed along with the WebSocket, when scrolled out of view, correct? Could this be avoided?
- Are there any considerations wrt. opening potentially many Websockets (it will be 5-10, hot hundreds) in parallel?
- Would you use a completely different design? Please share your idea.
So this would be my plan at the moment:
LobbyPage
Page { id: lobby
ListModel { id: roomsModel }
ListView {
model: roomsModel
delegate: Item { id: roomSummary
Label { text: roomName; text.bold: true }
Label { text: lastMessage }
WebSocket { id: socket }
onClicked: pageStack.push("RoomPage.qml", { "socket": socket, "uuid": uuid } )
}
}
}
RoomPage
Page { id: room
property string uuid
property WebSocket socket
component.onCompleted: {
ws.url = "wss://example.org/socket" + "/" + room.uuid
ws.active = true
}
Connections {
target: socket
onTextMessageReceived: function(msg) {
messagesModel.push ({ "author": msg.user, "message": msg.text })
}
}
ListModel { id: messagesModel }
ListView {
model: messagesModel
delegate: ChatBubble { user: author; text: message }
}
}
I actually have a working implementation of this app, but that one uses a WebSocket as a singleton, and can therefore only monitor one chat room at a time, not several. I want to improve on this.
Thanks for any comments.