-
Notifications
You must be signed in to change notification settings - Fork 7.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial support for scheduling on Android Handler threads #318
Changes from 6 commits
8df8e9a
f5e3b5b
3919547
d34372a
0959aa5
35cf457
7d397a7
b80de93
60fa754
6f18d8b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
apply plugin: 'java' | ||
apply plugin: 'eclipse' | ||
apply plugin: 'idea' | ||
apply plugin: 'osgi' | ||
|
||
sourceCompatibility = JavaVersion.VERSION_1_6 | ||
targetCompatibility = JavaVersion.VERSION_1_6 | ||
|
||
dependencies { | ||
compile project(':rxjava-core') | ||
provided 'junit:junit-dep:4.10' | ||
provided 'org.mockito:mockito-core:1.8.5' | ||
provided 'com.pivotallabs:robolectric:1.2' | ||
provided 'com.google.android:android:4.0.1.2' | ||
} | ||
|
||
eclipse { | ||
classpath { | ||
// include 'provided' dependencies on the classpath | ||
plusConfigurations += configurations.provided | ||
|
||
downloadSources = true | ||
downloadJavadoc = true | ||
} | ||
} | ||
|
||
idea { | ||
module { | ||
// include 'provided' dependencies on the classpath | ||
scopes.PROVIDED.plus += configurations.provided | ||
} | ||
} | ||
|
||
javadoc { | ||
options { | ||
doclet = "org.benjchristensen.doclet.DocletExclude" | ||
docletpath = [rootProject.file('./gradle/doclet-exclude.jar')] | ||
stylesheetFile = rootProject.file('./gradle/javadocStyleSheet.css') | ||
windowTitle = "RxJava Javadoc ${project.version}" | ||
} | ||
options.addStringOption('top').value = '<h2 class="title" style="padding-top:40px">RxJava</h2>' | ||
} | ||
|
||
jar { | ||
manifest { | ||
name = 'rxjava-android' | ||
instruction 'Bundle-Vendor', 'Netflix' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In case SoundCloud wants to take ownership of the Android module, should probably update this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know enough about OSGI requirements to comment on how this behaves. This artifact as part of RxJava however will be on maven central under "com.netflix.rxjava" as that's the namespace on Maven, despite keeping all of the code namespaced to just "rx". |
||
instruction 'Bundle-DocURL', 'https://github.com/Netflix/RxJava' | ||
instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package rx.android.testsupport; | ||
|
||
import com.xtremelabs.robolectric.RobolectricConfig; | ||
import com.xtremelabs.robolectric.RobolectricTestRunner; | ||
import org.junit.runners.model.InitializationError; | ||
|
||
import java.io.File; | ||
|
||
public class AndroidTestRunner extends RobolectricTestRunner { | ||
|
||
public AndroidTestRunner(Class<?> testClass) throws InitializationError { | ||
super(testClass, new RobolectricConfig(new File("src/test/resources"))); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package rx.android.testsupport; | ||
|
||
public class R { | ||
// resource stub for Robolectric | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package rx.concurrency; | ||
|
||
import android.os.Handler; | ||
import android.os.Looper; | ||
import rx.Scheduler; | ||
|
||
public class AndroidSchedulers { | ||
|
||
private static final Scheduler MAIN_THREAD_SCHEDULER = | ||
new HandlerThreadScheduler(new Handler(Looper.getMainLooper())); | ||
|
||
public static Scheduler handlerThread(final Handler handler) { | ||
return new HandlerThreadScheduler(handler); | ||
} | ||
|
||
public static Scheduler mainThread() { | ||
return MAIN_THREAD_SCHEDULER; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package rx.concurrency; | ||
|
||
import android.os.Handler; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import org.mockito.ArgumentCaptor; | ||
import rx.Scheduler; | ||
import rx.Subscription; | ||
import rx.android.testsupport.AndroidTestRunner; | ||
import rx.operators.AtomicObservableSubscription; | ||
import rx.util.functions.Func2; | ||
|
||
import java.util.concurrent.TimeUnit; | ||
|
||
import static org.mockito.Matchers.eq; | ||
import static org.mockito.Mockito.mock; | ||
import static org.mockito.Mockito.verify; | ||
|
||
/** | ||
* Schedules actions to run on an Android Handler thread. | ||
*/ | ||
public class HandlerThreadScheduler extends Scheduler { | ||
|
||
private final Handler handler; | ||
|
||
public HandlerThreadScheduler(Handler handler) { | ||
this.handler = handler; | ||
} | ||
|
||
@Override | ||
public <T> Subscription schedule(final T state, final Func2<Scheduler, T, Subscription> action) { | ||
return schedule(state, action, 0L, TimeUnit.MILLISECONDS); | ||
} | ||
|
||
@Override | ||
public <T> Subscription schedule(final T state, final Func2<Scheduler, T, Subscription> action, long delayTime, TimeUnit unit) { | ||
final AtomicObservableSubscription subscription = new AtomicObservableSubscription(); | ||
final Scheduler _scheduler = this; | ||
handler.postDelayed(new Runnable() { | ||
@Override | ||
public void run() { | ||
subscription.wrap(action.call(_scheduler, state)); | ||
} | ||
}, unit.toMillis(delayTime)); | ||
return subscription; | ||
} | ||
|
||
@RunWith(AndroidTestRunner.class) | ||
public static final class UnitTest { | ||
|
||
@Test | ||
public void shouldScheduleImmediateActionOnHandlerThread() { | ||
final Handler handler = mock(Handler.class); | ||
final Object state = new Object(); | ||
final Func2<Scheduler, Object, Subscription> action = mock(Func2.class); | ||
|
||
Scheduler scheduler = new HandlerThreadScheduler(handler); | ||
scheduler.schedule(state, action); | ||
|
||
// verify that we post to the given Handler | ||
ArgumentCaptor<Runnable> runnable = ArgumentCaptor.forClass(Runnable.class); | ||
verify(handler).postDelayed(runnable.capture(), eq(0L)); | ||
|
||
// verify that the given handler delegates to our action | ||
runnable.getValue().run(); | ||
verify(action).call(scheduler, state); | ||
} | ||
|
||
@Test | ||
public void shouldScheduleDelayedActionOnHandlerThread() { | ||
final Handler handler = mock(Handler.class); | ||
final Object state = new Object(); | ||
final Func2<Scheduler, Object, Subscription> action = mock(Func2.class); | ||
|
||
Scheduler scheduler = new HandlerThreadScheduler(handler); | ||
scheduler.schedule(state, action, 1L, TimeUnit.SECONDS); | ||
|
||
// verify that we post to the given Handler | ||
ArgumentCaptor<Runnable> runnable = ArgumentCaptor.forClass(Runnable.class); | ||
verify(handler).postDelayed(runnable.capture(), eq(1000L)); | ||
|
||
// verify that the given handler delegates to our action | ||
runnable.getValue().run(); | ||
verify(action).call(scheduler, state); | ||
} | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest package="rx.android.testsupport"> | ||
|
||
<application /> | ||
|
||
</manifest> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I basically copied this file over from the Swing contrib module. There's a lot of cruft in here which I think can be remove or at least shared with the parent modules? I'm thinking about IDE project file generation and JavaDoc setup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that's probably the case, I have not yet attempted doing that as I'm not the most comfortable with Gradle.