maskarade/Android-Orma

OrmaListAdapter::notifyDatasetChanged() should update current model when DB data is updated.

Closed this issue · 8 comments

repro step

  1. Show some items with ListView in ActivityA
  2. edit some model and commit it in another ActivityB (like standard master-detail structure).
  3. Then go back to ActivityA and call notifyDataSetChanged()

expected

the updated contents is shown

actual

The old content of model remains shown.

further info

I think cache of OrmaAdapter should be invalidated when OrmaListAdapter::notifyDataSetChanged() called.
Or may be I misunderstand very basic of these classes...

here is my work around:

abstract class RelodableOrmaListAdapter<Model> extends OrmaListAdapter<Model> {
    public RelodableOrmaListAdapter(@NonNull Context context, @NonNull Relation<Model, ?> relation) {
        super(new ReloadableOrmaAdapter<Model>(context, relation));
    }

    public void reload() {
        ((ReloadableOrmaAdapter) this.delegate).clearCache();
        notifyDataSetChanged();
    }
}

public class ReloadableOrmaAdapter<Model> extends OrmaAdapter {

    public ReloadableOrmaAdapter(@NonNull Context context, @NonNull Relation relation) {
        super(context, relation);
    }

    public void clearCache() {
        cache.evictAll();
    }
}
gfx commented

Thanks to the report, but I'm not sure your details.

Do you share OrmaDatabase instance with activities? OrmaDatabase instance has an internal event stream to subscribe dataset changes, so no notifyDataSetChanged should be required when you use OrmaListAdapter.

I added some tests for this issue (#373) because it is useful enough, but the tests did not fail.

Here is my Activity.

https://github.com/karino2/MeatPieDay/blob/3a177fa925e72920a27d31347fc457b209272738/app/src/main/java/karino2/livejournal/com/meatpieday/BookActivity.java

I edit my Cell model to EditActivity too, and this is normal master-detail like structures.

I saw test a litte, but in this case, this getItem() call is the first time and this test would succeed.
If my understanding is correct, I guess when you change test to add getItem() like below,

    listAdapter.getItem(0); // <- add this line here!
   
    db.updateAuthor()
            .nameEq("A")
            .note("foo/bar/baz")
            .execute();

    assertThat(listAdapter.getItem(0).name, is("A"));
    assertThat(listAdapter.getItem(0).note, is("foo/bar/baz"));

this test would fail.
If not there is something I misunderstand.

gfx commented

It seems a nice suggestion: #374

However, the test passes because of internal query event streams.

Can you try to make it singleton? OrmaDatabase is designed as singleton.

OK, so I'm wrong in someway.
I try to make OrmaDatabase as singleton as you suggest.

gfx commented

FYI: OrmaListAdapter does not require explicit call of #notifyDataSetChanged(). If you have to call it, it might be a bug.

You are right. I confirm that when I use singleton instance, I do not need to call notifyDatasetChanged().
I couldn't understand this behavior from README and example.
Why not OrmaDatabase provide Singleton getter if user must use it?

Anyway, thank you for your support.

gfx commented

👏