1. 程式人生 > >想用rxjava+rxandroid 替換handle實現數字時鐘,出現無響應,不能隔一秒呼叫onNext

想用rxjava+rxandroid 替換handle實現數字時鐘,出現無響應,不能隔一秒呼叫onNext

package com.example.testrxandroid;

import rx.Observable;
import rx.Observable.OnSubscribe;
import rx.android.schedulers.AndroidSchedulers;
import rx.Scheduler;
import rx.Subscriber;
import rx.schedulers.Schedulers;
import android.support.v7.app.ActionBarActivity;
import android.text.format.DateFormat;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {
TextView textView;
Button button;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textView = (TextView) findViewById(R.id.textView1);
    button = (Button) findViewById(R.id.button1);

    final Observable<String> observable = Observable
            .create(new OnSubscribe<String>() {

                @Override
                public void call(Subscriber<? super String> subscriber) {
                    // TODO Auto-generated method stub

                    while (true) {//迴圈
                        try {
                            Thread.sleep(1000);//隔1s
                            subscriber.onNext(DateFormat.format(
                                    "yyyy年MM月dd日 hh:mm:ss",
                                    System.currentTimeMillis()).toString());//返回當前時間
                            subscriber.onCompleted();
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }

                    }
                }
            }).observeOn(Schedulers.newThread())       //計時放在子執行緒
            .subscribeOn(AndroidSchedulers.mainThread());//介面UI放在主執行緒

    final Subscriber<String> subscriber = new Subscriber<String>() {

        @Override
        public void onCompleted() {
            // TODO Auto-generated method stub

        }

        @Override
        public void onError(Throwable throwable) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onNext(String str) {
            // TODO Auto-generated method stub
            Log.d("lihui", "time---" + str);
            textView.setText(str);
        }
    };

    button.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            observable.subscribe(subscriber);
        }

    });
}

}
問題:
發現介面點選button 直接無響應了。
難道rxandroid不能迴圈呼叫onnext???

分析log發現執行緒阻塞,導致無響應。
程式碼涉及到執行緒的地方只有2處:
observeOn(Schedulers.newThread())
subscribeOn(AndroidSchedulers.mainThread() );
一定是這裡出了問題。

網上查到observeOn是對應call()方法,
耗時操作,所以是
Schedulers.newThread();
subsubscribeOn對應onNext(),
所以是主執行緒 ,更新UI介面。

誤人子弟啊!!!其實正常相反!!!!!
 .subscribeOn
(Schedulers.io()) //指定 subscribe() 發生在 IO 執行緒,子執行緒,對應call() .observeOn( AndroidSchedulers.mainThread() ) //指定 Subscriber 的回調發生在主執行緒,對應onNext()

修改

.observeOn(AndroidSchedulers.mainThread()) 主執行緒
.subscribeOn(Schedulers.newThread()); new子執行緒、io執行緒

發現介面只更新一次!!!
尼瑪,什麼情況???

發現程式碼有個
subscriber.onCompleted(); 監聽完成。觀察者迴圈不再繼續,退出

去掉後,顯示正常!!!ok

使用rxjava+rxandroid 實現了數字時鐘!!!

停止訂閱:
訂閱者定義:
Subscriber subscriber
或者
Observer observer

如果你是使用了observable+Subscriber

1 observable
2 Subscriber
3 observer

注:
Subscriber subscriber;
subscription=observable.subscribe(subscriber);
subscription.unsubscribe();
再次訂閱:
observable.subscribe(subscriber);
尼瑪,發現沒有效果!!!

解決方法是訂閱者使用 Observer observer 來定義
1)subscription = observable.subscribe(observer);
2)subscription.unsubscribe();
再次訂閱
subscription = observable.subscribe(observer);
生效。

也就是說使用了subscriber作為訂閱者,那麼你取消訂閱後,無法再次訂閱,只能訂閱一次!!!

如果你想取消後可以重複訂閱,使用observer!!!