Szymon Rozga
Szymon Rozga

Reputation: 18178

WinJS IListDataAdapter getting called in a loop

I have implemented a IListDataAdapter (using VirtualizedDataSource) that populates objects from an asynchronous WinRT source. It almost works as expected. I set up a ListView with incremental load form my data source. It appears the itemsFromIndex() method gets called repeatedly by the WinJS libraries in some kind of infinite loop.

I simplified my data adapter so that it contains a reference to a populated list (to make sure my async calls were not creating a problem). As I scroll horizontally, the list view tries to populate itself, but many times, it just ends up going into some infinite loop internally.

As I scroll the list view, it starts loading item templates. It doesn't bind them. How do I know it is in a loop? Breakpoints and that console.log below. It just keep on going using up my processor like crazy. Does anyone know what's going on here?

Here is the code for my itemsFromIndex. Nothing special.

itemsFromIndex: function (requestIndex, countBefore, countAfter) {

    var length = this._isupportincrementalloadcollection.size;

    if (requestIndex >= length) {
        return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.doesNotExist));
    }

    var start = Math.max(requestIndex - countBefore, 0);
    var end = Math.min(requestIndex + countAfter, length - 1);

    var items = [];
    for (var i = start; i <= end; i++) {
        var item = this._itemFromIndex(i);
        items.push(item);
    }

    console.log("returning");
    return WinJS.Promise.wrap({
        absoluteIndex: requestIndex,
        atEnd: end === length - 1,
        atStart: start === 0,
        items: items,
        offset: requestIndex - start,
        totalCount: length
    });
}

My ListView is set up with the following options:

loadingBehavior: 'incremental', 
pagesToLoad: 4, 
automaticallyLoadPages: true, 
pagesToLoadThreshold: 1,

Upvotes: 1

Views: 673

Answers (2)

ninjascript
ninjascript

Reputation: 1751

I meant to add this as a comment to the original answer, but it's just too much to format correctly. Anyway, I ran into this today and wanted to clarify a bit:

IIListDataAdapter.itemsFromIndex() must return a Promise which itself returns an IFetchResult:

IFetchResult = {
    items: [Array],
    offset: [int],
    totalCount: [int]
};

IFetchResult.items must be an array of IItem objects:

IItem = {
    key: [string],
    data: [Object]
};

The key property doesn't need to be unique, it just needs to be a stringified version of the item's index (ie. 42.toString();).

The tutorial on MSDN doesn't really do a good job of making the necessary ingredients clear, but I found that scenario 4 in their sample source does.

Give it a shot: http://code.msdn.microsoft.com/windowsapps/ListView-custom-data-4dcfb128

Upvotes: 2

Szymon Rozga
Szymon Rozga

Reputation: 18178

Turns out the adapter was perfectly fine, the problem was the keys. IListDataAdapter expects that the data returned is a object that contains a key for the object and the object itself. The key has to be a unique string. If the key is anything but a string bad things happen. If the key is not unique bad things happen. In the code above, you can't see where the key was used but I had a key mapping function I was using.

Upvotes: 2

Related Questions