即使订阅了多个observable,也只在RxJava中触发了一个事件

时间:2016-10-17 18:07:32

标签: android rx-java

我想了解RxJava。我写了一小段代码,将列表文件上传到firebase服务器。我写了两个可观察量: 1. ImageUploaderService.java:上传单个文件并通知状态 2. AllImageUploaderService.java:创建新的单个文件上传器并将其提供给一个要上传的文件路径。收集所有上传者的结果并通知上传文件的链接。

我的问题是,即使在AllImageUploaderService中订阅了ImageUploaderService的每个实例,也只触发了一个OnNext事件。我该如何解决?

AllImageUploaderService.java

    public class AllImageUploaderService extends Subscriber<String>{
    private BehaviorSubject<String[]> uploadService;
    private ArrayList<String> uploadedFiles;
    private int expectedCount;
    private int actualCount;

    public Observable<String[]> uploadImages(final String[] fileNames, final StorageReference imagesRef,
        final String[] chosenImage) {
        expectedCount = fileNames.length;
        uploadedFiles = new ArrayList<>(fileNames.length);

        uploadService = BehaviorSubject.create();

        Observable<String[]> observable = Observable.create(new Observable.OnSubscribe<String[]>(){
            @Override
            public void call(Subscriber<? super String[]> subscriber) {
                for (int i = 0; i < fileNames.length; i++) {
                    ImageUploaderService imageUploaderService=new ImageUploaderService();
                    Observable<String> observable= imageUploaderService.uploadImage(fileNames[i],imagesRef,chosenImage[i]);
                    observable.subscribe(AllImageUploaderService.this);
                }
            }
        });
        observable.subscribe(uploadService);
        return uploadService;
    }

    @Override
    public void onCompleted() {
        actualCount++;
        if(expectedCount==actualCount) {
            String[] retValue = new String[uploadedFiles.size()];
            uploadedFiles.toArray(retValue);
            uploadService.onNext(retValue);
            uploadService.onCompleted();
        }
    }

    @Override
    public void onError(Throwable e) {
        Utils.logE(this,"Error",e);
    }

    @Override
    public void onNext(String s) {
        uploadedFiles.add(s);
    }
}

ImageUploaderService.java

public class ImageUploaderService implements OnFailureListener, OnSuccessListener<UploadTask.TaskSnapshot> {

    private BehaviorSubject<String> uploadSubject;

    public Observable<String> uploadImage(final String fileNames, final StorageReference imagesRef,
        final String chosenImage) {

        uploadSubject = BehaviorSubject.create();
        Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {               
                StorageReference spaceRef = imagesRef.child(fileNames);
                UploadTask uploadTask = spaceRef.putFile(UriUtil.generatorUri(chosenImage, UriUtil.LOCAL_FILE_SCHEME));
                uploadTask.addOnFailureListener(ImageUploaderService.this);
                uploadTask.addOnSuccessListener(ImageUploaderService.this);
            }
        });
        observable.subscribe(uploadSubject);
        return uploadSubject;
    }

    @Override
    public void onFailure(@NonNull Exception exception) {
        uploadSubject.onError(exception);
        uploadSubject.onCompleted();
    }

    @Override
    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
        Uri downloadUrl = taskSnapshot.getDownloadUrl();
        uploadSubject.onNext(downloadUrl.toString());
        uploadSubject.onCompleted();
    }
}

如果你能让我知道更好的方法,那就太好了。

1 个答案:

答案 0 :(得分:0)

无需过度复杂化:

public Observable<String> uploadImages(final String[] fileNames, final StorageReference imagesRef,
    final String[] chosenImage) {

    return Observable
        .range(0, fileNames.length)
        .flatMap(i -> new ImageUploaderService()
             .uploadImage(fileNames[i],imagesRef,chosenImage[i]))
}

当一切都结束时,你需要它作为一个集合吗? .toList()

另外,我认为你不需要ImageUploaderService中的主题:

public class ImageUploader implements OnFailureListener, OnSuccessListener<UploadTask.TaskSnapshot> {

  public static Observable<String> uploadImage(final String fileNames, final StorageReference imagesRef,
    final String chosenImage) {

    Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {               
            ImageUploader uploader = new ImageUploader(subscriber);
            StorageReference spaceRef = imagesRef.child(fileNames);
            UploadTask uploadTask = spaceRef.putFile(UriUtil.generatorUri(chosenImage, UriUtil.LOCAL_FILE_SCHEME));
            uploadTask.addOnFailureListener(uploader);
            uploadTask.addOnSuccessListener(uploader);
        }
    });
    return observable;
  }

  /////////

  private final Subscriber<String> subscriber;

  private ImageUploader(final Subscriber<String> subscriber) {
    this.subscriber = subscriber;
  }

  @Override
  public void onFailure(@NonNull Exception exception) {
    if(subscriber.isUnsubscribed()) return;
    subscriber.onError(exception);
  }

  @Override
  public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
    if(subscriber.isUnsubscribed()) return;
    Uri downloadUrl = taskSnapshot.getDownloadUrl();
    uploadSubject.onNext(downloadUrl.toString());
    uploadSubject.onCompleted();
  }
}

注意,onComplete()之后不要发出onError(),其中任何一个都是Observables的终端状态,并且要么是最后一个..