关闭飞行模式后,为啥 Android 应用程序会通过 Activity 和 Fragment 生命周期方法
Posted
技术标签:
【中文标题】关闭飞行模式后,为啥 Android 应用程序会通过 Activity 和 Fragment 生命周期方法【英文标题】:Why does an Android app go through the activity and fragment lifecycle methods when airplane mode is turned off关闭飞行模式后,为什么 Android 应用程序会通过 Activity 和 Fragment 生命周期方法 【发布时间】:2021-03-21 23:55:20 【问题描述】:我正在构建一个 android 应用程序,发生的一件令人惊讶的事情是,当我在应用程序处于前台时关闭飞行模式时它会崩溃。我尝试在活动的各种生命周期方法(onPause
、onCreate
、onResume
)和显示活动onCreate
的片段中包含日志。碰巧所有这些回调方法都按以下顺序调用:
显示片段中的onPause
onPause
在 MainActivity
onCreate
在 MainActivity 中
onViewCreated
在 MainActivity 的 onCreate
中显示的片段中
显示片段中的onStart
MainActivity 中的onStart
显示片段中的onResume
由于NullPointerException
,应用程序最终在显示的片段中的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());
非常感谢您。
【问题讨论】:
为什么不在崩溃后立即读取 Stacktrace 日志? 99% 的时间都是不言自明的...... 【参考方案1】:我刚刚意识到,在我的代码中,我在 MainActivity 的 onCreate 中显示了 MapFragment,导致应用崩溃。当应用程序处于前台时关闭飞行模式时,我无法让应用程序不通过生命周期方法。但是在我的 MainActivity 的 onStart 中显示 MapFragment 解决了这个问题。
@Override
protected void onStart()
super.onStart();
if (getCurrentFragment() == null)
displayFragment(new MapFragment(), null, false, true);
其中 getCurrentFragment() 是我定义的用于返回当前显示的片段的方法。
【讨论】:
以上是关于关闭飞行模式后,为啥 Android 应用程序会通过 Activity 和 Fragment 生命周期方法的主要内容,如果未能解决你的问题,请参考以下文章
为啥飞行模式开启时 CLLocationManager 不会失败?