I know that if the Observable emits a piece of data, it resubscribes, and if the Observable emits an onError notification, it passes that notification to the observer and terminates. The problem is that if I emit a Obervable.just(1,2),but it won't be accept by the observer.So what's the usage of it?Dose it just tell it to resubscribes,and it's not important what data i emit?
Observable.just(1, "2", 3)
.cast(Integer.class)
.retryWhen(new Function<Observable<Throwable>, ObservableSource<Integer>>() {
#Override
public ObservableSource<Integer> apply(Observable<Throwable> throwableObservable) throws Exception {
return Observable.just(4,5);
}
})
.subscribe(new Consumer<Integer>() {
#Override
public void accept(Integer integer) throws Exception {
Log.i(TAG, "retryWhen重试数据"+integer);
}
});
and the log is
retryWhen重试数据1
retryWhen重试数据1
so Observable.just(4,5) is gone?
You can check out this example from the documentation to better understand how the retryWhen supposed to work (source: http://reactivex.io/RxJava/javadoc/io/reactivex/Observable.html#retryWhen-io.reactivex.functions.Function-):
Observable.create((ObservableEmitter<? super String> s) -> {
System.out.println("subscribing");
s.onError(new RuntimeException("always fails"));
}).retryWhen(attempts -> {
return attempts.zipWith(Observable.range(1, 3), (n, i) -> i).flatMap(i -> {
System.out.println("delay retry by " + i + " second(s)");
return Observable.timer(i, TimeUnit.SECONDS);
});
}).blockingForEach(System.out::println);
Output is:
subscribing
delay retry by 1 second(s)
subscribing
delay retry by 2 second(s)
subscribing
delay retry by 3 second(s)
subscribing
Observable.create(new Observable.OnSubscribe<Integer>() {
#Override
public void call(Subscriber<? super Integer> subscriber) {
subscriber.onStart();
subscriber.onNext(1);
subscriber.onCompleted();
}
}).delaySubscription(5, TimeUnit.SECONDS).subscribe(new Subscriber<Integer>() {
#Override
public void onCompleted() {
Log.e("TAG", String.format("(%s) - onCompleted", System.currentTimeMillis()));
}
#Override
public void onError(Throwable e) {
Log.e("TAG", String.format("(%s) - onError", System.currentTimeMillis()), e);
}
#Override
public void onNext(Integer integer) {
Log.e("TAG", String.format("(%s) - onNext: %s", System.currentTimeMillis(), integer));
}
#Override
public void onStart() {
super.onStart();
Log.e("TAG", String.format("(%s) - onStart", System.currentTimeMillis()));
}
});
output:
(1485004553817) - onStart
(1485004558818) - onNext: 1
(1485004558819) - onCompleted
why onStart event not waiting to delaySubscription and calling soon ?
i want aware when call method called
Documentation says -
onStart -
This method is invoked when the Subscriber and Observable have been connected but the Observable has not yet begun to emit items or send notifications to the Subscriber.
delaySubscription:
Returns an Observable that delays the subscription to the source Observable by a given amount of time.
onNext is invoked only when the subscription is achieved. onStart is called the moment a connection is established. Thus, it works as expected according to the definition.
You can try commenting the code subscriber.onStart(); and execute the same again to notice that onStart is still called at the beginning. The intentional execution did not really invoke the said method because this was executed not on the real subscriber we created, but the one which was a result of delaySubscription (of type OnSubscribeDelaySubscription).
Below is a snippet which can probably help you achieve what you're looking for:
public static void main(String[] args) throws UnsupportedEncodingException, IOException {
Observable.timer(5, TimeUnit.SECONDS).flatMap(val -> {
System.out.println("Initialize");
return Observable.create(subscriber -> {
System.out.println("onsubscribe");
doMyAsyncStuff(subscriber);
});
}).subscribe(val -> System.out.println(val));
Observable.timer(10, TimeUnit.SECONDS).toBlocking().first();
}
We initialize a timer, once timer is executed, we perform some task in flatMap which should be the same as what you earlier did with onStart. Once that task is executed, we emit a Observable which emits all the elements that you could have consumed earlier with onNext calls.
Hello I am making observable to ask my server about its online/offline status every 15 seconds:
public Observable<Response> repeatCheckServerStatus(int intervalSec, final String path) {
return Observable.interval(intervalSec, TimeUnit.SECONDS)
.flatMap(new Func1<Long, Observable<Response>>() {
#Override
public Observable<Response> call(Long aLong) {
return Observable.create(new Observable.OnSubscribe<Response>() {
#Override
public void call(Subscriber<? super Response> subscriber) {
try {
Response response = client.newCall(new Request.Builder()
.url(path + API_ACTION_CHECK_ONLINE_STATUS)
.header("Content-Type", "application/x-www-form-urlencoded")
.get()
.build()).execute();
subscriber.onNext(response);
subscriber.onCompleted();
if (!response.isSuccessful())
subscriber.onError(new Exception());
} catch (Exception e) {
subscriber.onError(e);
}
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
});
}
After I call this method, first execution of code will be after intervalSec time (15sec in my case). Looking at rxJava docummentation of interval method:
http://reactivex.io/documentation/operators/interval.html
This is how it should be.
Question: is there any way to execute code instantly and then repeat in intervals?
You can execute it immediately also like this:
Observable.interval(0, 1000, TimeUnit.MILLISECONDS).subscribe();
What you are looking for is startWith
Observable.interval(15, SECONDS).startWith(1);
This will get the updates from the interval, but emit one item immediately after subscribing.
you can use `
Observable.interval(1, TimeUnit.SECONDS).startWith(0)
`
It is duplicate value "0" in subscribe.
What I want to do is to execute several operations(say network request) on worker threads, and then merge results of each request into one List<>.
Simplified version of my code looks like this:
public static void main(String[] args) {
Observable.from(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
.flatMap(integer -> {
try {
System.out.println(Thread.currentThread().getName());
//Simulate long-running operation
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Observable.just("number: " + integer);
})
.toList()
.subscribe(new Subscriber<List<String>>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(List<String> result) {
System.out.println(result);
}
});
}
Now this runs fine, but apparently it's executed on main thread. When I add this line before .toList():
.subscribeOn(Schedulers.io())
then nothing is printed into console. What I'm doing wrong here?
What happens is that your main thread exits before the io threads, which are daemon threads, have a chance to run. So you either use .toBlocking().forEach() to wait for the asynchronous computation or add Thread.sleep(10000) after the subscribe() call.
Edit:
The original example is sequential by nature. You can introduce some parallelism by deferring the calculation in the flatMap:
Observable.range(1, 10)
.flatMap(number ->
Observable.defer(() -> {
try {
// computation
return Observable.just("result: " + number);
} catch (Throwable e) {
return Observable.<String>error(e);
}
}).subscribeOn(Schedulers.computation());
)
.toList()
.subscribe(...);
Can anyone tell me if an equivalent for setInterval/setTimeout exists for Android? Does anybody have any example about how to do it?
As always with Android there's lots of ways to do this, but assuming you simply want to run a piece of code a little bit later on the same thread, I use this:
new android.os.Handler(Looper.getMainLooper()).postDelayed(
new Runnable() {
public void run() {
Log.i("tag", "This'll run 300 milliseconds later");
}
},
300);
.. this is pretty much equivalent to
setTimeout(
function() {
console.log("This will run 300 milliseconds later");
},
300);
setInterval()
function that repeats itself in every n milliseconds
Javascript
setInterval(function(){ Console.log("A Kiss every 5 seconds"); }, 5000);
Approximate java Equivalent
new Timer().scheduleAtFixedRate(new TimerTask(){
#Override
public void run(){
Log.i("tag", "A Kiss every 5 seconds");
}
},0,5000);
setTimeout()
function that works only after n milliseconds
Javascript
setTimeout(function(){ Console.log("A Kiss after 5 seconds"); },5000);
Approximate java Equivalent
new android.os.Handler().postDelayed(
new Runnable() {
public void run() {
Log.i("tag","A Kiss after 5 seconds");
}
}, 5000);
If you're not worried about waking your phone up or bringing your app back from the dead, try:
// Param is optional, to run task on UI thread.
Handler handler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
#Override
public void run() {
// Do the task...
handler.postDelayed(this, milliseconds) // Optional, to repeat the task.
}
};
handler.postDelayed(runnable, milliseconds);
// Stop a repeating task like this.
handler.removeCallbacks(runnable);
Depending on what you actually want to achieve, you should take a look at Android Handlers:
http://developer.android.com/reference/android/os/Handler.html
If you previously used javascript setTimeout() etc to schedule a task to run in the future, this is the Android way of doing it (postDelayed / sendMessageDelayed).
Note that neither Handlers or Timers makes an Android phone wake up from sleep mode. In other words, if you want to schedule something to actually happen even though the screen is off / cpu is sleeping, you need to check out the AlarmManager too.
The first answer is definitely the correct answer and is what I based this lambda version off of, which is much shorter in syntax. Since Runnable has only 1 override method "run()", we can use a lambda:
this.m_someBoolFlag = false;
new android.os.Handler().postDelayed(() -> this.m_someBoolFlag = true, 300);
I do not know much about JavaScript, but I think Timers may be what you are looking for.
http://developer.android.com/reference/java/util/Timer.html
From the link:
One-shot are scheduled to run at an absolute time or after a relative delay. Recurring tasks are scheduled with either a fixed period or a fixed rate.
import java.util.Timer;
import java.util.TimerTask;
class Clock {
private Timer mTimer = new Timer();
private int mSecondsPassed = 0;
private TimerTask mTask = new TimerTask() {
#Override
public void run() {
mSecondsPassed++;
System.out.println("Seconds passed: " + mSecondsPassed);
}
};
private void start() {
mTimer.scheduleAtFixedRate(mTask, 1000, 1000);
}
public static void main(String[] args) {
Clock c = new Clock();
c.start();
}
}
I was creating a mp3 player for android, I wanted to update the current time every 500ms so I did it like this
setInterval
private void update() {
new android.os.Handler().postDelayed(new Runnable() {
#Override
public void run() {
long cur = player.getCurrentPosition();
long dur = player.getDuration();
currentTime = millisecondsToTime(cur);
currentTimeView.setText(currentTime);
if (cur < dur) {
updatePlayer();
}
// update seekbar
seekBar.setProgress( (int) Math.round((float)cur / (float)dur * 100f));
}
}, 500);
}
which calls the same method recursively
Here's a setTimeout equivalent, mostly useful when trying to update the User Interface
after a delay.
As you may know, updating the user interface can only by done from the UI thread.
AsyncTask does that for you by calling its onPostExecute method from that thread.
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// Update the User Interface
}
}.execute();
As always with Android there's lots of ways to do this, but assuming you simply want to run a piece of code on the same thread, I use this:
new Timer().scheduleAtFixedRate(new TimerTask(){
#Override
public void run(){
Log.i("tag", "Hai Codemaker");
}
},0,1000);
This code will log Hai Codemaker text every one second.
Kotlin:
You can also use CountDownTimer:
class Timer {
companion object {
#JvmStatic
fun call(ms: Long, f: () -> Unit) {
object : CountDownTimer(ms,ms){
override fun onFinish() { f() }
override fun onTick(millisUntilFinished: Long) {}
}.start()
}
}
}
And in your code:
Timer.call(5000) { /*Whatever you want to execute after 5000 ms*/ }
In case someone wants -
Kotlin equivalent to JavaScript setInterval/setTimeout
IMPORTANT: Remember to import android.os.Handler. Don't get mistaken by java.util.logging.Handler
Timeout equivalent
Javascript: setTimeout()
setTimeout(function(){
// something that can be run.
}, 1500);
Kotlin: runOnTimeout()
inline fun runOnTimeout(crossinline block: () -> Unit, timeoutMillis: Long) {
Handler(Looper.getMainLooper()).postDelayed({
block()
}, timeoutMillis)
}
Kotlin: Calling
runOnTimeout({
// something that can be run.
}, 1500)
Timeinterval equivalent
Javascript: setInterval()
setInterval(function(){
// something that can be run.
}, 1500);
Kotlin: runOnInterval()
inline fun runOnInterval(crossinline block: () -> Unit, interval: Long) {
val runnable = object : Runnable {
override fun run() {
block()
handler.postDelayed(this, interval)
}
}
handler.post(runnable)
}
Kotlin: Calling
runOnInterval({
// something that can be run.
}, 1500)
Cancellable timeout and interval
If you want to use custom handler so that you can cancel the runnable, then you can use following codes.
Timeout
inline fun runOnTimeout(crossinline block: () -> Unit, timeoutMillis: Long) {
runOnTimeout(Handler(Looper.getMainLooper()), block, timeoutMillis)
}
inline fun runOnTimeout(handler: Handler, crossinline block: () -> Unit, timeoutMillis: Long): Runnable {
val runnable = Runnable { block() }
handler.postDelayed(runnable, timeoutMillis)
return runnable
}
Timeout: Calling
runOnTimeout({
// something that can be run.
}, 1500)
// OR
val runnable = runOnTimeout(mHandler, {
// something that can be run.
}, 1500)
// to cancel
mHandler.removeCallbacks(runnable)
Interval
inline fun runOnInterval(crossinline block: () -> Unit, interval: Long) {
runOnInterval(Handler(Looper.getMainLooper()), block, interval)
}
inline fun runOnInterval(handler: Handler, crossinline block: () -> Unit, interval: Long): Runnable {
val runnable = object : Runnable {
override fun run() {
block()
handler.postDelayed(this, interval)
}
}
handler.post(runnable)
return runnable
}
Interval: Calling
runOnInterval({
// something that can be run.
}, 1500)
// OR
val runnable = runOnInterval(mHandler, {
// something that can be run.
}, 1500)
// to cancel
mHandler.removeCallbacks(runnable)