All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.robolectric.annotation.LooperMode Maven / Gradle / Ivy

The newest version!
package org.robolectric.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * A {@link org.robolectric.pluginapi.config.Configurer} annotation for controlling Robolectric's
 * {@link android.os.Looper} behavior.
 *
 * 

Currently Robolectric will default to {@link LooperMode.Mode#PAUSED} behavior, but this can be * overridden by applying a @LooperMode(NewMode) annotation to a test package, test class, or test * method, or via the 'robolectric.looperMode' system property. * * @see org.robolectric.plugins.LooperModeConfigurer * @see org.robolectric.util.Scheduler * @see org.robolectric.shadows.ShadowLooper */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.PACKAGE, ElementType.TYPE, ElementType.METHOD}) public @interface LooperMode { /** Specifies the different supported Looper modes. */ enum Mode { /** * Robolectric's default threading model prior to 4.4. * *

Tasks posted to Loopers are managed via a {@link org.robolectric.util.Scheduler}. {@link * org.robolectric.util.Scheduler} behavior can be controlled via {@link * org.robolectric.util.Scheduler#setIdleState(org.robolectric.util.Scheduler.IdleState) * setIdleState(IdleState)}, with a default of {@link * org.robolectric.util.Scheduler.IdleState#UNPAUSED UNPAUSED}. * *

There is only a single Looper thread - with tests and all posted Looper tasks executing on * that thread. * *

{@link org.robolectric.shadows.ShadowLooper} APIs can also be used to control posted * tasks, but most of those APIs just serve as a facade to {@link * org.robolectric.util.Scheduler} APIs. * *

There are multiple problems with this mode. Some of the major ones are: * *

    *
  1. The default {@link org.robolectric.util.Scheduler.IdleState#UNPAUSED UNPAUSED} state * will execute tasks posted to a {@link android.os.Looper} inline synchronously. This * differs from real Android behaviour, and can cause issues with code that * expects/enforces that posted tasks execute in the correct order, such as RecyclerViews. *
  2. The {@link org.robolectric.util.Scheduler} list of Runnables can get out of sync with * the Looper's {@link android.os.MessageQueue}, causing deadlocks or other race * conditions. *
  3. Each {@link org.robolectric.util.Scheduler} keeps its own time value, which can get out * of sync. *
  4. Background {@link android.os.Looper} tasks execute in the main thread, causing errors * for code that enforces that it runs on a non-main {@link android.os.Looper} thread. *
* * @deprecated use LooperMode.PAUSED */ @Deprecated LEGACY, /** * A mode that more accurately models real Android's {@link android.os.Looper} behavior. * *

Conceptually LooperMode.PAUSED is similar to the LEGACY {@link * org.robolectric.util.Scheduler.IdleState#PAUSED} in the following ways: * *

    *
  • Tests run on the main looper thread *
  • Tasks posted to the main {@link android.os.Looper} are not executed automatically, and * must be explicitly executed via {@link org.robolectric.shadows.ShadowLooper} APIs like * {@link org.robolectric.shadows.ShadowLooper#idle()}. This guarantees execution order * correctness *
  • {@link android.os.SystemClock} time is frozen, and can be manually advanced via * Robolectric APIs. *
* * However, it has the following improvements: * *
    *
  • Robolectric will warn users if a test fails with unexecuted tasks in the main Looper * queue *
  • Robolectric test APIs, like {@link * org.robolectric.android.controller.ActivityController#setup()}, will automatically idle * the main {@link android.os.Looper} *
  • Each {@link android.os.Looper} has its own thread. Tasks posted to background loopers * are executed asynchronously in separate threads. *
  • {@link android.os.Looper} use the real {@link android.os.MessageQueue} to store their * queue of pending tasks *
  • There is only a single clock value, managed via {@link * org.robolectric.shadows.ShadowSystemClock}. This can be explictly incremented via * {@link android.os.SystemClock#setCurrentTimeMillis(long)}, or {@link * org.robolectric.shadows.ShadowLooper#idleFor(Duration)}. *
* * A subset of the {@link org.robolectric.util.Scheduler} APIs for the 'foreground' scheduler * are currently supported in this mode as well, although it is recommended to switch to use * ShadowLooper APIs directly. * *

To use: * *

    *
  • Apply the LooperMode(PAUSED) annotation to your test package/class/method (or remove a * LooperMode(LEGACY) annotation) *
  • Convert any background {@link org.robolectric.util.Scheduler} for controlling {@link * android.os.Looper}s to shadowOf(looper) *
  • Convert any {@link org.robolectric.android.util.concurrent.RoboExecutorService} usages * to {@link org.robolectric.android.util.concurrent.PausedExecutorService} or {@link * org.robolectric.android.util.concurrent.InlineExecutorService} *
  • Run your tests. If you see an test failures like 'Main looper has queued unexecuted * runnables.', you may need to insert shadowOf(getMainLooper()).idle() calls to your test * to drain the main Looper. *
*/ PAUSED, /** * A mode that simulates an android instrumentation test threading model, which has a separate * test thread distinct from the main looper thread. * *

Otherwise it is quite similar to PAUSED mode. The clock time is still fixed, and you can * use shadowLooper methods to pause, unpause, and wait for any looper to be idle. * *

It is recommended to use this mode in tests that mostly use androidx.test APIs, which will * support being called directly on the main thread or on the test thread. Most org.robolectric * APIs that interact with the android UI (e.g. ActivityController) will raise an exception if * called off the main thread. */ INSTRUMENTATION_TEST, /** * Currently not supported. * *

In future, will have free running threads with an automatically increasing clock. */ // RUNNING } /** Set the Looper mode. */ Mode value(); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy