繁体   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