为什么 Android 应用在关闭飞行模式时会经历 activity 和片段生命周期方法

Why does an Android app go through the activity and fragment lifecycle methods when airplane mode is turned off

我有一个正在构建的 android 应用程序,发生的一件令人惊讶的事情是,当我在应用程序处于前台时关闭飞行模式时它崩溃了。我尝试在 activity(onPauseonCreateonResume)和显示 activity 的片段的各种生命周期方法中包含日志onCreate。碰巧所有这些回调方法都是按以下顺序调用的:

显示片段

onPause

onPause 在 MainActivity

onCreate 在 MainActivity

onViewCreated 在 MainActivity 的 onCreate

中显示的片段中 显示片段

onStart

onStart 在 MainActivity

显示片段

onResume

并且由于 NullPointerException.

,应用最终在显示的 Fragment 中的 onPause 处崩溃

我试图跟踪所有这些回调,它们是由于在显示的片段 onPause 中,有一些状态我保存在 SharedPreferences 中以在片段恢复时恢复它们,显然它们引发异常。

能否请您帮助我理解当应用程序在前台关闭飞行模式时为什么应用程序会经历所有这些生命周期方法,以及在发生这种情况时防止应用程序崩溃的最佳方法?我浏览了几篇关于这个问题的帖子,但没有找到任何答案。

这是代码

public class MainActivity extends AppCompatActivity{

    public static FragmentManager fragmentManager;
    public static final String LOG_TAG = "LOG_TAG";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.i(LOG_TAG, "Main activity created");
        super.onCreate(savedInstanceState);

        // init airplane mode receiver
        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {

                boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
                if(isAirplaneModeOn){
                    Log.i(LOG_TAG, "Airplane mode turned on");// handle Airplane Mode on
                } else {
                    Log.i(LOG_TAG, "Airplane mode turned off");
                }
            }
        };
        this.registerReceiver(receiver, intentFilter);


        setContentView(R.layout.activity_main);
        fragmentManager = getSupportFragmentManager();
        displayFragment(new MapFragment());
    }


    @Override
    protected void onPause() {
        super.onPause();
        Log.i(LOG_TAG, "Main activity paused");
    }


    @Override
    protected void onResume() {
        super.onResume();
        Log.i(LOG_TAG, "Main activity resumed");
    }


    public void displayFragment(Fragment fragmentActivity){

        // start the transaction
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.fragment_container, fragmentActivity).
                    addToBackStack(fragmentActivity.getClass().getSimpleName()).commit();
    }
}

和片段

public class MapsFragment extends Fragment implements
        OnMapReadyCallback {


    public MapsFragment() {
        // Required empty public constructor
        super();
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_map, container, false);
    }


    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        FrameLayout map_frame = view.findViewById(R.id.map_frame);

        // configure map
        MapView mapFragment = view.findViewById(R.id.map_view);
        mapFragment.onCreate(savedInstanceState);
        mapFragment.onResume();
        mapFragment.getMapAsync(this);
        View mapView = mapFragment.getRootView();
        super.onViewCreated(mapView, savedInstanceState);
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.i(LOG_TAG, "MapFragment resumed");
    }


    @Override
    public void onPause() {
        super.onPause();
        Log.i(LOG_TAG, "Map fragment paused");
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        Log.i(LOG_TAG, "onMapReadyCalled");
        MapsInitializer.initialize(getActivity());
    }
}

在此先感谢您。

我刚刚意识到在我的代码中,我在 MainActivity 的 onCreate 中显示了 MapFragment,这导致应用崩溃。当应用程序处于前台时关闭飞行模式时,我无法让应用程序不通过生命周期方法。然而,在我的 MainActivity 的 onStart 中显示 MapFragment 解决了这个问题。

@Override
    protected void onStart() {
        super.onStart();
        if (getCurrentFragment() == null) {
            displayFragment(new MapFragment(), null, false, true);
        }
    }

其中 getCurrentFragment() 是我为 return 当前显示的片段定义的方法。