runOnUiThread()在线程中执行时似乎不起作用。有人知道一个变通方法吗?
注意:我在这里提交了一张票 - https://github.com/robolectric/robolectric/issues/2479
import android.app.Activity;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.junit.Assert.assertTrue;
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class RunOnUiThreadTest {
/**
* Works
* @throws Exception
*/
@Test
public void inside_the_main_thread() throws Exception {
final Activity activity = Robolectric.setupActivity(Activity.class);
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean didRun = new AtomicBoolean(false);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
didRun.set(true);
latch.countDown();
}
});
latch.await(20, TimeUnit.SECONDS);
assertTrue(didRun.get());
}
/**
* Fails
* @throws Exception
*/
@Test
public void inside_a_new_thread() throws Exception {
final Activity activity = Robolectric.setupActivity(Activity.class);
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean didRun = new AtomicBoolean(false);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
didRun.set(true);
latch.countDown();
}
});
}
});
thread.start();
latch.await(20, TimeUnit.SECONDS);
assertTrue(didRun.get());
}
}
由于第二个测试阻止了运行目标Runnable
所需的UI线程,因此测试的结果可能与预期的一样。
第一个测试将通过,因为整个方法是同步执行的。由于您已经在UI线程上,当调用activity.runOnUiThread(...)
时,Runnable
将立即执行。因为latch
是0,所以latch.await(20, TimeUnit.SECONDS)
立即返回并且断言为真。
在第二个示例中,您将启动一个新线程并从其中调用activity.runOnUiThread(...)
。由于您不在UI线程上,因此将Runnable
发布到UI线程上的Handler
,以便将来异步执行。此时,您将继续从UI线程调用latch.await(20, TimeUnit.SECONDS);
,这意味着在此期间Runnable
无法运行,因为您阻止了UI线程。
20秒后,线程恢复,但Runnable
从未有机会运行,因此断言失败,因为didRun()
从未设置为true。
下面是一个更新的测试,允许使用Runnable
发布的runOnUiThread()
运行。
@Test
public void inside_a_new_thread() throws Exception {
final Activity activity = Robolectric.setupActivity(Activity.class);
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean didRun = new AtomicBoolean(false);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
didRun.set(true);
latch.countDown();
}
});
}
});
thread.start();
// sleep current thread to give the new thread a chance to run and post the runnable
Thread.sleep(1000);
// This method will cause the runnable to be executed
Robolectric.flushForegroundThreadScheduler();
// Should immediately return since the runnable has been executed
latch.await(20, TimeUnit.SECONDS);
assertTrue(didRun.get());
}