【问题标题】:android - Replacing fragment in the middle of retrofit calls cause fragment transaction to produce awkward resultandroid - 在改造调用中间替换片段会导致片段事务产生尴尬的结果
【发布时间】:2017-03-18 14:30:34
【问题描述】:

我有问题。在我的 android 应用程序中,我有一个执行改造调用的片段。在片段内部,有一个按钮可以导航到下一个片段。如果我在改造调用完成后单击按钮,则没有问题。但是,当我在调用执行时单击按钮时出现问题。片段被替换但不完全。正如您在我上传的图片中看到的那样,按钮停留在替换片段的顶部。

通过在屏幕上执行滑动刷新来调用改造调用,如果在这样做的过程中我更改为另一个片段,结果可以在下面看到(在这种情况下,我点击了底部的按钮)

虽然预期的结果应该是这样的。 (另请注意,虽然尴尬的结果显示前一个片段位于替换它的片段的顶部,但前一个片段的 UI 小部件没有响应,而其下方的小部件是可点击的。

第一个片段的 xml(显示出勤列表)

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/refresh_attendance"
android:layout_height="match_parent"
android:layout_width="match_parent">

<LinearLayout
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/attendance_list"
        android:layout_weight="9"
        android:name="proj.com.fyp.AttendanceFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        app:layoutManager="LinearLayoutManager"
        tools:context="proj.com.fyp.AttendanceFragment"
        tools:listitem="@layout/fragment_attendance" />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/button_appeal_attendance"
            android:text="@string/appeal_attendance"/>
</LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout>
@OnClick(R.id.button_appeal_attendance)
public void showAppealFragment() {
    mListener.onListFragmentInteraction(null);
}

执行 api 调用的方法(也在 AttendanceFragment.java 中)

private void loadData() {
    mRefresh.setRefreshing(true);
    Log.i(TAG, "loadData: ");
    RequestInterface request = RestHelper.getClient();
    request.getOverallAttendancesRx("TP035763")
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.newThread())
            .subscribeWith(disposableObserver);
}

disposableObserver 的定义如下:

    disposableObserver = new DisposableObserver<List<ModuleOverallAttendance>>() {
        @Override
        public void onNext(List<ModuleOverallAttendance> value) {
            try (Realm realm = Realm.getDefaultInstance()){
                Log.i(TAG, "onNext: " + (Looper.myLooper() == Looper.getMainLooper()));
                Log.i(TAG, "onNext: ");
                realm.executeTransaction(r -> {
                    r.insertOrUpdate(value);
                });
            } catch(Exception e) {
                Log.e(TAG, "onNext: ", e);
                onError(e);
            }
        }

        @Override
        public void onError(Throwable e) {
            mRefresh.setRefreshing(false);
            Log.e(TAG, "onError: ", e);
        }

        @Override
        public void onComplete() {
            Log.i(TAG, "onComplete: " + (Looper.myLooper() == Looper.getMainLooper()));
            try (Realm realm = Realm.getDefaultInstance()){
                mRefresh.setRefreshing(false);
                moduleOverallAttendances = realm.copyFromRealm(realm.where(ModuleOverallAttendance.class).findAll());
                mAdapter.setmValues(moduleOverallAttendances);
                Log.i(TAG, "onComplete: a");
                Log.i(TAG, "onComplete: " + Thread.currentThread().getName());
            } catch(Exception e) {
                Log.e(TAG, "onComplete: ", e);
            }
        }
    };

实际的片段事务在 MainActivity.java 中处理

@Override
public void onListFragmentInteraction(ModuleOverallAttendance item) {
    Log.i("onFragmentInteraction", "DummyItem: " + item);
    if (item.getModuleId() == null) {
        mFragmentTransaction = mFragmentManager.beginTransaction();
        mFragmentTransaction
                .addToBackStack(null)
                .replace(R.id.fragment_container, AppealAttendanceFragment.newInstance(),"AppealAttendance")
                .commit();
        setTitle("Appeal Attendance");
        toggleHamburger(false);
    } else {
        mFragmentTransaction = mFragmentManager.beginTransaction();
        mFragmentTransaction
                .addToBackStack(null)
                .replace(R.id.fragment_container, AttendanceDetailsFragment.newInstance("", ""),"AttendanceDetails")
                .commit();
        setTitle(item.getModuleId());
        toggleHamburger(false);
    }
}

我在 onDestroy 方法中取消请求

@Override
public void onDestroyView() {
    super.onDestroyView();
    Log.i(TAG, "onDestroyView: ");
    mRefresh.setRefreshing(false);
    unbinder.unbind();
    disposableObserver.dispose();
    realm.close();
}

【问题讨论】:

  • 请分享一些代码
  • @KlitosG。已添加代码,如有需要,请随时请求。
  • 如果在 onListFragmentInteraction 方法中,您的“错误”案例是否成功?为什么在您的第一笔交易中删除现有的 Fragment 然后添加另一个?使用替换而不是添加和删除删除行。我认为您不能在事务中同时拥有 remove(...) 和 add(...) 。如果我是对的,那么只有 add 有效,你会看到两个 Fragments 一个在另一个之上
  • 在onListFragmentInteraction方法里面是成功的。我刚把它改成replace,结果还是一样。
  • 更新了代码和图片@KlitosG。

标签: android android-layout android-fragments android-recyclerview retrofit2


【解决方案1】:

问题在于 SwipeRefreshLayout。从这个link 可以使用一些解决方法来解决这个问题。就我而言,在onDestroyView() 中调用mRefresh.removeAllViews 就可以了。

【讨论】:

    猜你喜欢
    • 2018-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多