Example usage for android.os HandlerThread quit

List of usage examples for android.os HandlerThread quit

Introduction

In this page you can find the example usage for android.os HandlerThread quit.

Prototype

public boolean quit() 

Source Link

Document

Quits the handler thread's looper.

Usage

From source file:Main.java

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public static void quitSafely(HandlerThread handlerThread) {
    if (handlerThread == null) {
        return;/*from  w w w  .  ja v  a  2 s .c om*/
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
        handlerThread.quitSafely();
    } else {
        handlerThread.quit();
    }
}

From source file:com.kogitune.launcher3.LauncherAppWidgetHostView.java

@Override
public void updateAppWidget(RemoteViews remoteViews) {
    if (EXPERIMENTAL) {
        if (remoteViews != null) {
            Handler mH = null;//  w w  w. j  a v a 2  s.  c  o  m
            Field queueField = null;
            MessageQueue messageQueue = null;
            try {
                Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
                Class[] params = new Class[0];
                Method currentActivityThread = activityThreadClass.getDeclaredMethod("currentActivityThread",
                        params);
                Boolean accessible = currentActivityThread.isAccessible();
                currentActivityThread.setAccessible(true);
                Object obj = currentActivityThread.invoke(activityThreadClass);
                if (obj == null) {
                    Log.d("ERROR", "The current activity thread is null!");
                }
                currentActivityThread.setAccessible(accessible);

                Field mHField = activityThreadClass.getDeclaredField("mH");
                mHField.setAccessible(true);
                mH = (Handler) mHField.get(obj);
                queueField = Handler.class.getDeclaredField("mQueue");
                queueField.setAccessible(true);
                messageQueue = (MessageQueue) queueField.get(mH);

                HandlerThread handlerThread = new HandlerThread("other");
                handlerThread.start();
                handlerThread.quit();
                queueField.set(mH, null);

            } catch (Exception e) {
                Log.d("ERROR", Log.getStackTraceString(e));
            }
            Context context = getContext().getApplicationContext();
            NotificationManager notificationManager = (NotificationManager) context.getApplicationContext()
                    .getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
            builder.setContent(remoteViews).setSmallIcon(R.drawable.ic_launcher_info_normal_holo)
                    .setContentTitle("My notification") // ?
                    .setContentText("Hello Notification!!"); // ?

            Notification notification = builder.build();
            notificationManager.notify(getAppWidgetId(), notification);

            final Field finalQueueField = queueField;
            final Handler finalMH = mH;
            final MessageQueue finalMessageQueue = messageQueue;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(50L);
                        if (finalMessageQueue != null)
                            finalQueueField.set(finalMH, finalMessageQueue);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();

        }
    }
    // Store the orientation in which the widget was inflated
    mPreviousOrientation = mContext.getResources().getConfiguration().orientation;
    super.updateAppWidget(remoteViews);
}

From source file:org.ymkm.lib.controller.support.ControlledDialogFragment.java

@Override
public void onDestroy() {
    super.onDestroy();
    synchronized (this) {
        mHandler.removeCallbacksAndMessages(null);
        if (null != _handlerThread) {
            HandlerThread ht = _handlerThread;
            _handlerThread = null;/*from  w ww .  j a  va 2 s .  co  m*/
            ht.quit();
            ht.interrupt();
        }
        mHandler = null;
        mControllerMessenger = null;
    }
}

From source file:im.vector.activity.RoomActivity.java

/**
 * Send a list of images from their URIs
 * @param mediaUris the media URIs/*from  ww  w .  ja v a  2 s  .c om*/
 */
private void sendMedias(final ArrayList<Uri> mediaUris) {

    final View progressBackground = findViewById(R.id.medias_processing_progress_background);
    final View progress = findViewById(R.id.medias_processing_progress);

    progressBackground.setVisibility(View.VISIBLE);
    progress.setVisibility(View.VISIBLE);

    final HandlerThread handlerThread = new HandlerThread("MediasEncodingThread");
    handlerThread.start();

    final android.os.Handler handler = new android.os.Handler(handlerThread.getLooper());

    Runnable r = new Runnable() {
        @Override
        public void run() {
            handler.post(new Runnable() {
                public void run() {
                    final int mediaCount = mediaUris.size();

                    for (Uri anUri : mediaUris) {
                        // crash from Google Analytics : null URI on a nexus 5
                        if (null != anUri) {
                            final Uri mediaUri = anUri;
                            String filename = null;

                            if (mediaUri.toString().startsWith("content://")) {
                                Cursor cursor = null;
                                try {
                                    cursor = RoomActivity.this.getContentResolver().query(mediaUri, null, null,
                                            null, null);
                                    if (cursor != null && cursor.moveToFirst()) {
                                        filename = cursor
                                                .getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                                    }
                                } catch (Exception e) {
                                    Log.e(LOG_TAG, "cursor.getString " + e.getMessage());
                                } finally {
                                    cursor.close();
                                }

                                if (TextUtils.isEmpty(filename)) {
                                    List uriPath = mediaUri.getPathSegments();
                                    filename = (String) uriPath.get(uriPath.size() - 1);
                                }
                            } else if (mediaUri.toString().startsWith("file://")) {
                                // try to retrieve the filename from the file url.
                                try {
                                    filename = anUri.getLastPathSegment();
                                } catch (Exception e) {
                                }

                                if (TextUtils.isEmpty(filename)) {
                                    filename = null;
                                }
                            }

                            final String fFilename = filename;

                            ResourceUtils.Resource resource = ResourceUtils.openResource(RoomActivity.this,
                                    mediaUri);

                            if (null == resource) {
                                RoomActivity.this.runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        handlerThread.quit();
                                        progressBackground.setVisibility(View.GONE);
                                        progress.setVisibility(View.GONE);

                                        Toast.makeText(RoomActivity.this,
                                                getString(R.string.message_failed_to_upload), Toast.LENGTH_LONG)
                                                .show();
                                    }

                                    ;
                                });

                                return;
                            }

                            // save the file in the filesystem
                            String mediaUrl = mMediasCache.saveMedia(resource.contentStream, null,
                                    resource.mimeType);
                            String mimeType = resource.mimeType;
                            Boolean isManaged = false;

                            if ((null != resource.mimeType) && resource.mimeType.startsWith("image/")) {
                                // manage except if there is an error
                                isManaged = true;

                                // try to retrieve the gallery thumbnail
                                // if the image comes from the gallery..
                                Bitmap thumbnailBitmap = null;

                                try {
                                    ContentResolver resolver = getContentResolver();

                                    List uriPath = mediaUri.getPathSegments();
                                    long imageId = -1;
                                    String lastSegment = (String) uriPath.get(uriPath.size() - 1);

                                    // > Kitkat
                                    if (lastSegment.startsWith("image:")) {
                                        lastSegment = lastSegment.substring("image:".length());
                                    }

                                    imageId = Long.parseLong(lastSegment);

                                    thumbnailBitmap = MediaStore.Images.Thumbnails.getThumbnail(resolver,
                                            imageId, MediaStore.Images.Thumbnails.MINI_KIND, null);
                                } catch (Exception e) {
                                    Log.e(LOG_TAG,
                                            "MediaStore.Images.Thumbnails.getThumbnail " + e.getMessage());
                                }

                                double thumbnailWidth = mConsoleMessageListFragment.getMaxThumbnailWith();
                                double thumbnailHeight = mConsoleMessageListFragment.getMaxThumbnailHeight();

                                // no thumbnail has been found or the mimetype is unknown
                                if ((null == thumbnailBitmap) || (thumbnailBitmap.getHeight() > thumbnailHeight)
                                        || (thumbnailBitmap.getWidth() > thumbnailWidth)) {
                                    // need to decompress the high res image
                                    BitmapFactory.Options options = new BitmapFactory.Options();
                                    options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                                    resource = ResourceUtils.openResource(RoomActivity.this, mediaUri);

                                    // get the full size bitmap
                                    Bitmap fullSizeBitmap = null;

                                    if (null == thumbnailBitmap) {
                                        fullSizeBitmap = BitmapFactory.decodeStream(resource.contentStream,
                                                null, options);
                                    }

                                    if ((fullSizeBitmap != null) || (thumbnailBitmap != null)) {
                                        double imageWidth;
                                        double imageHeight;

                                        if (null == thumbnailBitmap) {
                                            imageWidth = fullSizeBitmap.getWidth();
                                            imageHeight = fullSizeBitmap.getHeight();
                                        } else {
                                            imageWidth = thumbnailBitmap.getWidth();
                                            imageHeight = thumbnailBitmap.getHeight();
                                        }

                                        if (imageWidth > imageHeight) {
                                            thumbnailHeight = thumbnailWidth * imageHeight / imageWidth;
                                        } else {
                                            thumbnailWidth = thumbnailHeight * imageWidth / imageHeight;
                                        }

                                        try {
                                            thumbnailBitmap = Bitmap.createScaledBitmap(
                                                    (null == fullSizeBitmap) ? thumbnailBitmap : fullSizeBitmap,
                                                    (int) thumbnailWidth, (int) thumbnailHeight, false);
                                        } catch (OutOfMemoryError ex) {
                                            Log.e(LOG_TAG, "Bitmap.createScaledBitmap " + ex.getMessage());
                                        }
                                    }

                                    // the valid mimetype is not provided
                                    if ("image/*".equals(mimeType)) {
                                        // make a jpg snapshot.
                                        mimeType = null;
                                    }

                                    // unknown mimetype
                                    if ((null == mimeType) || (mimeType.startsWith("image/"))) {
                                        try {
                                            // try again
                                            if (null == fullSizeBitmap) {
                                                System.gc();
                                                fullSizeBitmap = BitmapFactory
                                                        .decodeStream(resource.contentStream, null, options);
                                            }

                                            if (null != fullSizeBitmap) {
                                                Uri uri = Uri.parse(mediaUrl);

                                                if (null == mimeType) {
                                                    // the images are save in jpeg format
                                                    mimeType = "image/jpeg";
                                                }

                                                resource.contentStream.close();
                                                resource = ResourceUtils.openResource(RoomActivity.this,
                                                        mediaUri);

                                                try {
                                                    mMediasCache.saveMedia(resource.contentStream,
                                                            uri.getPath(), mimeType);
                                                } catch (OutOfMemoryError ex) {
                                                    Log.e(LOG_TAG, "mMediasCache.saveMedia" + ex.getMessage());
                                                }

                                            } else {
                                                isManaged = false;
                                            }

                                            resource.contentStream.close();

                                        } catch (Exception e) {
                                            isManaged = false;
                                            Log.e(LOG_TAG, "sendMedias " + e.getMessage());
                                        }
                                    }

                                    // reduce the memory consumption
                                    if (null != fullSizeBitmap) {
                                        fullSizeBitmap.recycle();
                                        System.gc();
                                    }
                                }

                                String thumbnailURL = mMediasCache.saveBitmap(thumbnailBitmap, null);

                                if (null != thumbnailBitmap) {
                                    thumbnailBitmap.recycle();
                                }

                                //
                                if (("image/jpg".equals(mimeType) || "image/jpeg".equals(mimeType))
                                        && (null != mediaUrl)) {

                                    Uri imageUri = Uri.parse(mediaUrl);
                                    // get the exif rotation angle
                                    final int rotationAngle = ImageUtils
                                            .getRotationAngleForBitmap(RoomActivity.this, imageUri);

                                    if (0 != rotationAngle) {
                                        // always apply the rotation to the image
                                        ImageUtils.rotateImage(RoomActivity.this, thumbnailURL, rotationAngle,
                                                mMediasCache);

                                        // the high res media orientation should be not be done on uploading
                                        //ImageUtils.rotateImage(RoomActivity.this, mediaUrl, rotationAngle, mMediasCache))
                                    }
                                }

                                // is the image content valid ?
                                if (isManaged && (null != thumbnailURL)) {

                                    final String fThumbnailURL = thumbnailURL;
                                    final String fMediaUrl = mediaUrl;
                                    final String fMimeType = mimeType;

                                    RoomActivity.this.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            // if there is only one image
                                            if (mediaCount == 1) {
                                                // display an image preview before sending it
                                                mPendingThumbnailUrl = fThumbnailURL;
                                                mPendingMediaUrl = fMediaUrl;
                                                mPendingMimeType = fMimeType;
                                                mPendingFilename = fFilename;

                                                mConsoleMessageListFragment.scrollToBottom();

                                                manageSendMoreButtons();
                                            } else {
                                                mConsoleMessageListFragment.uploadImageContent(fThumbnailURL,
                                                        fMediaUrl, fFilename, fMimeType);
                                            }
                                        }
                                    });
                                }
                            }

                            // default behaviour
                            if ((!isManaged) && (null != mediaUrl)) {
                                final String fMediaUrl = mediaUrl;
                                final String fMimeType = mimeType;

                                RoomActivity.this.runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        mConsoleMessageListFragment.uploadMediaContent(fMediaUrl, fMimeType,
                                                fFilename);
                                    }
                                });
                            }
                        }
                    }

                    RoomActivity.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            handlerThread.quit();
                            progressBackground.setVisibility(View.GONE);
                            progress.setVisibility(View.GONE);
                        };
                    });
                }
            });
        }
    };

    Thread t = new Thread(r);
    t.start();
}

From source file:org.matrix.console.activity.RoomActivity.java

/**
 * Send a list of images from their URIs
 * @param mediaUris the media URIs//from w w w  .  j  ava  2  s  . com
 */
private void sendMedias(final ArrayList<Uri> mediaUris) {

    final View progressBackground = findViewById(R.id.medias_processing_progress_background);
    final View progress = findViewById(R.id.medias_processing_progress);

    progressBackground.setVisibility(View.VISIBLE);
    progress.setVisibility(View.VISIBLE);

    final HandlerThread handlerThread = new HandlerThread("MediasEncodingThread");
    handlerThread.start();

    final android.os.Handler handler = new android.os.Handler(handlerThread.getLooper());

    Runnable r = new Runnable() {
        @Override
        public void run() {
            handler.post(new Runnable() {
                public void run() {
                    final int mediaCount = mediaUris.size();

                    for (Uri anUri : mediaUris) {
                        // crash from Google Analytics : null URI on a nexus 5
                        if (null != anUri) {
                            final Uri mediaUri = anUri;
                            String filename = null;

                            if (mediaUri.toString().startsWith("content://")) {
                                Cursor cursor = null;
                                try {
                                    cursor = RoomActivity.this.getContentResolver().query(mediaUri, null, null,
                                            null, null);
                                    if (cursor != null && cursor.moveToFirst()) {
                                        filename = cursor
                                                .getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                                    }
                                } catch (Exception e) {
                                    Log.e(LOG_TAG, "cursor.getString " + e.getMessage());
                                } finally {
                                    if (null != cursor) {
                                        cursor.close();
                                    }
                                }

                                if (TextUtils.isEmpty(filename)) {
                                    List uriPath = mediaUri.getPathSegments();
                                    filename = (String) uriPath.get(uriPath.size() - 1);
                                }
                            } else if (mediaUri.toString().startsWith("file://")) {
                                // try to retrieve the filename from the file url.
                                try {
                                    filename = anUri.getLastPathSegment();
                                } catch (Exception e) {
                                }

                                if (TextUtils.isEmpty(filename)) {
                                    filename = null;
                                }
                            }

                            final String fFilename = filename;

                            ResourceUtils.Resource resource = ResourceUtils.openResource(RoomActivity.this,
                                    mediaUri);

                            if (null == resource) {
                                RoomActivity.this.runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        handlerThread.quit();
                                        progressBackground.setVisibility(View.GONE);
                                        progress.setVisibility(View.GONE);

                                        Toast.makeText(RoomActivity.this,
                                                getString(R.string.message_failed_to_upload), Toast.LENGTH_LONG)
                                                .show();
                                    }

                                    ;
                                });

                                return;
                            }

                            // save the file in the filesystem
                            String mediaUrl = mMediasCache.saveMedia(resource.contentStream, null,
                                    resource.mimeType);
                            String mimeType = resource.mimeType;
                            Boolean isManaged = false;

                            if ((null != resource.mimeType) && resource.mimeType.startsWith("image/")) {
                                // manage except if there is an error
                                isManaged = true;

                                // try to retrieve the gallery thumbnail
                                // if the image comes from the gallery..
                                Bitmap thumbnailBitmap = null;

                                try {
                                    ContentResolver resolver = getContentResolver();

                                    List uriPath = mediaUri.getPathSegments();
                                    long imageId = -1;
                                    String lastSegment = (String) uriPath.get(uriPath.size() - 1);

                                    // > Kitkat
                                    if (lastSegment.startsWith("image:")) {
                                        lastSegment = lastSegment.substring("image:".length());
                                    }

                                    imageId = Long.parseLong(lastSegment);

                                    thumbnailBitmap = MediaStore.Images.Thumbnails.getThumbnail(resolver,
                                            imageId, MediaStore.Images.Thumbnails.MINI_KIND, null);
                                } catch (Exception e) {
                                    Log.e(LOG_TAG,
                                            "MediaStore.Images.Thumbnails.getThumbnail " + e.getMessage());
                                }

                                double thumbnailWidth = mConsoleMessageListFragment.getMaxThumbnailWith();
                                double thumbnailHeight = mConsoleMessageListFragment.getMaxThumbnailHeight();

                                // no thumbnail has been found or the mimetype is unknown
                                if ((null == thumbnailBitmap) || (thumbnailBitmap.getHeight() > thumbnailHeight)
                                        || (thumbnailBitmap.getWidth() > thumbnailWidth)) {
                                    // need to decompress the high res image
                                    BitmapFactory.Options options = new BitmapFactory.Options();
                                    options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                                    resource = ResourceUtils.openResource(RoomActivity.this, mediaUri);

                                    // get the full size bitmap
                                    Bitmap fullSizeBitmap = null;

                                    if (null == thumbnailBitmap) {
                                        fullSizeBitmap = BitmapFactory.decodeStream(resource.contentStream,
                                                null, options);
                                    }

                                    if ((fullSizeBitmap != null) || (thumbnailBitmap != null)) {
                                        double imageWidth;
                                        double imageHeight;

                                        if (null == thumbnailBitmap) {
                                            imageWidth = fullSizeBitmap.getWidth();
                                            imageHeight = fullSizeBitmap.getHeight();
                                        } else {
                                            imageWidth = thumbnailBitmap.getWidth();
                                            imageHeight = thumbnailBitmap.getHeight();
                                        }

                                        if (imageWidth > imageHeight) {
                                            thumbnailHeight = thumbnailWidth * imageHeight / imageWidth;
                                        } else {
                                            thumbnailWidth = thumbnailHeight * imageWidth / imageHeight;
                                        }

                                        try {
                                            thumbnailBitmap = Bitmap.createScaledBitmap(
                                                    (null == fullSizeBitmap) ? thumbnailBitmap : fullSizeBitmap,
                                                    (int) thumbnailWidth, (int) thumbnailHeight, false);
                                        } catch (OutOfMemoryError ex) {
                                            Log.e(LOG_TAG, "Bitmap.createScaledBitmap " + ex.getMessage());
                                        }
                                    }

                                    // the valid mimetype is not provided
                                    if ("image/*".equals(mimeType)) {
                                        // make a jpg snapshot.
                                        mimeType = null;
                                    }

                                    // unknown mimetype
                                    if ((null == mimeType) || (mimeType.startsWith("image/"))) {
                                        try {
                                            // try again
                                            if (null == fullSizeBitmap) {
                                                System.gc();
                                                fullSizeBitmap = BitmapFactory
                                                        .decodeStream(resource.contentStream, null, options);
                                            }

                                            if (null != fullSizeBitmap) {
                                                Uri uri = Uri.parse(mediaUrl);

                                                if (null == mimeType) {
                                                    // the images are save in jpeg format
                                                    mimeType = "image/jpeg";
                                                }

                                                resource.contentStream.close();
                                                resource = ResourceUtils.openResource(RoomActivity.this,
                                                        mediaUri);

                                                try {
                                                    mMediasCache.saveMedia(resource.contentStream,
                                                            uri.getPath(), mimeType);
                                                } catch (OutOfMemoryError ex) {
                                                    Log.e(LOG_TAG, "mMediasCache.saveMedia" + ex.getMessage());
                                                }

                                            } else {
                                                isManaged = false;
                                            }

                                            resource.contentStream.close();

                                        } catch (Exception e) {
                                            isManaged = false;
                                            Log.e(LOG_TAG, "sendMedias " + e.getMessage());
                                        }
                                    }

                                    // reduce the memory consumption
                                    if (null != fullSizeBitmap) {
                                        fullSizeBitmap.recycle();
                                        System.gc();
                                    }
                                }

                                String thumbnailURL = mMediasCache.saveBitmap(thumbnailBitmap, null);

                                if (null != thumbnailBitmap) {
                                    thumbnailBitmap.recycle();
                                }

                                //
                                if (("image/jpg".equals(mimeType) || "image/jpeg".equals(mimeType))
                                        && (null != mediaUrl)) {

                                    Uri imageUri = Uri.parse(mediaUrl);
                                    // get the exif rotation angle
                                    final int rotationAngle = ImageUtils
                                            .getRotationAngleForBitmap(RoomActivity.this, imageUri);

                                    if (0 != rotationAngle) {
                                        // always apply the rotation to the image
                                        ImageUtils.rotateImage(RoomActivity.this, thumbnailURL, rotationAngle,
                                                mMediasCache);

                                        // the high res media orientation should be not be done on uploading
                                        //ImageUtils.rotateImage(RoomActivity.this, mediaUrl, rotationAngle, mMediasCache))
                                    }
                                }

                                // is the image content valid ?
                                if (isManaged && (null != thumbnailURL)) {

                                    final String fThumbnailURL = thumbnailURL;
                                    final String fMediaUrl = mediaUrl;
                                    final String fMimeType = mimeType;

                                    RoomActivity.this.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            // if there is only one image
                                            if (mediaCount == 1) {
                                                // display an image preview before sending it
                                                mPendingThumbnailUrl = fThumbnailURL;
                                                mPendingMediaUrl = fMediaUrl;
                                                mPendingMimeType = fMimeType;
                                                mPendingFilename = fFilename;

                                                mConsoleMessageListFragment.scrollToBottom();

                                                manageSendMoreButtons();
                                            } else {
                                                mConsoleMessageListFragment.uploadImageContent(fThumbnailURL,
                                                        fMediaUrl, fFilename, fMimeType);
                                            }
                                        }
                                    });
                                }
                            }

                            // default behaviour
                            if ((!isManaged) && (null != mediaUrl)) {
                                final String fMediaUrl = mediaUrl;
                                final String fMimeType = mimeType;

                                RoomActivity.this.runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        if ((null != fMimeType) && fMimeType.startsWith("video/")) {
                                            mConsoleMessageListFragment.uploadVideoContent(fMediaUrl, null,
                                                    fMimeType);
                                        } else {
                                            mConsoleMessageListFragment.uploadFileContent(fMediaUrl, fMimeType,
                                                    fFilename);
                                        }
                                    }
                                });
                            }
                        }
                    }

                    RoomActivity.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            handlerThread.quit();
                            progressBackground.setVisibility(View.GONE);
                            progress.setVisibility(View.GONE);
                        };
                    });
                }
            });
        }
    };

    Thread t = new Thread(r);
    t.start();
}

From source file:io.realm.TypeBasedNotificationsTests.java

@Test
@RunTestInLooperThread//w  w  w. ja va  2  s  . co  m
public void callback_with_relevant_commit_from_different_looper_realmobject_async() {
    final CountDownLatch looperThread1Done = new CountDownLatch(1);
    final CountDownLatch looperThread2Done = new CountDownLatch(1);
    final CountDownLatch looperThread3Done = new CountDownLatch(1);
    final HandlerThread looperThread1 = new HandlerThread("looperThread1");
    final HandlerThread looperThread2 = new HandlerThread("looperThread2");
    final HandlerThread looperThread3 = new HandlerThread("looperThread3");
    looperThread1.start();
    looperThread2.start();
    looperThread3.start();
    final Handler looperHandler1 = new Handler(looperThread1.getLooper());
    final Handler looperHandler2 = new Handler(looperThread2.getLooper());
    final Handler looperHandler3 = new Handler(looperThread3.getLooper());
    final Realm realm = looperThread.realm;
    realm.addChangeListener(new RealmChangeListener() {
        @Override
        public void onChange() {
            globalCommitInvocations.incrementAndGet();
        }
    });

    final Dog dog = realm.where(Dog.class).findFirstAsync();
    assertTrue(dog.load());
    dog.addChangeListener(new RealmChangeListener() {
        @Override
        public void onChange() {
            switch (typebasedCommitInvocations.incrementAndGet()) {
            case 1: // triggered by COMPLETED_ASYNC_REALM_OBJECT from calling dog.load()
                assertTrue(dog.isLoaded());
                assertFalse(dog.isValid());

                looperHandler1.post(new Runnable() {
                    @Override
                    public void run() {
                        Realm realmLooperThread1 = Realm.getInstance(realm.getConfiguration());
                        realmLooperThread1.beginTransaction();
                        realmLooperThread1.commitTransaction();
                        realmLooperThread1.close();
                        looperThread1Done.countDown();
                    }
                });
                break;
            case 2: // triggered by the irrelevant commit (not affecting Dog table) from LooperThread1
                assertTrue(dog.isLoaded());
                assertFalse(dog.isValid());

                looperHandler2.post(new Runnable() {
                    @Override
                    public void run() {
                        Realm realmLooperThread2 = Realm.getInstance(realm.getConfiguration());
                        // trigger first callback invocation
                        realmLooperThread2.beginTransaction();
                        Dog dog = realmLooperThread2.createObject(Dog.class);
                        dog.setName("Akamaru");
                        realmLooperThread2.commitTransaction();
                        realmLooperThread2.close();
                        looperThread2Done.countDown();
                    }
                });
                break;

            case 3: // triggered by relevant commit from LooperThread2
                assertEquals("Akamaru", dog.getName());
                realm.handler.post(new Runnable() {
                    @Override
                    public void run() {
                        // trigger second callback invocation
                        looperHandler3.post(new Runnable() {
                            @Override
                            public void run() {
                                Realm realmLooperThread3 = Realm.getInstance(realm.getConfiguration());
                                realmLooperThread3.beginTransaction();
                                realmLooperThread3.where(Dog.class).findFirst().setAge(17);
                                realmLooperThread3.commitTransaction();
                                realmLooperThread3.close();
                                looperThread3Done.countDown();
                            }
                        });
                    }
                });
                break;
            case 4:
                assertEquals("Akamaru", dog.getName());
                assertEquals(17, dog.getAge());
                // posting as an event will give the handler a chance
                // to deliver the notification for globalCommitInvocations
                // otherwise, test will exit before the callback get a chance to be invoked
                realm.handler.post(new Runnable() {
                    @Override
                    public void run() {
                        assertEquals(3, globalCommitInvocations.get());
                        assertEquals(4, typebasedCommitInvocations.get());
                        looperThread1.quit();
                        looperThread2.quit();
                        looperThread3.quit();
                        TestHelper.awaitOrFail(looperThread1Done);
                        TestHelper.awaitOrFail(looperThread2Done);
                        TestHelper.awaitOrFail(looperThread3Done);
                        looperThread.testComplete();
                    }
                });
                break;
            }
        }
    });

}