Content flash when updating lists

Hi all. I haven’t built a standalone example of this problem, but in Ionic1 if you had a list that was based on a variable and you updated the variable with a new copy of the list, the whole list wouldn’t flash and images wouldn’t disappear and reappear, etc. In Ionic2, it seems when you update a list, it re-renders everything and the user sees that happen. Maybe Ionic1 did re-render everything but somehow it didn’t cause a flash. Here’s a rough example:

list = [ { id: 1, name: 'Item 1', image: 'img/1.png'},
         { id: 2, name: 'Item 2', image: 'img/2.png'}];

Displayed like so:

<ion-item *ngFor="let item of list">
  <ion-avatar item-left><img [src]="item.image" width="40" height="40" /></ion-avatar>
  <b>{{item.name}}</b>
</ion-item>

Then later an updated version of the list comes in and you replace the variable

httpCtrl.get('/list/update').subscribe(data => {
  this.list = data;
}, err => {});

So in Ionic2 all the items flash when the list is updated. If I switch the list to use BehaviorSubjects for each item, then the text doesn’t flash but the images still do.

Is there another way I’m not thinking of other than iterating the list and specifically updating only the part that changed? Like so (haven’t checked if this even works):

httpCtrl.get('/list/update').subscribe(data => {
  for (var i = 0; i < data.length; i++) {
    if (this.list[i].image != data[i].image) this.list[i].image = data[i].image;
  }
}, err => {});

I would prefer not to do that because there are so many places in the app where a list could need to get updated based on an event. The app gets alerted by the server whenever another user has updated something that the current user is looking at, and the current user grabs a new copy of it.

Would be better if Ionic could compare the previous list and the new list and update what changed. Item was added, add an item. Item changed, change just the elements that changed…

Hi Jelliben,

In Ionic 2 what you describe is called a subscribe event on a method.
Globally through Angular 2 the code can now “more or less” see what’s updated in real time.
So injectable or observable is way more efficient than Ionic 1.

In Ionic 2 a list can be dynamically changed with this RxJS technology, observables and injectables.
And even better with databases record.

Hope it helps,

I tried displaying the observable directly, but then how do I manually cause the observable to reload the http request when I know there is an updated version of the list waiting on the server? I could only get it to display the first load, then basically I would be replacing the observable itself with a new observable. Ideally yeah, originally I was trying to use the Observable method, I just don’t see how to re-play it, seemed like one-and-done. The observable originated from @angular/http…

Well it is a bit above my skills with http api, but clearly there is a way to do it.
You would need to make your own listeners of http, then watch for changes in a remote data source.

The next part is to dynamically recall the data once a change is made, there are tutorials about that, it’s ok to get the data in general but harder to reload it dynamically, i have troubles with that too not on the data side, but the display side (recall a remote array on page with ng events on ion-list for example).

On the clues I think of, the new subscribe item next, is supposed to anwser an array of all data in collection, in ionicDB for example. And can be combined with a watch (event).

If you have clues please share,

Regards,

The accepted answer is basically what I’m doing but using BehaviorSubject instead of regular Subject and each xyz.next(value) replaces the whole list with a new version. But it still flashes the images…

Ok, I figured out the images flashing. It’s because ionic serve sends a no-cache header even on images. If the images are served within a real app or from Apache, they don’t flash when the list is updated.

However, the list is still being re-processed, it’s not just updating what changed. If an item in the list is based on a random result, the result changes every time there is a change in the list… This is not great for ads where we have an ad service that provides a random ad based on the interests of the user. Every time the list changes, the ads jump around… Have to change how the random thing works so it’s the same random every time.

I had the same flicker/flash problem with images and the same ponder about how to address… I fixed it by turning off automated change detection and moving it to manual mode

Turn off (can be done page by page)

changeDetection: ChangeDetectionStrategy.OnPush

When I want to rerun change detection, which I do when I know that the final (new) data is all there

this.ref.markForCheck();

Docs
https://angular.io/docs/js/latest/api/core/index/ChangeDetectorRef-class.html

FYI if you have a pull to refresh on the same page, the above slightly breaks it. You need to do something like this to make the pull to refresh icon animate again!

Template

(ionPull)=“checkChangeDetection($event)”

Code

  checkChangeDetection(refresher)
  {
    if (refresher.progress > 0.2)
    {
      this.ref.markForCheck();
    }
  }

No doubt there is a much more advanced, proper, way of solving this, but this is what I could work out based on my limited knowledge of non angular 2 specific concepts…

Thanks for the suggestion! It still feels like something is going to flash but for now it’s calmed down for the most part if I serve the images with a cache header or from a local file on the device.