尝试在 bottomSheet 上启动片段时应用程序崩溃

App crashes when trying to initiate fragment on bottomSheet

问题可能出在我的架构上,但我不太确定。

问题来了。

我有一个 activity 可以启动一个片段。 activity 的 .xml 文件包含一个 FrameLayout 片段(我们称它为 FragmentA)和一个作为 bottomSheet 的 CoordinatorLayout

在 bottomSheet 中,还有另一个 FrameLayout 用于另一个片段(我们称之为 FragmentB)。

我想要完成的是,当 bottomSheet 一直展开时,然后在其 FrameLayout 上,我启动 FragmentB。

为了节省 space,我决定在另一个名为 BottomSheetManagement

的单独 class 中处理与 bottomSheet 相关的所有内容

然后,我将 BottomSheetCallback 附加到我的 bottomSheet 上,当它的状态为 expanded 时,我调用方法 initiateFragment(currentFragmentID, WorkFragment.newInstance()).

此方法是在名为 FragmentHost 的接口中创建的,该接口在我的 mainActivity 中实现。因此,当我调用 initiateFragment(currentFragmentID, WorkFragment.newInstance()) 时,我实际上是在我的 mainActivity 中调用同名方法。

但是,当我测试我的应用程序并将我的 bottomSheet 拖到顶部时,我收到错误消息:IllegalStateException : Activity has been destroyed.

我不明白如何在 initiateFragment(currentFragmentID, WorkFragment.newInstance()) 中确保 activity 仍然存在(通过 !isfinishing() && !isDestroyed()

我能做什么?

MainActivity.java

public class MainActivity extends AppCompatActivity implements FragmentHost {

    //BottomSheet Variables
    View bottomSheet;
    RelativeLayout bottomSheetHeader;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.container, MainFragment.newInstance())
                    .commitNow();
        }
        //Handle BottomSheet
        bottomSheet = findViewById(R.id.bottom_sheet);
        bottomSheetHeader = findViewById(R.id.BottomSheet_Layout_Header);
        bottomSheetManagement();
    }
    private void bottomSheetManagement(){
        BottomSheetManagement bottomSheetManagement = new BottomSheetManagement();
        bottomSheetManagement.handleBottomSheet(R.id.work_container, bottomSheet, bottomSheetHeader);
    }

    @Override
    public void initiateFragment(int containerID, Fragment fragment) {
        if (!isFinishing() && !isDestroyed()){
            getSupportFragmentManager().beginTransaction()
                    .replace(containerID, fragment)
                    .commit();
        }
    }
}

BottomSheetManagement.java

public class BottomSheetManagement {
    private BottomSheetBehavior bottomSheetBehavior;
    private int activeBottomSheetState;

    public void handleBottomSheet(int currentFragmentID, View bottomSheet, RelativeLayout bottomSheetHeader){
        FragmentHost fragmentHost = new MainActivity();
        bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
        bottomSheetHeader.setOnClickListener(v -> {
            switch (bottomSheetBehavior.getState()){
                case BottomSheetBehavior.STATE_COLLAPSED:
                    bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                    break;
                case BottomSheetBehavior.STATE_EXPANDED:
                    bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
                    break;
            }
        });
        bottomSheetBehavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                switch (newState){
                    case BottomSheetBehavior.STATE_EXPANDED:
                        fragmentHost.initiateFragment(currentFragmentID, WorkFragment.newInstance());
                        break;
                }
            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {

            }
        });
    }
}

main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout
            android:id="@+id/bottom_sheet"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="?attr/colorSurface"
            app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
            app:behavior_hideable="false"
            app:behavior_peekHeight="50dp"
            android:orientation="vertical">
            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="?android:attr/listDivider" />
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="16dp"
                android:id="@+id/BottomSheet_Layout_Header">
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:text="@string/app_name"
                    style="?attr/titleTextAppearance"
                    android:textColor="?attr/colorOnSurface"/>
            </RelativeLayout>

            <FrameLayout
                android:id="@+id/work_container"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

        </LinearLayout>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
</RelativeLayout>

您应该将已经创建的 MainActivity 的上下文分配给 fragmentHost,而不是通过编写 'new MainActivivty()' 创建一个新的上下文,这会破坏您调用 BottomSheetManagement 的先前的 MainActivity 并创建一个新的。 将您的 BottomSheetManagement 代码修改为,

public class BottomSheetManagement {
    private BottomSheetBehavior bottomSheetBehavior;
    private int activeBottomSheetState;
    private FragmentHost fragmentHost;

    public void handleBottomSheet(FragmentHost context, int currentFragmentID, View bottomSheet, RelativeLayout bottomSheetHeader){
        fragmentHost = (FragmentHost) context;
        bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
        bottomSheetHeader.setOnClickListener(v -> {

并在 MainActivity 代码中,将方法更改为

private void bottomSheetManagement(){
        BottomSheetManagement bottomSheetManagement = new BottomSheetManagement();
        bottomSheetManagement.handleBottomSheet(this, R.id.work_container, bottomSheet, bottomSheetHeader);
    }