Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Loading QAbstractListModel takes too long



  • I have a QML view that loads a ListView with a lot of components. Each Item in the view has several rectangles, texts, and other ListView's as children.

    The data comes from a model that inherits from QAbstractListModel. I have a refresh() methods that does:

    • beginResetModel()
    • //update all model data
    • endResetModel()

    This works fine, but the problem is that depending on the number of items I have, it can take too long to load the view.

    Would it be possible to load model data partially? Or how can I display the view with just a few items loaded while the rest (the ones that are not still visible) are loading?

    Since the view has a scrollbar, it would be great to load just the visible items first.


  • Moderators

    @Adso4 IIRC ListVIew should do that already in advance (Loading only what you see), but just in case:

    Move your delegate in its own QML file, make a loader your delegate, set it to active, if the current index is equal to the index +- N(depending on how many you want to show at once


  • Qt Champions 2018

    @J-Hilk said in Loading QAbstractListModel takes too long:

    @Adso4 IIRC ListVIew should do that already in advance (Loading only what you see), but just in case:

    Move your delegate in its own QML file, make a loader your delegate, set it to active, if the current index is equal to the index +- N(depending on how many you want to show at once

    Better yet, don't try a sketchy workaround and figure out if the ListView behaves as it should (make sure not all delegates are created by monitoring listView.contentItem.chlildren.length), and if not, determine why.

    How do you set the dimension of your ListView?
    anchors.fill: parent, using a layout, height: count * delegateHeight, ...?



  • The listView in placed inside an item and it gets its parent size. The model comes from an implementation of QAbstractListModel and the delegate is a separate QML component.

    Probably I didn't explain myself properly. The problem is not in the model refresh (which updates the data between begin and end resteModel). This is done quite fast. The issues come when drawing the list. Is there when it needs several seconds to be displayed. But once the listView is displayed, it behaves correctly.


  • Qt Champions 2018

    @Adso4 said in Loading QAbstractListModel takes too long:

    Probably I didn't explain myself properly. The problem is not in the model refresh (which updates the data between begin and end resteModel). This is done quite fast. The issues come when drawing the list. Is there when it needs several seconds to be displayed. But once the listView is displayed, it behaves correctly.

    I understood that correctly, I believe it's because your ListView instantiates too much delegates.

    As always, try to provide a minimal reproducible example of your problem. We can't help much more without it, and it'll also help you better figure out the issue.

    Have you checked the number of delegates created like I mentioned ?



  • In my case ( the software run on ARM A7 454MHz MCU),The Listview refresh data take about 1s.

    beginResetModel() and endResetModel() will load all of the data and reset the listvew. It take more time. so I use like below:

        QModelIndex topLeft = createIndex(0, 0);
        QModelIndex bottomRight = createIndex(rows, 1);
        emit dataChanged(topLeft, bottomRight);
    

    emit dataChanged signal can refresh what's the datas u want.



  • As mentioned in previous post, the root of the issue is likely to be that you are resetting the entire model. As mentioned, if data in an existing element changes, then emit dataChanged but also look at begin/endInsertRows and begin/endRemoveRows to notify of structural changes to your data. Rule of thumb is always to update incrementally wherever possible and avoid full resets except for the probably limited cases where you are genuinely reinitialising your model.



  • In my case, I just need to reset the entire model. Once it is loaded, there won't be any insert or update. I need to speed up the model refresh. This is my pseudo-code:

    **MainModel.cpp**
    
    MainModel::refresh() {
        listViewModel_1->refresh()
        emit changed();
    }
    
    **ListViewModel_1.cpp (inherits from QAbstractListModel)**
    
    ListViewModel_1::refresh() {
        beginResetModel();
        newItems = updateNewItems(); // add items to ListViewModel_2. Each item on m_items has a ListViewModel_2 object (childs)
        m_items.clear();
        for (item in newItems) {
            m_items.push_back(item)
        }
        endResetModel();
    }
    
    **ListViewModel_2.cpp (inherits from QAbstractListModel)**
    
    ListViewModel_2::addNewItem(newItem) {
        beginInsertRows(QModelIndex(), rowCount(), rowCount());
        m_childs.push_back(model);
        endInsertRows();
    }
    

    Should I use begin/endInserRow instead of begin/EndResetModel()? Any other suggestion?


Log in to reply