即使我重写onSaveInstanceState,在Fragment中调用onCreateView时savedInstanceState为null

时间:2017-10-30 03:02:08

标签: android android-fragments

我将按钮添加到工具栏以从片段B导航到片段A.

当我点击向上按钮时,我无法恢复A片段的成员变量

因为即使我覆盖了

,savedInstanceState也为null

onSaveInstanceState(Bundle)并放入我想要稍后恢复的所有变量。

我尽力搜索原因,但我找不到原因和solutoin。

我的情况和其他帖子的问题(答案)之间存在差异。

首先,我的片段是动态托管的,所以我无法用XML或其他东西给我的片段提供id。

其次,它在我旋转设备时起作用(onCreateView()上的savedInstanceState不为null)。我认为两者(旋转设备并从片段B导航到片段A)都是相同的情况

因为片段A被销毁并重新创建,所以onSaveInstanceState方法

首先调用

,并在重新创建片段A后调用onCreateView。

我不知道为什么会出现这种情况。请帮我。感谢。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    if(savedInstanceState != null){
        mSubtitleVisible = savedInstanceState.getBoolean(SAVED_SUBTITLE_VISIBLE);
    }
    View view = inflater.inflate(R.layout.fragment_crime_list, container, false);
    mCrimeRecyclerView = (RecyclerView) view.findViewById(R.id.crime_recycler_view);
    mCrimeRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));

    updateUI();
    return view;
}

...

@Override
public void onSaveInstanceState(Bundle outState){
    super.onSaveInstanceState(outState);
    outState.putBoolean(SAVED_SUBTITLE_VISIBLE, mSubtitleVisible);
}

Fragment B的完整代码

package com.bignerdranch.android.criminalintent;

import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;

import java.util.Calendar;
import java.util.Date;
import java.util.UUID;

/**
 * Created by sgc109 on 2017-10-05.
 */

public class CrimeFragment extends android.support.v4.app.Fragment {
    private static final String ARG_CRIME_ID = "crime_id";
    private static final String DIALOG_DATE = "DialogDate";
    private static final String DIALOG_TIME = "DialogTime";
    private static final int REQUEST_DATE = 0;
    private static final int REQUEST_TIME = 1;

    private Crime mCrime;
    private EditText mTitleField;
    private Button mDateButton;
    private Button mTimeButton;
    private CheckBox mSolvedCheckBox;

    public static CrimeFragment newInstance(UUID crimeId){
        Bundle args = new Bundle();
        args.putSerializable(ARG_CRIME_ID, crimeId);

        CrimeFragment fragment = new CrimeFragment();
        fragment.setArguments(args);
        return fragment;
    }
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        UUID crimeId = (UUID)getArguments().getSerializable(ARG_CRIME_ID);
        mCrime = CrimeLab.get(getActivity()).getCrime(crimeId);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        View v = inflater.inflate(R.layout.fragment_crime, container, false);

        mTitleField = (EditText)v.findViewById(R.id.crime_title);
        mTitleField.setText(mCrime.getTitle());
        mTitleField.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                mCrime.setTitle(s.toString());
            }
            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        mDateButton = (Button)v.findViewById(R.id.crime_date);
        mDateButton.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                FragmentManager manager = getFragmentManager();
                DatePickerFragment dialog = DatePickerFragment.newInstance(mCrime.getDate());
                dialog.setTargetFragment(CrimeFragment.this, REQUEST_DATE);
                dialog.show(manager, DIALOG_DATE);
            }
        });
        mTimeButton = (Button)v.findViewById(R.id.crime_time);
        mTimeButton.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                FragmentManager manager = getFragmentManager();
                TimePickerFragment dialog = TimePickerFragment.newInstance(mCrime.getDate());
                dialog.setTargetFragment(CrimeFragment.this, REQUEST_TIME);
                dialog.show(manager, DIALOG_TIME);
            }
        });

        updateDateAndTimeButton();

        mSolvedCheckBox = (CheckBox)v.findViewById(R.id.crime_solved);
        mSolvedCheckBox.setChecked(mCrime.isSolved());
        mSolvedCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                mCrime.setSolved(isChecked);
            }
        });
        return v;
    }
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent){
        if(resultCode != Activity.RESULT_OK) {
            return;
        }
        if(requestCode == REQUEST_DATE){
            Date date = (Date)intent.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
            mCrime.setDate(updateDate(date));
            updateDateAndTimeButton();
        }
        else if(requestCode == REQUEST_TIME){
            Date date = (Date)intent.getSerializableExtra(TimePickerFragment.EXTRA_TIME);
            mCrime.setDate(updateTime(date));
            updateDateAndTimeButton();
        }
    }

    private Date updateDate(Date date){
        Calendar calOld = Calendar.getInstance();
        calOld.setTime(mCrime.getDate());
        Calendar calNew = Calendar.getInstance();
        calNew.setTime(date);

        calNew.set(Calendar.HOUR_OF_DAY, calOld.get(Calendar.HOUR_OF_DAY));
        calNew.set(Calendar.MINUTE, calOld.get(Calendar.MINUTE));

        return calNew.getTime();
    }

    private Date updateTime(Date date){
        Calendar calOld = Calendar.getInstance();
        calOld.setTime(mCrime.getDate());
        Calendar calNew = Calendar.getInstance();
        calNew.setTime(date);

        calNew.set(Calendar.YEAR, calOld.get(Calendar.YEAR));
        calNew.set(Calendar.MONTH, calOld.get(Calendar.MONTH));
        calNew.set(Calendar.DAY_OF_MONTH, calOld.get(Calendar.DAY_OF_MONTH));

        return calNew.getTime();
    }

    private void updateDateAndTimeButton() {
        mDateButton.setText(mCrime.getDateString());
        mTimeButton.setText(mCrime.getTimeString());
    }

    public void returnResult(){
        getActivity().setResult(Activity.RESULT_OK, null);
    }
}

1 个答案:

答案 0 :(得分:3)

因为Activity之后创建了onCreateView

您可以使用onActivityCreated方法在此处恢复片段的状态。

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if (savedInstanceState != null) {
        mSubtitleVisible = savedInstanceState.getBoolean(SAVED_SUBTITLE_VISIBLE);
    }
    Log.e("TAG", "onActivityCreated OK");
    Log.e("TAG", savedInstanceState.getBoolean(SAVED_SUBTITLE_VISIBLE) + "");
}

修改

更改为onViewStateRestored方法,然后重试。

添加登录onSaveInstanceStateonViewStateRestored,确保所有这些都有效。

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if (savedInstanceState != null) {
        mSubtitleVisible = savedInstanceState.getBoolean(SAVED_SUBTITLE_VISIBLE);
    }
    Log.e("TAG", "onActivityCreated OK");
    Log.e("TAG", "onActivityCreated " + savedInstanceState.getBoolean(SAVED_SUBTITLE_VISIBLE));
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean(SAVED_SUBTITLE_VISIBLE, mSubtitleVisible);
    Log.e("TAG", "onSaveInstanceState OK");
    Log.e("TAG", "onSaveInstanceState" + mSubtitleVisible);
}

修改

您可以将状态保存在onSaveInstanceStateonDestroyView

然后,恢复onActivityCreated

中的状态

你可以这样做。

Bundle savedState;

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    // Restore State Here
    if (!restoreStateFromArguments()) {
        // First Time, Initialize something here
        onFirstTimeLaunched();
    }
}

protected void onFirstTimeLaunched() {
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    // Save State Here
    saveStateToArguments();
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    // Save State Here
    saveStateToArguments();
}

private void saveStateToArguments() {
    if (getView() != null)
        savedState = saveState();
    if (savedState != null) {
        Bundle b = getArguments();
        b.putBundle("savedState", savedState);
    }
}

private boolean restoreStateFromArguments() {
    Bundle b = getArguments();
    savedState = b.getBundle("savedState");
    if (savedState != null) {
        restoreState();
        return true;
    }
    return false;
}

// Restore Instance State Here
private void restoreState() {
    if (savedState != null) {
        // For Example
        uSelected.setText(savedState.getString("uSelected"));
        onRestoreState(savedState);
    }
}

protected void onRestoreState(Bundle savedInstanceState) {
}

// Save Instance State Here
private Bundle saveState() {
    Bundle state = new Bundle();
    // For Example
    state.putString("uSelected", uSelected.getText().toString());
    onSaveState(state);
    return state;
}

protected void onSaveState(Bundle outState) {
}

片段生命周期

enter image description here