简体   繁体   English

可观察到按需发射物品

[英]Observable that emit items on demand

I want to create an Observable that will emit items on demand, that means I want a single subscribe to Observable and notify Observable that I need new item based on my request. 我想创建一个Observable,它将按需发出项目,这意味着我希望一个订阅Observable,并根据请求通知Observable我需要新的项目。

This is what I have done using PublishSubject: 这是我使用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
}

} }

and here is a usage in Activity class: 这是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());
}

So basically I subscribe to Flowable object and pass Bitmap object to my Subject class to proceed and return result via Flowable, is that solution right or can produce some memory leaks? 因此,基本上我订阅了Flowable对象,然后将Bitmap对象传递给我的Subject类,以继续进行操作并通过Flowable返回结果,该解决方案正确吗?还是会产生一些内存泄漏?

Is there any better solution to send an object to Observable to proceed and return result via a standard onNext() method? 有没有更好的解决方案,可以通过标准的onNext()方法将对象发送到Observable进行处理并返回结果?

RxRelays can be handy in this situation RxRelays在这种情况下可以派上用场

  1. Create a PublishRelay subject. 创建一个PublishRelay主题。
  2. Subscribe on it. 订阅它。
  3. And pass on data using publishRelaySubject.call(your_object); 然后使用publishRelaySubject.call(your_object);传递数据

https://github.com/JakeWharton/RxRelay https://github.com/JakeWharton/RxRelay

(I'd put this as a comment because this is not an answer but it's too long) (我将其作为注释,因为这不是答案,但时间太长)

I'm not really sure what is your use case here, and what exactly you're trying to achieve as the thing you described and implemented is little bit different. 我不太确定您的用例是什么,以及由于您描述和实现的内容稍有不同,您到底要实现什么目标。

What you described is a mechanism that is capable of processing some stuff and requesting new stuff when it's free/capable of processing/etc 您所描述的是一种机制,该机制能够处理一些东西并在其空闲/能够处理等时请求新的东西

What you implemented is a mechanism that is push-based processor processing items depending on data it receives from the clients. 您实现的机制是基于推送的处理器根据从客户端接收的数据来处理项目的机制。

So if the stuff you implemented is working as you want it's fine, but I'd suggest some little changes: 因此,如果您实现的功能可以按您的意愿正常运行,那么我建议您进行一些小的更改:

  • I'd rename execute method to something else (as it doesn't execute anything) 我将execute方法重命名为其他名称(因为它不执行任何操作)
  • I'd init disposable with Disposables.disposed() to avoid null check and 我会用Disposables.disposed()初始化disposable使用,以避免空检查和
  • I'd rename RecognizeSubject to something else at as right now it's leaking information about it's internal implementation. 我现在将RecognizeSubject重命名为其他名称,因为它正在泄漏有关其内部实现的信息。
  • I'd make mSubject private and final 我将mSubject privatefinal
  • I'd get rid of hungarian notation 我会摆脱匈牙利符号

And I'm not really sure if flowable is appropriate thing in while working with bitmaps, are you sure you need that many bitmaps at once and process all of them (and drop the ones that were not processed?). 而且我不太确定在使用位图时,flowable是否适合使用,您确定一次需要多个位图并处理所有位图(并丢弃未处理的位图吗?)。

OK, I have read your answer and changed my code a little, here is a diagram that illustrates what I want to achieve: 好的,我已经阅读了您的答案并稍稍更改了我的代码,下面的图表说明了我想要实现的目标:

主题图

So my Subject class will process received data on background thread and emit processed items via onNext() method to their Observer. 因此,我的Subject类将在后台线程上处理接收到的数据,并通过onNext()方法将处理后的项目发送给其Observer。 I made a simple Subject that receives Integer object and convert it to String object, here is the code: 我做了一个简单的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;
}

} }

And here is a usage in Activity class: 这是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);
}

Every time that method onButton1() is called I post new random int to subject object and after that I received processed data via onNext() method when it is finished. 每次调用方法onButton1()时,我都会将新的随机整数发布到主题对象,此后,当完成时,我会通过onNext()方法接收处理后的数据。

Is that solution correct and doesn't cause any side effect or memory leaks? 该解决方案是否正确,并且不会引起任何副作用或内存泄漏? Of course I unsubscribe from subject in onStop() method of Activity. 当然,我在Activity的onStop()方法中取消订阅主题。 Maybe there is a better solution to handle this kind of problem in Rxjava? 也许在Rxjava中有更好的解决方案来解决此类问题?

Any further answers will be appreciated :) 任何进一步的答案将不胜感激:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM