[Interest] Managing memory with QObject*-models exposed to QML

Ben Lau xbenlau at gmail.com
Fri Jul 15 19:32:10 CEST 2016


Hi,

In my humble opinion, QObjectListModel is a bad idea. Because it is
difficult to manage the life cycle of QObject with QML. Just like your
problem. I have met the similar issue in my first QML project. The
application always crashes. The pattern is purely random. I wasted a lot of
time to discover the root cause.

Moreover, I am doubt to use a list of QObject as a data storage class.
Since QObject is not copyable, it must use a pointer to share QObject to
multiple classes. Extra care is needed to manage its life cycle. And they
are not able to be passed to another thread for processing directly.
Therefore, I always prefer an implicitly shared class over a list of
QObject as data storage. It is copyable and thread safe (using a worker
model).

Instead, I use another approach for sharing data between C++ and QML. I
just hold a QList<T> (T is an implicitly shared class) as the central data
storage in memory. Whatever it is changed, it will update a
QVariabtListModel to inform QML to render the content. However, QML/JS do
not write to the model directly. Instead, it will ask another C++ object to
update the central data. (e.g by context object / messaging system)

In order to simplify the process to update the QVariantListModel, I have
written a library called QSyncable. It have document and example code to
demonstrate how this approach works.

https://github.com/benlau/qsyncable



On 14 July 2016 at 17:02, Ola Røer Thorsen <ola at silentwings.no> wrote:

> I've found that creating C++ models containing a list of QObject* based on
> QAbstractListModels and using them in Quick views such as ListView is very
> useful. I'm not the only one, there are several implementations of
> "QObjectListModel" around, and I've got my own as well.
>
> On quite rare ocations I have had crashes deep inside the QML engine
> itself, that are very hard to reproduce, when rapidly adding and removing +
> deleting objects in the model from C++. I think this probably has to do
> with the Quick view's delegate that might still be using an Object that was
> just deleted.
>
> I've made sure that all objects put into the list model are created in C++
> and they do have a parent to avoid qml taking ownership of them. When
> removing from a model, they are first removed  (beginRemoveRows, remove
> from array, endRemoveRows), then finally deleted using
> object->deleteLater().
>
> My worry here is that deleteLater() is sometimes still too soon for the
> QML engine to keep up, especially when there is a lot of things going on in
> the Quick scene.
>
> Could this be the case? If so, what is the rock-solid way to do this?
>
> One ugly "fix" that I would like to avoid is to put the objects in some
> queue and delete them after a given "safe time duration", like
> "deleteMuchLater()".
>
> Another way idea that I have not tried is to use QSharedPointer, and
> expose some wrapper Q_GADGET-based type to QML that contains this pointer
> with some raw pointer property, but this introduces shared pointers to my
> C++ application and changes a lot of other things.
>
> I'd appreciate any input on if this is a real problem to begin with, and
> if so, how to work around it.
>
> Thanks,
> Ola
>
>
>
>
>
>
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20160716/905e8735/attachment.html>


More information about the Interest mailing list