在后台丢失 MainActivity
Loosing MainActivity on Background
每次应用程序进入后台,RAM 开始填满,应用程序开始丢失变量(如果我没记错的话,这是 Android 的正常行为,它会丢失变量的实例)
当我从后台恢复应用程序时,应用程序崩溃,因为我丢失了 MainActivity。
如果根本没有 activity,有没有办法重新启动这个 activity?
是一个模棱两可的问题,但我发现这个问题,但我认为不是最好的选择
ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
if(taskList.get(0).numActivities == 1 &&
taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())) {
Log.i(TAG, "This is last activity in the stack");
}
我失去了完整的 activity,我可以得到 activity
@Override
public void onAttach(Activity activity) {
LocalNotification.registerReceiver(reloadReceiver, LocalNotification.RELOAD_CARTMG);
try {
mListener = (OnFragmentInteractionListener) activity;
MainActivity ma = (MainActivity)activity; //THIS IS LOOSE
ma.openMyList = false;
ma.openMyAddress = false;
ma.hideSearchButton();
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener");
}
super.onAttach(activity);
}
这是应用内的日志
com.XXXX.mg E/Uncaught Exception detected in thread {}: Unable to start activity ComponentInfo{com.XXXX.mg/com.XXXX.view.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.XXXX.view.MainActivity.showShoppingCartIcon()' on a null object reference
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.XXXX.mg/com.XXXX.view.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.XXXX.view.MainActivity.showShoppingCartIcon()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2426)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5443)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.XXXX.view.MainActivity.showShoppingCartIcon()' on a null object reference
at com.XXXX.view.shoppingCart.ShoppingCartFragment.onDetach(ShoppingCartFragment.java:411)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1202)
at android.support.v4.app.FragmentManagerImpl.removeFragment(FragmentManager.java:1349)
at android.support.v4.app.BackStackRecord.popFromBackStack(BackStackRecord.java:915)
at android.support.v4.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1722)
at android.support.v4.app.FragmentManagerImpl.run(FragmentManager.java:593)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:339)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:602)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1260)
at android.app.Activity.performStart(Activity.java:6261)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2389)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5443)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
我不确定你的应用程序崩溃是否只是因为你丢失了 MainActivity,你应该在编码时预料到这种行为,使用 @pablobu 建议的 onSaveInstanceState 是正确的方法。
我们能看到日志吗?如果您正在丢失实例的状态,那没关系,您应该保存这些状态并恢复它们 Recreating an Activity is it because of Fragments? you can also save those too, Handling Fragments Tutorial 这是一本好书。
拜托,你能给我们你的 logcat 输出,这可能对我们了解真正发生的事情有很大帮助。
编辑
使用您的 Logcat 编辑,尝试查看片段生命周期,onAttach 比 onActivityCreated() 先执行,因此如果您的 Activity 已经被销毁,您的 onAttach 方法不会有您的 activity,您应该等到 Activity 被 重新创建 。
此外,您还有
super.onAttach(activity);
在代码块的末尾,将其放在代码块之前。
/**
This method was deprecated in API level 23.
Use onAttach(Context) instead.
*/
@Override
public void onAttach(Context context) {
super.onAttach(context);
MainActivity mainActivity;
if (context instanceof Activity) {
mainActivity = (MainActivity) context;
try {
mListener = (OnFragmentInteractionListener) mainActivity;
/**
Since you are getting a reference and accesing attributes you should be careful
with NullPointerException, check if not null first.
Or better yet refactor a little your code using an interface to handle this behaviour or use
the one you already created and just tell the activity what to do.
*/
/*if(mainActivity != null) {
ma.openMyList = false;
ma.openMyAddress = false;
ma.hideSearchButton();
}*/
} catch (ClassCastException e) {
throw new ClassCastException(mainActivity.getClass().getSimpleName() + " must implement OnFragmentInteractionListener");
}
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//since your Listener is global use mListener behaviour that I suggested here.
if (mListener != null){
mListener.openListOfSomething(false);
mListener.hideSearch();
}
}
您可以使用 Bundle savedInstatceState,它在 OnCreate 和类似方法中给出:
private String aVariable;
@Override
public void onCreate (Bundle savedInstantceState) {
super.onCreate(savedInstanceState);
// Get the variable from savedInstanceState, if it isn't empty.
// If it is empty, it could be the first Activity run.
try {
aVariable = savedInstanceState.get("Key");
} catch (NullPointerException e) {
aVariable = "Baum";
}
}
@Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
outState.putString(aVariable, "Key");
}
这些方法在第一个 运行 上将变量 "aVariable" 设置为 "Baum"
(NullPointerException,因为 "Key" 没有字符串)。
稍后,当 Activity 将被销毁时,将调用 onSaveInstanceState。在那里,您将变量 (aVariable) 保存在键 ("Key") 下。
每次应用程序进入后台,RAM 开始填满,应用程序开始丢失变量(如果我没记错的话,这是 Android 的正常行为,它会丢失变量的实例)
当我从后台恢复应用程序时,应用程序崩溃,因为我丢失了 MainActivity。
如果根本没有 activity,有没有办法重新启动这个 activity? 是一个模棱两可的问题,但我发现这个问题,但我认为不是最好的选择
ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
if(taskList.get(0).numActivities == 1 &&
taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())) {
Log.i(TAG, "This is last activity in the stack");
}
我失去了完整的 activity,我可以得到 activity
@Override
public void onAttach(Activity activity) {
LocalNotification.registerReceiver(reloadReceiver, LocalNotification.RELOAD_CARTMG);
try {
mListener = (OnFragmentInteractionListener) activity;
MainActivity ma = (MainActivity)activity; //THIS IS LOOSE
ma.openMyList = false;
ma.openMyAddress = false;
ma.hideSearchButton();
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener");
}
super.onAttach(activity);
}
这是应用内的日志
com.XXXX.mg E/Uncaught Exception detected in thread {}: Unable to start activity ComponentInfo{com.XXXX.mg/com.XXXX.view.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.XXXX.view.MainActivity.showShoppingCartIcon()' on a null object reference
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.XXXX.mg/com.XXXX.view.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.XXXX.view.MainActivity.showShoppingCartIcon()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2426)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5443)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.XXXX.view.MainActivity.showShoppingCartIcon()' on a null object reference
at com.XXXX.view.shoppingCart.ShoppingCartFragment.onDetach(ShoppingCartFragment.java:411)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1202)
at android.support.v4.app.FragmentManagerImpl.removeFragment(FragmentManager.java:1349)
at android.support.v4.app.BackStackRecord.popFromBackStack(BackStackRecord.java:915)
at android.support.v4.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1722)
at android.support.v4.app.FragmentManagerImpl.run(FragmentManager.java:593)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:339)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:602)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1260)
at android.app.Activity.performStart(Activity.java:6261)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2389)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5443)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
我不确定你的应用程序崩溃是否只是因为你丢失了 MainActivity,你应该在编码时预料到这种行为,使用 @pablobu 建议的 onSaveInstanceState 是正确的方法。
我们能看到日志吗?如果您正在丢失实例的状态,那没关系,您应该保存这些状态并恢复它们 Recreating an Activity is it because of Fragments? you can also save those too, Handling Fragments Tutorial 这是一本好书。
拜托,你能给我们你的 logcat 输出,这可能对我们了解真正发生的事情有很大帮助。
编辑
使用您的 Logcat 编辑,尝试查看片段生命周期,onAttach 比 onActivityCreated() 先执行,因此如果您的 Activity 已经被销毁,您的 onAttach 方法不会有您的 activity,您应该等到 Activity 被 重新创建 。
此外,您还有
super.onAttach(activity);
在代码块的末尾,将其放在代码块之前。
/**
This method was deprecated in API level 23.
Use onAttach(Context) instead.
*/
@Override
public void onAttach(Context context) {
super.onAttach(context);
MainActivity mainActivity;
if (context instanceof Activity) {
mainActivity = (MainActivity) context;
try {
mListener = (OnFragmentInteractionListener) mainActivity;
/**
Since you are getting a reference and accesing attributes you should be careful
with NullPointerException, check if not null first.
Or better yet refactor a little your code using an interface to handle this behaviour or use
the one you already created and just tell the activity what to do.
*/
/*if(mainActivity != null) {
ma.openMyList = false;
ma.openMyAddress = false;
ma.hideSearchButton();
}*/
} catch (ClassCastException e) {
throw new ClassCastException(mainActivity.getClass().getSimpleName() + " must implement OnFragmentInteractionListener");
}
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//since your Listener is global use mListener behaviour that I suggested here.
if (mListener != null){
mListener.openListOfSomething(false);
mListener.hideSearch();
}
}
您可以使用 Bundle savedInstatceState,它在 OnCreate 和类似方法中给出:
private String aVariable;
@Override
public void onCreate (Bundle savedInstantceState) {
super.onCreate(savedInstanceState);
// Get the variable from savedInstanceState, if it isn't empty.
// If it is empty, it could be the first Activity run.
try {
aVariable = savedInstanceState.get("Key");
} catch (NullPointerException e) {
aVariable = "Baum";
}
}
@Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
outState.putString(aVariable, "Key");
}
这些方法在第一个 运行 上将变量 "aVariable" 设置为 "Baum" (NullPointerException,因为 "Key" 没有字符串)。 稍后,当 Activity 将被销毁时,将调用 onSaveInstanceState。在那里,您将变量 (aVariable) 保存在键 ("Key") 下。