当 FragmentActivity 在 Android 中进入后台时出现 NotSerializableException
Posted
技术标签:
【中文标题】当 FragmentActivity 在 Android 中进入后台时出现 NotSerializableException【英文标题】:NotSerializableException when FragmentActivity goes to background in Android 【发布时间】:2019-05-24 17:22:31 【问题描述】:我的活动中有 5 个片段,其中一个片段一次保持活动状态。单击一个 recyclerview 项目会打开另一个片段并将当前片段放入后台堆栈。 几天前相同的代码运行良好,但现在每当我单击主页按钮将应用程序置于后台时,应用程序都会抛出 NotSerializableException。我尝试将初始化变量放在 onStart 中,然后在 onStop 中给出空值,但这不起作用。片段代码:
public class PaperListFragment extends Fragment implements Serializable
private static final String TAG = "PaperListFragment";
private static final String QUESTIONS_FRAGMENT_TAG = "questions_fragment";
private static final String ADD_PAPER_FRAGMENT_TAG = "add_paper_fragment";
private OnFragmentActiveListener mOnFragmentActiveListener;
private TextView mHeadingText;
private Bundle mOutState;
private FirebaseAuth mAuth;
private DatabaseReference mDatabaseReference;
private ProgressBar mProgressBar;
private OnItemClickListener mOnItemClickListener;
private FloatingActionButton mFab;
private RecyclerView mRecyclerViewPaper;
private ArrayList<Paper> mPaperList = new ArrayList<>();
private Subject mSubject = new Subject();
private Exam mExam = new Exam();
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
View rootView = inflater.inflate(R.layout.fragment_recycler_list, container, false);
mProgressBar = (ProgressBar) rootView.findViewById(R.id.progressbar_news);
mFab = (FloatingActionButton) rootView.findViewById(R.id.floatingActionButton);
mProgressBar.setVisibility(View.VISIBLE);
Log.d(TAG, "onCreateView: Fragment created");
mAuth = FirebaseAuth.getInstance();
mDatabaseReference = FirebaseDatabase.getInstance().getReference();
if (mAuth.getCurrentUser() == null)
startActivity(new Intent(getActivity(), LoginActivity.class));
getActivity().finish();
return null;
if (getArguments() != null)
mOnFragmentActiveListener = (OnFragmentActiveListener) getArguments().getSerializable(Keys.FRAGMENT_ACTIVE_LISTENER);
mSubject = (Subject) getArguments().getSerializable(Keys.SUBJECT_KEY);
mExam = (Exam) getArguments().getSerializable(Keys.EXAMS_KEY);
mRecyclerViewPaper = (RecyclerView) rootView.findViewById(R.id.recycler_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity())
@Override
public boolean canScrollVertically()
return false;
;
mRecyclerViewPaper.setLayoutManager(layoutManager);
Log.d(TAG, "onCreateView: Layout Manager Set.");
mFab.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
startAddPaperFragment();
);
mOnItemClickListener = new OnItemClickListener()
@Override
public void onItemClicked(RecyclerView.ViewHolder holder, int position)
Log.d(TAG, "onItemClicked: Clicked item position is: "+ position);
QuestionListFragment questionFragment = new QuestionListFragment();
questionFragment.setRetainInstance(true);
startFragment(position, questionFragment, QUESTIONS_FRAGMENT_TAG);
@Override
public void OnItemLongClicked(RecyclerView.ViewHolder holder, int position)
;
mHeadingText = (TextView) rootView.findViewById(R.id.heading_textview);
mHeadingText.setText(mExam.getExam_name()+" > "+ mSubject.getSubject_name());
if (mOutState != null)
mPaperList = (ArrayList<Paper>) mOutState.getSerializable(Keys.PAPER_LIST_KEY);
updateUI();
else
updateUIFromDatabase();
return rootView;
private void startFragment(int position, Fragment fragment, String fragmentTag)
Paper paper = new Paper();
if (mPaperList.size() > 0)
paper = mPaperList.get(position);
Bundle args = new Bundle();
args.putSerializable(Keys.EXAMS_KEY, mExam);
args.putSerializable(Keys.SUBJECT_KEY, mSubject);
args.putSerializable(Keys.PAPER, paper);
args.putSerializable(Keys.FRAGMENT_ACTIVE_LISTENER, mOnFragmentActiveListener);
fragment.setArguments(args);
FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right);
fragmentTransaction.replace(R.id.questions_fragment_container, fragment, fragmentTag);
fragmentTransaction.addToBackStack(fragmentTag);
fragmentTransaction.commit();
private void startAddPaperFragment()
AddPaperFragment addPaperFragment = new AddPaperFragment();
addPaperFragment.setRetainInstance(true);
startFragment(0, addPaperFragment, ADD_PAPER_FRAGMENT_TAG);
private void updateUIFromDatabase()
if (getArguments() != null)
Exam exam = (Exam) getArguments().getSerializable(Keys.EXAMS_KEY);
Subject subject = (Subject) getArguments().getSerializable(Keys.SUBJECT_KEY);
DatabaseReference paperReference =
mDatabaseReference
.child(Keys.APP_DATA_KEY)
.child(Keys.EXAM_PAPERS)
.child(exam.getExam_name())
.child(subject.getSubject_name());
Query query = paperReference.orderByChild(Keys.TIME_ADDED);
query.addValueEventListener(new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot)
mPaperList.clear();
for (DataSnapshot paperChild : dataSnapshot.getChildren())
mPaperList.add(paperChild.getValue(Paper.class));
updateUI();
@Override
public void onCancelled(@NonNull DatabaseError databaseError)
);
private void updateUI()
PaperRecyclerAdapter adapter = new PaperRecyclerAdapter(
getActivity(),
mRecyclerViewPaper,
mPaperList,
mOnItemClickListener
);
mRecyclerViewPaper.setAdapter(adapter);
mProgressBar.setVisibility(View.GONE);
@Override
public void onResume()
super.onResume();
if (getArguments()!=null)
mOnFragmentActiveListener.onFragmentActive(
this,
"Topics"
);
@Override
public void onPause()
super.onPause();
mOutState = new Bundle();
mOutState.putSerializable(Keys.PAPER_LIST_KEY, mPaperList);
例外:
2018-12-26 17:49:38.344 14834-14834/in.crazybytes.bankmaniaadmin E/androidRuntime: FATAL EXCEPTION: main
Process: in.crazybytes.bankmaniaadmin, PID: 14834
java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = in.crazybytes.bankmaniaadmin.activities.QuestionsActivity)
at android.os.Parcel.writeSerializable(Parcel.java:1526)
at android.os.Parcel.writeValue(Parcel.java:1474)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:723)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
at android.os.Bundle.writeToParcel(Bundle.java:1133)
at android.os.Parcel.writeBundle(Parcel.java:763)
at android.support.v4.app.FragmentState.writeToParcel(FragmentState.java:124)
at android.os.Parcel.writeTypedArray(Parcel.java:1306)
at android.support.v4.app.FragmentManagerState.writeToParcel(FragmentManager.java:639)
at android.os.Parcel.writeParcelable(Parcel.java:1495)
at android.os.Parcel.writeValue(Parcel.java:1401)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:723)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
at android.os.Bundle.writeToParcel(Bundle.java:1133)
at android.os.Parcel.writeBundle(Parcel.java:763)
at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3697)
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3768)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
Caused by: java.io.NotSerializableException: com.google.firebase.auth.internal.zzj
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1224)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1584)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1549)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1472)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1218)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1584)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1549)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1472)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1218)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
at android.os.Parcel.writeSerializable(Parcel.java:1521)
at android.os.Parcel.writeValue(Parcel.java:1474)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:723)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
at android.os.Bundle.writeToParcel(Bundle.java:1133)
at android.os.Parcel.writeBundle(Parcel.java:763)
at android.support.v4.app.FragmentState.writeToParcel(FragmentState.java:124)
at android.os.Parcel.writeTypedArray(Parcel.java:1306)
at android.support.v4.app.FragmentManagerState.writeToParcel(FragmentManager.java:639)
at android.os.Parcel.writeParcelable(Parcel.java:1495)
at android.os.Parcel.writeValue(Parcel.java:1401)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:723)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1408)
at android.os.Bundle.writeToParcel(Bundle.java:1133)
at android.os.Parcel.writeBundle(Parcel.java:763)
at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3697)
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3768)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6123)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
注意: 奇怪的是其中一个片段具有完全相同的代码并托管在同一个活动中,但是当该片段处于活动状态并且应用程序进入后台时,有趣的是该应用程序不是崩溃。
**考试模型类: 打包在.crazybytes.bankmaniaadmin.models;
import java.io.Serializable;
public class Exam implements Serializable
private String mExam_name;
private String mExam_key;
private Long mTime_added;
private int mNum_subjects;
private int mNum_questions;
public Exam(String exam_name, String exam_key, Long time_added, int num_subjects, int num_questions)
mExam_name = exam_name;
mExam_key = exam_key;
mTime_added = time_added;
mNum_subjects = num_subjects;
mNum_questions = num_questions;
public Exam()
public String getExam_name()
return mExam_name;
public void setExam_name(String exam_name)
mExam_name = exam_name;
public String getExam_key()
return mExam_key;
public void setExam_key(String exam_key)
mExam_key = exam_key;
public Long getTime_added()
return mTime_added;
public void setTime_added(Long time_added)
mTime_added = time_added;
public int getNum_subjects()
return mNum_subjects;
public void setNum_subjects(int num_subjects)
mNum_subjects = num_subjects;
public int getNum_questions()
return mNum_questions;
public void setNum_questions(int num_questions)
mNum_questions = num_questions;
纸模型类
package in.crazybytes.bankmaniaadmin.models;
import java.io.Serializable;
public class Paper implements Serializable
private String mPaper_name;
private String mPaper_key;
private Long mTime_added;
private int mNum_questions;
public Paper(String paper_name, String paper_key, Long time_added, int num_questions)
mPaper_name = paper_name;
mPaper_key = paper_key;
mTime_added = time_added;
mNum_questions = num_questions;
public Paper()
public String getPaper_key()
return mPaper_key;
public void setPaper_key(String paper_key)
mPaper_key = paper_key;
public Long getTime_added()
return mTime_added;
public void setTime_added(Long time_added)
mTime_added = time_added;
public int getNum_questions()
return mNum_questions;
public void setNum_questions(int num_questions)
mNum_questions = num_questions;
public String getPaper_name()
return mPaper_name;
public void setPaper_name(String paper_name)
mPaper_name = paper_name;
主题模型类:
package in.crazybytes.bankmaniaadmin.models;
import java.io.Serializable;
public class Subject implements Serializable
private String mSubject_name;
private String mSubject_key;
private Long mTime_added;
private int mNum_papers;
private int mNum_questions;
public Subject(String subject_name, String subject_key, Long time_added, int num_papers, int num_questions)
mSubject_name = subject_name;
mSubject_key = subject_key;
mTime_added = time_added;
mNum_papers = num_papers;
mNum_questions = num_questions;
public Subject()
public String getSubject_name()
return mSubject_name;
public void setSubject_name(String subject_name)
mSubject_name = subject_name;
public String getSubject_key()
return mSubject_key;
public void setSubject_key(String subject_key)
mSubject_key = subject_key;
public Long getTime_added()
return mTime_added;
public void setTime_added(Long time_added)
mTime_added = time_added;
public int getNum_papers()
return mNum_papers;
public void setNum_papers(int num_papers)
mNum_papers = num_papers;
public int getNum_questions()
return mNum_questions;
public void setNum_questions(int num_questions)
mNum_questions = num_questions;
【问题讨论】:
你能添加你的考试和科目模型类吗 我已经在这些模型类中实现了 Serializable,所有其他片段、模型、接口、活动和类也在实现 Serializable 添加了考试、科目和论文模型类 即使在 TextViews 和 FloatingActionButtons 上也会给出 NotSerializableException。 OnFragmentActiveListener 在哪里定义?它是 QuestionsActivity 的内部类吗? 【参考方案1】:QuestsActivity 不知何故进入了片段保存状态,即使您不打算发生这种情况。在对 QuestionsActivity 进行序列化时,遇到了另一个不可序列化的对象。这就是为什么您会看到 TextView 和其他尝试序列化的东西的原因,因为 QuestionsActivity 的所有实例变量默认情况下都会被序列化。
我对为什么会发生这种情况的最佳猜测是由于这一行:
args.putSerializable(Keys.FRAGMENT_ACTIVE_LISTENER, mOnFragmentActiveListener);
但是如果不查看 OnFragmentActiveListener 的定义位置,就很难确定。我假设 QuestionsActivity 实现 OnFragmentActiveListener,或者 QuestionsActivity 将 OnFragmentActiveListener 定义为内部类。无论哪种方式,如果您将 OnFragmentActiveListener 放入片段参数中,您将遇到异常,因为您也间接地将整个 QuestionsActivity 存储为片段 arg。当一个片段停止时,所有片段参数都成为片段保存状态的一部分。这就是错误的原因。
我建议不要将 OnFragmentActiveListener 作为片段 arg 传递。如果 OnFragmentActiveListener 来自 Activity,只需使用 getActivity() 获取对 Activity 的引用,然后获取对侦听器的引用。
我还注意到 PaperListFragment 实现了 Serializable,我假设您对 QuestionsActivity 做了同样的事情。您可能这样做是为了避免编译错误。但这导致了运行时错误,因为这两个类上的实例变量都不是可序列化的。所以为了避免更多的运行时问题,我建议永远不要让活动或片段实现可序列化,因为这些类由于它们的成员而本质上是不可序列化的。
【讨论】:
非常感谢@Greg Moens。是的,我的 QuestionsActivity 正在实现 OnFragmentActiveListener,然后我将“this”作为 Serializable 并将其放入片段中。通过将 OnFragmentListener 声明为变量,然后在每个片段中使用公共设置器进行设置,解决了这个问题。以上是关于当 FragmentActivity 在 Android 中进入后台时出现 NotSerializableException的主要内容,如果未能解决你的问题,请参考以下文章
Activity 和 FragmentActivity 的区别
无法使用兼容包 v4 解决在 Android 2.3.3 上运行的 FragmentActivity