[go: nahoru, domu]

Add compatibility factories for createAsync()

Bug: 111266997
Test: ./gradlew :core:conCh
Change-Id: Ib64e0dc7e57b2e12c897e241a513d6b350c8485d
diff --git a/compat/src/main/java/androidx/core/os/HandlerCompat.java b/compat/src/main/java/androidx/core/os/HandlerCompat.java
index fee06ed..05f5333 100644
--- a/compat/src/main/java/androidx/core/os/HandlerCompat.java
+++ b/compat/src/main/java/androidx/core/os/HandlerCompat.java
@@ -18,15 +18,104 @@
 
 import android.os.Build;
 import android.os.Handler;
+import android.os.Handler.Callback;
+import android.os.Looper;
 import android.os.Message;
+import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import java.lang.reflect.InvocationTargetException;
+
 /**
  * Helper for accessing features in {@link Handler}.
  */
 public final class HandlerCompat {
+    private static final String TAG = "HandlerCompat";
+
+    /**
+     * Create a new Handler whose posted messages and runnables are not subject to
+     * synchronization barriers such as display vsync.
+     *
+     * <p>Messages sent to an async handler are guaranteed to be ordered with respect to one
+     * another, but not necessarily with respect to messages from other Handlers.</p>
+     *
+     * @see #createAsync(Looper, Callback) to create an async Handler with custom message handling.
+     *
+     * @param looper the Looper that the new Handler should be bound to
+     * @return a new async Handler instance
+     * @see Handler#createAsync(Looper)
+     */
+    @NonNull
+    public static Handler createAsync(@NonNull Looper looper) {
+        if (Build.VERSION.SDK_INT >= 28) {
+            return Handler.createAsync(looper);
+        }
+        if (Build.VERSION.SDK_INT >= 16) {
+            try {
+                return Handler.class.getDeclaredConstructor(Looper.class, Callback.class,
+                        boolean.class)
+                        .newInstance(looper, null, true);
+            } catch (IllegalAccessException ignored) {
+            } catch (InstantiationException ignored) {
+            } catch (NoSuchMethodException ignored) {
+            } catch (InvocationTargetException e) {
+                Throwable cause = e.getCause();
+                if (cause instanceof RuntimeException) {
+                    throw ((RuntimeException) cause);
+                }
+                if (cause instanceof Error) {
+                    throw ((Error) cause);
+                }
+                throw new RuntimeException(cause);
+            }
+            Log.v(TAG, "Unable to invoke Handler(Looper, Callback, boolean) constructor");
+        }
+        return new Handler(looper);
+    }
+
+    /**
+     * Create a new Handler whose posted messages and runnables are not subject to
+     * synchronization barriers such as display vsync.
+     *
+     * <p>Messages sent to an async handler are guaranteed to be ordered with respect to one
+     * another, but not necessarily with respect to messages from other Handlers.</p>
+     *
+     * @see #createAsync(Looper) to create an async Handler without custom message handling.
+     *
+     * @param looper the Looper that the new Handler should be bound to
+     * @return a new async Handler instance
+     * @see Handler#createAsync(Looper, Callback)
+     */
+    @NonNull
+    public static Handler createAsync(@NonNull Looper looper, @NonNull Callback callback) {
+        if (Build.VERSION.SDK_INT >= 28) {
+            return Handler.createAsync(looper, callback);
+        }
+        if (Build.VERSION.SDK_INT >= 16) {
+            try {
+                return Handler.class.getDeclaredConstructor(Looper.class, Callback.class,
+                        boolean.class)
+                        .newInstance(looper, callback, true);
+            } catch (IllegalAccessException ignored) {
+            } catch (InstantiationException ignored) {
+            } catch (NoSuchMethodException ignored) {
+            } catch (InvocationTargetException e) {
+                Throwable cause = e.getCause();
+                if (cause instanceof RuntimeException) {
+                    throw ((RuntimeException) cause);
+                }
+                if (cause instanceof Error) {
+                    throw ((Error) cause);
+                }
+                throw new RuntimeException(cause);
+            }
+            Log.v(TAG, "Unable to invoke Handler(Looper, Callback, boolean) constructor");
+        }
+        return new Handler(looper, callback);
+    }
+
     /**
      * Causes the Runnable r to be added to the message queue, to be run
      * after the specified amount of time elapses.