可观察到按需发射物品

时间:2017-03-29 06:54:42

标签: java android rx-java observable rx-android

我想创建一个按需发出项目的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返回结果,该解决方案是正确的还是会产生一些内存泄漏?

有没有更好的解决方案将对象发送到Observable继续并通过标准的onNext()方法返回结果?

3 个答案:

答案 0 :(得分:0)

在这种情况下,RxRelays非常方便

  1. 创建PublishRelay主题。
  2. 订阅它。
  3. 使用publishRelaySubject.call(your_object);
  4. 传递数据

    https://github.com/JakeWharton/RxRelay

答案 1 :(得分:0)

(我将此作为评论,因为这不是一个答案,但它太长了)

我不确定这里的用例是什么,以及您正在尝试实现的内容,因为您描述和实施的内容略有不同。

您所描述的是一种能够处理某些内容并在其自由/能够处理/等时请求新内容的机制

您实现的是一种基于推送的处理器处理项目的机制,具体取决于它从客户端接收的数据。

因此,如果您实施的内容按照您的要求正常运行,那么我会提出一些改变:

  • 我将execute方法重命名为其他方法(因为它不会执行任何操作)
  • 我使用disposable初始化Disposables.disposed()以避免空检查
  • 我现在正在将RecognizeSubject重命名为其他内容,因为它正在泄漏有关其内部实施的信息。
  • mSubject privatefinal
  • 我摆脱了匈牙利的记谱法

我并不确定在使用位图时是否可以使用可流动的东西,您确定需要同时处理多个位图并处理所有位图(并删除那些未处理的位图吗?)。

答案 2 :(得分:0)

好的,我已经阅读了您的答案并稍微更改了我的代码,这是一个图表,说明了我想要实现的目标:

subject diagram

所以我的Subject类将处理后台线程上的接收数据,并通过onNext()方法将处理过的项目发送到它们的Observer。我创建了一个简单的Subject,它接收Integer对象并将其转换为String对象,这里是代码:

fadeOut fadeOut fadeIn

}

这是Activity类中的用法:

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;
}

每次调用onButton1()方法时,我都会将新的随机int发布到主题对象,然后在完成后通过onNext()方法接收处理过的数据。

该解决方案是否正确并且不会导致任何副作用或内存泄漏? 当然我在Activity的onStop()方法中取消订阅主题。 也许有更好的解决方案来处理Rxjava中的这类问题?

任何进一步的答案将不胜感激:)