java - mSubscription.unsubscribe onCreate 与 Activity 中的 onDestroy 的工作方式相同吗?

标签 java android rx-java unsubscribe

  1. rxjava mSubscription.unsubscribe onCreate 的工作方式与 Activity 中的 onDestroy 相同吗?

  2. 它是否会以相同的方式工作并通过将其放在 onCreate 中作为 subscription.subscribeOn().observeOn().subscribe().unsubscribe 取消订阅以防止内存泄漏 因为 Activity 不断被调用来填充下一个 fragment 并弹出回堆栈。如果 mSubscription.unsubscribe 在 Activity 的 onDestroy 中完成,则会抛出 RunTimeException: Unable to destroy Activity due to NullPointerException

  3. 我在这里错过了一些生命周期问题吗?

谢谢!

    private ViewPager viewPager;
    private TabLayout tabLayout;
    private int mPosition;
    private String id;
    private Subscription mSubscription;
    private Context mContext;
    private RealmResults<Experience> realmResults; 
    private String animateExtraColumnName, tag;
    private Boolean automaticUpdate, animateResults;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_employment);

        User currentUser = AppDelegate.getCurrentUser();
        assert currentUser != null;
        mEmployee = getRealm().where(Employee.class).equalTo("user.id", currentUser.getId()).findFirst();


            //Server returns Experience's ID
            if (employeeExperience == null) {

                AccessToken accessToken = currentUser.getAccessTokenAsTokenType(AppDelegate.getContext(), "Bearer");
               employeeExperienceAPIOAuth2Call apiCall = new employeeExperienceAPIOAuth2Call(AppDelegate.getContext(), accessToken);

                Observable<ResponseEmployeeExperience> postEmployeeExperienceObservable = apiCall.postEmployeeExperiencesRX();

                mSubscription = postEmployeeExperienceObservable
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe((data) -> {
                            Log.d(TAG, "onCreate: Subscribe ");
                         employeeExperience = data.getEmployeeExperience();
                            Log.d(TAG, "onCreate: employeeExperience.getId()");

                            getRealm().beginTransaction();
                            getRealm().copyToRealmOrUpdate(employeeExperience);
                            // This adds the new employeeExperience object into the EmployeeExperiences RealmList
                            employee.employeeExperiences.add(employeeExperience);
                            getRealm().commitTransaction();
                            getRealm().close();

                            //unsubscribe here because the activity doesnt close itself to begin with?
                            mSubscription.unsubscribe();
                            Log.d(TAG, "onCreate: Unsubscribe: ");

                            // prepare data needed by our fragment
                            FragmentAddOrUpdateEmploymentHistory addEmploymentHistoryFragment = new FragmentAddOrUpdateEmploymentHistory();

                            FragmentManager fm = getSupportFragmentManager();
                            fm.beginTransaction().replace(R.id.edit_frame_layout, addEmploymentHistoryFragment, "EDIT_FRAGMENT").commit();

                        }, (error) -> {
                            // TODO do whatever error handling we need to do here
                            Log.d(TAG, "onCreate: postEmployeeExp error");
                            error.printStackTrace();
                        });
            }

        } else if (employee.getEmployeeExperiences() != null) {
            employeeExperience = getRealm().where(employeeExperience.class).equalTo("id", id).findFirst();

            FragmentAddOrUpdateEmploymentHistory addEmploymentHistoryFragment = new FragmentAddOrUpdateEmploymentHistory();

            FragmentManager fm = getSupportFragmentManager();
            fm.beginTransaction().replace(R.id.edit_frame_layout, addEmploymentHistoryFragment, "EDIT_FRAGMENT").commit();
        }

        ImageButton checkButton = (ImageButton) findViewById(R.id.edit_toolbar_check);
        checkButton.setOnClickListener(this);

        ImageButton crossButton = (ImageButton) findViewById(R.id.edit_toolbar_cross);
        crossButton.setOnClickListener(this);

    }

    @Override
    protected void onStart() {
        super.onStart();
    }

    @Override
    public void onClick(View view) {

        Fragment editFragments = getSupportFragmentManager().findFragmentByTag("EDIT_FRAGMENT");

        switch (view.getId()) {

            case R.id.edit_toolbar_check:
                if (editFragments instanceof FragmentEditDate) {
                    Log.d(TAG, "onClick: editdate ");
                    getSupportFragmentManager().popBackStack();
                } else if (editFragments instanceof FragmentSalary){
                    Log.d(TAG, "onClick: salary ");
                    getSupportFragmentManager().popBackStack();
                } else if (editFragments instanceof FragmentAddOrUpdateEmploymentHistory) {
                    Log.d(TAG, "onClick: employmenthistory ");
                    finish();
                } else if (editFragments instanceof FragmentSingleChoice) {
                    Log.d(TAG, "singlechoice  " );
                    getSupportFragmentManager().popBackStack();
                }
                else if (editFragments instanceof FragmentMultipleChoice) {
                    Log.d(TAG, "multiplechoice  " );
                    getSupportFragmentManager().popBackStack();
                }
                break;


            case R.id.edit_toolbar_cross:
                if (editFragments instanceof FragmentAddOrUpdateEmploymentHistory) {

                            getRealm().beginTransaction();
                            employeeExperience.DELETE();
                            getRealm().commitTransaction();
                            getRealm().close();
                        }
                        finish();
                    } else {
                        finish();

                    }
                } else {
                    getSupportFragmentManager().popBackStack(); }
                break;

        }
    }

最佳答案

简而言之 - 一旦您订阅 Observable您已准备好接收来自它的通知并对其使用react( onNextonErroronComplete )。同样在大多数情况下(对于冷 Observables),这实际上是 Observable 的触发点。开始发射元素。

Unsubscribing来自 Observable 意味着您不再有兴趣接收任何进一步的通知。您需要unsubscribe当你不再想接收任何东西时,类似于如何释放 Activity 的 onDestroy() 中的任何资源方法。当然,与 Activity 生命周期的并行只是为了比较 - 订阅/取消订阅过程是完全独立的事情。

您可以详细阅读 subscribingunsubscribing意味着[此处][1] [1]:http://reactivex.io/documentation/contract.html

也就是说,对您的代码有一些具体建议:

您当前在 Android 主线程上执行了太多操作。我建议将所有与实际相关的内容作为 RX 链的一部分移动,而不是在 onNext() 中。处理程序位于 subscribe(...) 。这样它将在 io 上执行线。像这样的东西:

...
mSubscription = postEmployeeExperienceObservable
            .subscribeOn(Schedulers.io())
            .doOnNext(data -> saveDataToRealm(data))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe((data) -> {
                // prepare data needed by our fragment
                FragmentAddOrUpdateEmploymentHistory addEmploymentHistoryFragment = new FragmentAddOrUpdateEmploymentHistory();

                FragmentManager fm = getSupportFragmentManager();
                fm.beginTransaction().replace(R.id.edit_frame_layout, addEmploymentHistoryFragment, "EDIT_FRAGMENT").commit();

            }, (error) -> {
                // TODO do whatever error handling we need to do here
                Log.d(TAG, "onCreate: postEmployeeExp error");
                error.printStackTrace();
            });
}

private Data saveDataToRealm(Data data) {
    employeeExperience = data.getEmployeeExperience();
    Log.d(TAG, "onCreate: employeeExperience.getId()");

    getRealm().beginTransaction();
    getRealm().copyToRealmOrUpdate(employeeExperience);
    // This adds the new employeeExperience object into the EmployeeExperiences RealmList
    employee.employeeExperiences.add(employeeExperience);
    getRealm().commitTransaction();
    getRealm().close();
}

就取消订阅而言 - 如果您确实想要unsubscribe来自onNext()内事件,更好的策略是通过 Subscriber<Data> 订阅然后使用它的 unsubscribe()方法。换句话说 - 你不会调用 mSubscription.unsubscribe()而是 this.unsubscribe() .

mSubscription = postEmployeeExperienceObservable
            .subscribeOn(Schedulers.io())
            .doOnNext(data -> saveDataToRealm(data))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<Data>() {

                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(Data data) {
                    ...
                    this.unsubscribe();
                }
            });

综上所述,我认为您真的不需要 unsubscribe来自onNext()方法在你的情况下,相反你可以在 onDestroy() 中这样做,当然检查之前是否创建了订阅:

@Override
protected void onDestroy() {
    super.onDestroy();
    if (mSubscription != null) {
        mSubscription.unsubscribe();
    }
}

关于java - mSubscription.unsubscribe onCreate 与 Activity 中的 onDestroy 的工作方式相同吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41709934/

相关文章:

java - Swing 常数与组件常数

带有 ActionListener 的 Java 动画

java - 从文件中读取。安卓、Java

android - 如何在多风格应用程序中添加多个 Google Maps API 配置

rx-java - 使用 RXJava 防止快速点击

java - 如何摆脱使用 RxJava 实现 Firebase 注册的 instanceOf

java - 在 Java 冒险游戏中跟踪房间?

java - 在java中查找XML文件中特定属性的值

android - RxJava 类立即调度程序

android - 由于flatMap未完成,因此FlatMap失败后RxJava使用toList