【问题标题】:Android Debounce / TakeLast RxJava Never Receives Last Item After OnCompleted()Android Debounce / TakeLast RxJava 在 OnCompleted() 之后从不接收最后一个项目
【发布时间】:2016-02-06 16:07:04
【问题描述】:

背景

我下面的代码旨在防止每次用户选择图像时都上传图像。本质上,我的目标是在开始上传之前创建“冷静”期,以节省用户的电池和数据。

问题

代码运行良好,除非 Fragment 被销毁 OnComplete 在发出最后一项之前取消订阅订阅者,因此永远不会上传最新选择的图像。我想这是正确的行为,但我不知道如何解决它。

我对@9​​87654321@ 的运气也很差,不得不改用TakeLast。结果是我想要的。

也许 AsyncSubject 会更好,但我不确定前进的方向。谢谢。

public class MyFragment extends Fragment {

    private static final int DO_STUFF_REQUEST_CODE = 123173;
    private static final int DEBOUNCE_TIME = 20;

    private PublishSubject<Object> startPhotoUploadPublishSubject;

    @Bind(R.id.photo)
    ImageView photo;

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        startPhotoUploadPublishSubject = PublishSubject.create();


        startPhotoUploadPublishSubject
            .observeOn(AndroidSchedulers.mainThread())
            .takeLast(DEBOUNCE_TIME, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
            .subscribe(new StartUploadPhotoIntentServiceSubscriber());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, 
        ViewGroup container, Bundle savedInstanceState) {
...
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        startPhotoUploadPublishSubject.onCompleted();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (resultCode == Activity.RESULT_OK) {

            if (requestCode == Crop.REQUEST_CROP) {

                startPhotoUploadPublishSubject.onNext(null);
            }
        }
    }

    @OnClick(R.id.photo)
    public void choosePhotoSelected() {

        Intent chooserIntent = ...etc
        startActivityForResult(chooserIntent, DO_STUFF_REQUEST_CODE);
    }

    private class StartUploadPhotoIntentServiceSubscriber extends Subscriber<Object> {

        @Override
        public void onCompleted() {
            //do nothing
            Toast.makeText(getActivity(), "ON COMPLETE", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onError(Throwable e) {
            //we shouldnt have any errors
        }

        @Override
        public void onNext(Object object) {
            Toast.makeText(getActivity(), "ON NEXT", Toast.LENGTH_SHORT).show();
            Intent uploadPhotoIntent = new Intent(
                getActivity(), UploaderIntentService.class);
            getActivity().startService(uploadPhotoIntent);
        }
    }
}

【问题讨论】:

  • AsyncSubject 而不是 PublishSubject 听起来更好,但我不太了解 Android 生命周期;由于您在 onDestroy 中调用 onCompleted(),我认为 getActivity() 不再起作用。
  • 只是为了做到这一点:您是要上传多个项目 - 如果中间经过了足够的时间 - 还是只上传一个? takeLast() 让我假设您只想上传一项,但您的文字让我假设您想要上传多项。
  • 我最初的计划是上传多个项目,因为用户可能会改变主意但不会离开活动,因此允许多个项目会更实用。我希望使用 debounce 而不是 last 但它不会触发 onNext
  • 使用在所有内容上传之前一直运行的服务。您需要将其与 UI 生命周期分离。您无能为力。
  • 我想我可以将项目添加到我的意图服务中,并检查是否已经存在具有相同签名的内容,或者相同请求的项目是否处于待处理状态,然后取消它们。谢谢大家的帮助!

标签: android rx-java onactivityresult debouncing


【解决方案1】:

我假设发生的事情是碎片在 20 秒的弹跳之前被摧毁,对吧?

调用onCompleted时,订阅者的onComplete方法也会被调用,因此onNext不会被执行,因为订阅者没有调用它。

这个怎么样?

@Override
public void onDestroy() {
    super.onDestroy();
    startPhotoUploadPublishSubject.onNext();
    startPhotoUploadPublishSubject.onCompleted();
}

它可能适用于您的情况。我认为对于这种情况,AsyncSubject 或 PublishSubject 之间没有区别。

希望对你有帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-06
    • 1970-01-01
    • 2018-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多