簡體   English   中英

可觀察到按需發射物品

[英]Observable that emit items on demand

我想創建一個Observable,它將按需發出項目,這意味着我希望一個訂閱Observable,並根據請求通知Observable我需要新的項目。

這是我使用PublishSubject完成的工作:

public class RecognizeSubject {

PublishSubject<Bitmap> mSubject;

private Context mContext;
private FaceDetector mFaceDetecor;

public RecognizeSubject(Context mContext) {
    this.mContext = mContext;
    this.mSubject = PublishSubject.create();
}

public void detect(Bitmap btm){
    mSubject.onNext(btm);
}

public Flowable<SinglePhotoId> execute() {
    return mSubject.toFlowable(BackpressureStrategy.DROP)
            .observeOn(Schedulers.newThread())
            .map(bitmap1 -> recognize(bitmap1))
            .observeOn(AndroidSchedulers.mainThread())
            .doOnSubscribe(disposable -> initialize())
            .doFinally(() -> release());
}


private void initialize() {
    mFaceDetecor = new FaceDetector.Builder(mContext)
            .setTrackingEnabled(false)
            .setLandmarkType(FaceDetector.ALL_LANDMARKS)
            .build();
}

private void release() {
    if (mFaceDetecor != null)
        mFaceDetecor.release();
}

private SinglePhotoId recognize(Bitmap bitmap) {
    //SystemClock.sleep(3000);
   //make hard background work and return SinglePhotoId object
}

}

這是Activity類的用法:

private void takeSubjectSnap() {
    if (mSubject == null)
        mSubject = new RecognizeSubject(getBaseContext());

    if (mDisposable == null || mDisposable.isDisposed()) {
        mDisposable = mSubject.execute()
                .subscribe(this::handleDetectionSuccess,
                        this::handleDetectionError,
                        this::handleDetectionCompleted);
    }

    mSnapshotButton.setProgress(true);
    mSubject.detect(myVideoView.getBitmap());
}

因此,基本上我訂閱了Flowable對象,然后將Bitmap對象傳遞給我的Subject類,以繼續進行操作並通過Flowable返回結果,該解決方案正確嗎?還是會產生一些內存泄漏?

有沒有更好的解決方案,可以通過標准的onNext()方法將對象發送到Observable進行處理並返回結果?

RxRelays在這種情況下可以派上用場

  1. 創建一個PublishRelay主題。
  2. 訂閱它。
  3. 然后使用publishRelaySubject.call(your_object);傳遞數據

https://github.com/JakeWharton/RxRelay

(我將其作為注釋,因為這不是答案,但時間太長)

我不太確定您的用例是什么,以及由於您描述和實現的內容稍有不同,您到底要實現什么目標。

您所描述的是一種機制,該機制能夠處理一些東西並在其空閑/能夠處理等時請求新的東西

您實現的機制是基於推送的處理器根據從客戶端接收的數據來處理項目的機制。

因此,如果您實現的功能可以按您的意願正常運行,那么我建議您進行一些小的更改:

  • 我將execute方法重命名為其他名稱(因為它不執行任何操作)
  • 我會用Disposables.disposed()初始化disposable使用,以避免空檢查和
  • 我現在將RecognizeSubject重命名為其他名稱,因為它正在泄漏有關其內部實現的信息。
  • 我將mSubject privatefinal
  • 我會擺脫匈牙利符號

而且我不太確定在使用位圖時,flowable是否適合使用,您確定一次需要多個位圖並處理所有位圖(並丟棄未處理的位圖嗎?)。

好的,我已經閱讀了您的答案並稍稍更改了我的代碼,下面的圖表說明了我想要實現的目標:

主題圖

因此,我的Subject類將在后台線程上處理接收到的數據,並通過onNext()方法將處理后的項目發送給其Observer。 我做了一個簡單的Subject,它接收Integer對象並將其轉換為String對象,這是代碼:

public class MySubject {

private String TAG = "MySubject";

private PublishSubject<Integer> subject;
private final Observable<String> observable;

public MySubject() {
   Log.d(TAG, "---> MySubject() called");
   this.subject = PublishSubject.create();
   this.observable = subject
           .doOnSubscribe(disposable -> init())
           .doFinally(() -> relese()) //try do after terminate
           .observeOn(Schedulers.newThread())
           .map(this::myMap)
           .observeOn(AndroidSchedulers.mainThread());
}


private void init(){
   Log.d(TAG, "---> init() called");
}

private void relese(){
   Log.d(TAG, "---> relese() called");
}

private String myMap(Integer integer){
   Log.d(TAG, "---> myMap() called int: " + integer);
   SystemClock.sleep(3000);
   return " :) " + String.valueOf(integer);
}

public void decode(Integer integer){
   subject.onNext(integer);
}

public Observable<String> getObservable(){
   return observable;
}

}

這是Activity類的用法:

Disposable disposable = Disposables.disposed();
MySubject subject = new MySubject();

void onButton1() {

   if(disposable.isDisposed()){
       disposable = subject.getObservable()
               .subscribe(s -> {
                   Log.d(TAG, "---> onNext() called " + s);
               }, throwable -> {
                   Log.d(TAG, "---> onError() called " + throwable.getMessage());
               }, () -> {
                   Log.d(TAG, "---> onCompleted() called ");
               });
   }

   Random generator = new Random();
   int i = generator.nextInt(100) + 1;
   subject.decode(i);
}

每次調用方法onButton1()時,我都會將新的隨機整數發布到主題對象,此后,當完成時,我會通過onNext()方法接收處理后的數據。

該解決方案是否正確,並且不會引起任何副作用或內存泄漏? 當然,我在Activity的onStop()方法中取消訂閱主題。 也許在Rxjava中有更好的解決方案來解決此類問題?

任何進一步的答案將不勝感激:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM