Realm : Working with RealmChangeListener in Runnable

677 Views Asked by At

I'm working with Realm for my database in my Android Application. But when I try to add/remove RealmChangeListener from a Runnable I got the exception.

java.lang.IllegalStateException: You can't remove/register a listener from a non-Looper thread

It's working fine if I do not use Runnable. below are my code:

public void clearDatabase(final RealmChangeListener realmChangeListener) {
        Realm realm = RealmManager.getNewInstance().getRealm();
        realm.addChangeListener(realmChangeListener);
        realm.beginTransaction();
        realm.clear(RBooking.class);
        realm.commitTransaction();
    }

Working code:

protected void clearData() {
        mDatabaseManager.clearDataBase(new RealmChangeListener() {
            @Override
            public void onChange() {
                TLog.d("Feb 23 : Database has been clean completed!");
            }
        });
    }

EDIT : Update NOT working code:

protected void processLogout() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                Looper.prepare();

                mDatabaseManager.clearDataBase(new RealmChangeListener() {
                    @Override
                    public void onChange() {
                        TLog.d("Feb 23 : Database has been clean completed!");
                    }
                });
                Looper.loop();
            }
        };
        doTask(runnable); // excute the runnable
    }

So any body can help me to make the RealmChangeListener get correct working on Runnable. Thank you.

2

There are 2 best solutions below

5
On

Calling Looper.loop() actually blocks the thread as that line is the line that starts processing the event queue on the thread, so that is why your example doesn't work.

It is not entirely clear why you need a RealmChangeListener in this case?, but if you really need them you can use a HandlerThread: http://developer.android.com/reference/android/os/HandlerThread.html instead of a normal Thread. HandlerThread has a looper so change listeners will work on those.

0
On

Create a handler with the runnable code which you are passing currently to doTask() method. Then in your worker thread call the handler. So that that runnable executes in UI Thread.

Like :

private Handler messageHandler = new Handler() {
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        mDatabaseManager.clearDataBase(new RealmChangeListener() {
            @Override
            public void onChange() {
                TLog.d("Feb 23 : Database has been clean completed!");
            }
        });
    }
};

Then in worker thread call this handler :

new Thread() {
    public void run() {
        messageHandler.sendEmptyMessage(0);
    }
}.start();