Daniel Argüelles
Daniel Argüelles

Reputation: 2349

RealmChangeListener not called

I'm trying to have a listview linked with a Realm table, so when a item is added to the table, the listview should be updated. The problem is that RealmChangeListener is not called when the item is added.

Realm real = RealmController.getInstance(getContext()); // Singleton
RealmResults<Friend> friends = real.where(Friend.class).findAllAsync();
friends.addChangeListener(callback);

RealmChangeListener<RealmResults<Friend>> callback=new RealmChangeListener<RealmResults<Friend>>() {
    @Override
    public void onChange(RealmResults<Friend> element) {
        // This is only called on async completed but not later
    }
};

The saving process is done in a retrotif response:

    new MyService(context).userService().getFriends().enqueue(new Callback<FriendResponse>() {
        @Override
        public void onResponse(Call<FriendResponse> call, Response<FriendResponse> response) {
            Realm realm = RealmController.getInstance(context); // singleton
            realm.beginTransaction();
            realm.copyToRealmOrUpdate(response.body().friends);
            realm.commitTransaction();
        }

        @Override
        public void onFailure(Call<AllInfoResponse> call, Throwable t) {

        }
    });

Do you know what is happening? Any suggestion?

Upvotes: 3

Views: 724

Answers (1)

josemigallas
josemigallas

Reputation: 3909

I have experienced some issues with your exact situation (Retrofit call and UI refreshed via RealmChangeListener) and I was about to post a new question but I just figured it out.

In my case, I implemented the RealmChangeListener inside my ArrayAdapter, which I find cleaner:

public class ListAdapter extends ArrayAdapter<Item> implements
        RealmChangeListener<RealmResults<Item>> {

    private final List<Item> items;

    public ListAdapter(Context context, RealmResults<Item> items) {
        super(context, R.layout.listitem_item);
        this.items = items;
        items.addChangeListener(this);
    }

    @Override
    public void onChange(RealmResults<Restaurant> element) {
        notifyDataSetChanged();
    }

    ...
}

In another situation, I was initialising the views and calling my Retrofit service in the activity's onCreate and somehow the listener was not being attached before receiving the response. So, another thing I did was calling Retrofit in the onPostCreate method, ensuring the listener is ready.

public class ItemListActivity BaseActivity implements
        RealmChangeListener<RealmResults<Item>>,
        Callback<GetItemsResponse> {

    private long id;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_item_list);

        RealmResults<Item> items = getRealm()
                .where(Item.class)
                .findAll();

        items.addChangeListener(this);

        setupUI(items);
    }

    @Override
    protected void onPostCreate(@Nullable Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);

        MyRetrofitClient
                .getInstance(this)
                .getItems()
                .enqueue(this);
    }

    @Override
    public void onResponse(Call<GetItemsResponse> call, final Response<GetItemsResponse> response) {
        getRealm().executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                List<Item> newItems = response.body().getNewItems();
                realm.copyToRealmOrUpdate(newItems);
            }
        });
    }

    @Override
    public void onChange(RealmResults<Item> items) {
        updateUI();
    }

    ...
}

Hope any of this helps!

Upvotes: 1

Related Questions