NotSerializableException, когда FragmentActivity переходит в фоновый режим в Android - PullRequest
0 голосов
/ 26 декабря 2018

У меня есть 5 фрагментов в моей деятельности, где один фрагмент остается активным одновременно.Нажатие на элемент в окне повторного просмотра открывает другой фрагмент и помещает текущий фрагмент в backstack.
Тот же код работал несколько дней назад, но теперь приложение выдает NotSerializableException всякий раз, когда я нажимаю кнопку home, чтобы поместитьприложение в фоновом режиме.Я попытался поместить инициализацию переменных в 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)

Примечание: Странно то, что один из фрагментов имеет точно такой же код и размещен внутри той же операции, нокогда этот фрагмент активен и приложение переходит в фоновый режим, интересно, что приложение не падает.

** Класс модели экзамена: упаковка in.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;
}

}

1 Ответ

0 голосов
/ 26 декабря 2018

Каким-то образом QuestionActivity переходит в состояние сохранения фрагмента, даже если вы этого не планируете.Во время сериализации QuestionActivity встречается другой объект, который не сериализуется.Вот почему вы видите TextViews и другие вещи, пытающиеся сериализоваться, потому что все переменные экземпляра QuestionsActivity по умолчанию сериализуются.

Моя лучшая догадка, почему это происходит, из-за этой строки:

args.putSerializable(Keys.FRAGMENT_ACTIVE_LISTENER, mOnFragmentActiveListener);

Но трудно знать наверняка, не видя, где определен OnFragmentActiveListener.Я предполагаю, что либо QuestionsActivity реализует OnFragmentActiveListener, либо QuestionsActivity определяет OnFragmentActiveListener как внутренний класс.В любом случае, если вы поместите OnFragmentActiveListener в аргументы фрагмента, вы столкнетесь с исключением, потому что вы косвенно сохраняете всю QuestionsActivity как аргумент фрагмента.Когда фрагмент останавливается, все аргументы фрагмента становятся частью состояния сохранения фрагмента.И это является причиной ошибки.

Я бы предложил не передавать OnFragmentActiveListener как фрагмент arg.Если OnFragmentActiveListener происходит из действия, просто используйте getActivity (), чтобы получить ссылку на действие, а затем получить ссылку на слушателя.

Я также заметил, что PaperListFragment реализует Serializable, и я предполагаю, что вы сделали то же самоевещь для вопросов деятельности.Вы, вероятно, сделали это, чтобы обойти ошибки компиляции.Но это привело к ошибкам во время выполнения, потому что переменные экземпляра в обоих этих классах не все сериализуемы.Поэтому, чтобы избежать большего количества проблем во время выполнения, я бы предложил никогда не делать сериализуемые операции или фрагменты, потому что эти классы по своей природе не сериализуемы из-за своих членов.

...