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

ListModel data from JSON without .append() loop



  • Dear all,

    im getting JSON data from XMLHttpRequest(), and the data are huge.
    lets say 10000 rows (each if its own array) which I have to add into ListModel.

    so far im using:

    // Populate Model
    function populateRecordsGrouped() {
        console.log("start " + new Date().getTime());
        var array_records = httpRequest();  // this gives me array from JSON from XMLHttpRequest(), i guess no need to specify
        for (var ix = 0; ix < array_records.length; ++ix) {
            myModelGrouped.append({"serialNumber": "",
                                   "material": array_records[ix]['material'],
                                   "batch": array_records[ix]['batch'],
                                   "amount": array_records[ix]['amount'],
                                   "location": array_records[ix]['location']});
        }
        console.log("end " + new Date().getTime());
    }
    

    so is there better/faster way than looping?
    I have noticed this link:
    https://blog.felgo.com/cross-platform-app-development/avoid-cpp-models-qt
    which is using AppListView instead, where they just simply asset all data at once like:

      // on app start: fetch data from REST api
      Component.onCompleted: {
        HttpRequest.get("https://jsonplaceholder.typicode.com/todos")
        .timeout(5000)
        .then(function(res) { dataFetched(res.body) })
        .catch(function(err) { console.err("Fetch failed:"+err) });
      }
      
      // dataFetched gets called on success of http request
      function dataFetched(jsonData) {
        listView.model = jsonData // set retrieved json data as model for list
      }
      
      // list page
      NavigationStack {
        Page {
          title: "Todo List"
          
          AppListView {
            id: listView
            anchors.fill: parent
            
            delegate: SimpleRow {
              text: modelData.title
            }
          }
        }
      }
    

    so is there something I could use for ListModel the same/similar way?
    cause looping thought 10.000 records (each its own array) takes roughly 8 seconds :(



  • Is the intention to support updating the model in place? If not, a json array can be directly used as a model.

        property var jsonModel: JSON.parse('[ {"data": "one", "data2": "1"}, {"data": "two", "data2": "2"} ]')
        ListView {
            id: view
            anchors.fill: parent
            model: jsonModel
            delegate: Text {
                text: modelData.data + ":" + modelData.data2
            }
        }
    

    If the model does need to be updated in place, and using C++ instead of javascript isn't an option, the threaded ListModel example demonstrates using WorkerScript to avoid blocking the UI thread.


  • Qt Champions 2018

    If the model needs to be updated (even if not), I would advise to use https://github.com/benlau/qsyncable and its JsonListModel. It's a QAbstractListModel under the hood that calculates the diff between the new and old model and only emit the necessary signals (dataChanged, rowInserted/Removed), no complete model reset and delegate deletion/recreation.


Log in to reply