Skip to content

Instantly share code, notes, and snippets.

@lvsecoto
Created December 26, 2018 09:03
Show Gist options
  • Save lvsecoto/bc0e88e721ff690bb46e7ef5eead4e9c to your computer and use it in GitHub Desktop.
Save lvsecoto/bc0e88e721ff690bb46e7ef5eead4e9c to your computer and use it in GitHub Desktop.
每隔一段时间生成LiveData
import android.annotation.SuppressLint;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MediatorLiveData;
import android.support.annotation.MainThread;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import static android.arch.core.executor.ArchTaskExecutor.getMainThreadExecutor;
/**
* 在{@link #onSchedule(ScheduledExecutorService, Runnable)}回调中进行定时任务调度,每当这个任务被执行,就会
* 回调{@link #onGenerateLiveData()} 创建LiveData,作为TimerLiveData的源
*/
@SuppressLint("RestrictedApi")
public abstract class TimerLiveData<T> {
@Nullable
private LiveData<T> mSource;
@NonNull
private final MediatorLiveData<T> mResult;
@Nullable
private ScheduledExecutorService mExecutor;
@NonNull
private final Runnable mSchedule;
public TimerLiveData() {
mResult = new MediatorLiveData<T>() {
@Override
protected void onActive() {
super.onActive();
mExecutor = Executors.newScheduledThreadPool(1);
onSchedule(mExecutor, mSchedule);
}
@Override
protected void onInactive() {
super.onInactive();
if (mExecutor != null) {
mExecutor.shutdown();
mExecutor = null;
}
}
};
mSchedule = () -> getMainThreadExecutor().execute(() -> {
LiveData<T> newSource = onGenerateLiveData();
if (mSource != null) {
mResult.removeSource(mSource);
}
mSource = newSource;
if (mSource != null) {
mResult.addSource(mSource, mResult::setValue);
}
});
}
public LiveData<T> asLiveData() {
return mResult;
}
/**
* 返回的LiveData,作为TimerLiveData的源
* <p>当返回是null, 则从此时刻到下一次调用此回调之间的时间,此TimerLiveData解除所有LiveData源
*/
@Nullable
@MainThread
protected abstract LiveData<T> onGenerateLiveData();
/**
* 利用{@code executor}调度{@code schedule}, 产生定时任务
*
* @see ScheduledExecutorService#schedule(Runnable, long, TimeUnit)
* @see ScheduledExecutorService#scheduleAtFixedRate(Runnable, long, long, TimeUnit)
* @see ScheduledExecutorService#scheduleWithFixedDelay(Runnable, long, long, TimeUnit)
*/
@SuppressWarnings("UnusedReturnValue")
@NonNull
protected abstract ScheduledFuture<?> onSchedule(final ScheduledExecutorService executor, final Runnable schedule);
}
import android.arch.core.executor.testing.InstantTaskExecutorRule;
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.LifecycleRegistry;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.Observer;
import android.support.annotation.NonNull;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.after;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(AndroidJUnit4.class)
public class TimerLiveDataTest {
@Rule
public TestRule rule = new InstantTaskExecutorRule();
private static LifecycleOwner mockLifecycleOwner() {
LifecycleOwner owner = mock(LifecycleOwner.class);
LifecycleRegistry lifecycle = new LifecycleRegistry(owner);
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
when(owner.getLifecycle()).thenReturn(lifecycle);
return owner;
}
@SuppressWarnings("unchecked")
private static <T> Observer<T> mockObserver() {
return (Observer<T>) Mockito.mock(Observer.class);
}
@Test
public void timerLiveDataTest() {
LiveData<String> timerLiveData = new TimerLiveData<String>() {
@Override
protected LiveData<String> onGenerateLiveData() {
MutableLiveData<String> newLiveData = new MutableLiveData<>();
newLiveData.setValue("new value");
return newLiveData;
}
@NonNull
@Override
protected ScheduledFuture<?> onSchedule(ScheduledExecutorService executor, Runnable schedule) {
return executor.schedule(schedule, 100, TimeUnit.MILLISECONDS);
}
}.asLiveData();
LifecycleOwner owner = mockLifecycleOwner();
Observer<String> observer = mockObserver();
timerLiveData.observe(owner, observer);
verify(observer, after(50).never()).onChanged(any());
verify(observer, after(150).times(1)).onChanged("new value");
}
/**
* 每一秒持续生成LiveData,第三秒不生成
*/
@Test
public void timerLiveDataTestReturnNullToPass() {
LiveData<String> timerLiveData = new TimerLiveData<String>() {
private int time = 0;
@Override
protected LiveData<String> onGenerateLiveData() {
time++;
if (time == 3) {
return null;
} else {
MutableLiveData<String> newLiveData = new MutableLiveData<>();
newLiveData.setValue("time " + time);
return newLiveData;
}
}
@NonNull
@Override
protected ScheduledFuture<?> onSchedule(ScheduledExecutorService executor, Runnable schedule) {
return executor.scheduleAtFixedRate(schedule, 1000, 1000, TimeUnit.MILLISECONDS);
}
}.asLiveData();
LifecycleOwner owner = mockLifecycleOwner();
Observer<String> observer = mockObserver();
timerLiveData.observe(owner, observer);
verify(observer, after(800).never()).onChanged(any());
verify(observer, after(1500).times(1)).onChanged("time 1");
verify(observer, after(2500).times(1)).onChanged("time 2");
verify(observer, after(3500).never()).onChanged("time 3");
verify(observer, after(4500).times(1)).onChanged("time 4");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment