Android碎片生命周期:onResume被调用两次

4
我正在尝试在用户切换到另一个活动并返回当前活动后,在我的片段中保存和恢复滚动。以下是发生的情况:enter image description here 可以看到,直接进行第一个片段的 onResume 后就会进入 onPause,尽管用户没有做任何操作。问题是:我的代码有什么问题?
以下是我的代码:
public class DisplayNoteActivity extends Activity {

private Context mContext;
//static final int SUBACT_EDITNOTE=100;
private long m_NoteID;
private String m_sTextNoAbbrev;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    try
    {
        Log.v("DEBUG", "DisplayNoteActivity.onCreate()");
        setContentView(R.layout.activity_display_note);

        Bundle extras = getIntent().getExtras();
        m_NoteID = extras.getLong("DisplayNote_NOTEID");
        m_sTextNoAbbrev = extras.getString("DisplayNote_TextNoAbbrev");

        if (savedInstanceState != null)
            RefreshFragment();
    }
    catch(Exception e){
        Toast.makeText(this, e.getMessage() , Toast.LENGTH_LONG).show();
        e.printStackTrace();
    }

}


public void onSaveInstanceState(Bundle savedInstanceState)
{
    Log.v("DEBUG", "DisplayNoteActivity.onSaveInstanceState()");
    super.onSaveInstanceState(savedInstanceState);
    savedInstanceState.putLong("DisplayNote_NOTEID", m_NoteID);
    savedInstanceState.putString("DisplayNote_TextNoAbbrev", m_sTextNoAbbrev);
}

public void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    // Restore UI state from the savedInstanceState.
    // This bundle has also been passed to onCreate.
    Log.v("DEBUG", "DisplayNoteActivity.onRestoreInstanceState()");
    m_NoteID = savedInstanceState.getLong("DisplayNote_NOTEID");
    m_sTextNoAbbrev= savedInstanceState.getString("DisplayNote_TextNoAbbrev");
}

@Override
public void onResume() {
    Log.v("DEBUG", "DisplayNoteActivity.onResume()");
    super.onResume();

    RefreshFragment();
}


private void RefreshFragment()
{

    Bundle bundle = new Bundle();
    bundle.putLong("DisplayNote_NOTEID", m_NoteID);
    bundle.putString("DisplayNote_TextNoAbbrev", m_sTextNoAbbrev);

    android.app.FragmentManager fm=getFragmentManager();
    android.app.FragmentTransaction ft = fm.beginTransaction();

    DisplayNoteFragment dnf = new DisplayNoteFragment();
    dnf.setArguments(bundle);
    ft.replace(R.id.container, dnf);

    ft.commit();
}}

片段代码:

public class DisplayNoteFragment extends Fragment {


private Context mContext;

private long mNoteID = 0;
private Note m_NoteData;

private long mTextID = 0;
private int m_levels = 0;

private String m_dbtype;
private String m_dblang;
GitaTextsHelper m_tdb;

private String m_sTextNo;
private ScrollView m_Scroll;
private int mScrollPos=0;

AutoResizeTextView m_atvHeaderTitle;
AutoResizeTextView m_atvHeaderSubTitle;

AutoResizeTextView m_atvBookTitle;
AutoResizeTextView m_atvChapterTitle;
TextView m_atvTags;
AutoResizeTextView m_atvVerse;

TextView m_tvGitaText;
ImageView m_NoteTypeIcon;
ImageView m_EditNoteIcon;
TextView m_tvNote;

int m_titlePrefixID;


long m_TextRowID = -1;
String m_sVerse;

public DisplayNoteFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_display_note, container, false);
    Log.v("DEBUG", "DisplayNoteFragment onCreateView()");
    try {
        m_Scroll = (ScrollView)rootView.findViewById(R.id.ScrollView02);
        m_atvHeaderTitle = (AutoResizeTextView) rootView.findViewById(R.id.header_title);
        m_atvHeaderSubTitle = (AutoResizeTextView) rootView.findViewById(R.id.header_subtitle);

        m_atvBookTitle = (AutoResizeTextView) rootView.findViewById(R.id.book_title);
        m_atvChapterTitle = (AutoResizeTextView) rootView.findViewById(R.id.chapter_title);
        m_atvTags = (TextView) rootView.findViewById(R.id.note_tags);
        m_atvVerse = (AutoResizeTextView) rootView.findViewById(R.id.note_verse);

        m_tvGitaText = (TextView) rootView.findViewById(R.id.gita_text);
        m_tvNote = (TextView) rootView.findViewById(R.id.note_text);

        //***** INPUT
        mNoteID = getArguments().getLong("DisplayNote_NOTEID");
        m_NoteData = MyApp.mUserDB.GetNote(mNoteID);
        // common fields for text notes and custom notes
        m_atvHeaderSubTitle.setText(m_NoteData.sCreatedDate);
        m_NoteTypeIcon = (ImageView) rootView.findViewById(R.id.note_type_icon); m_NoteTypeIcon.setImageResource(MyApp.getNoteTypeIcon(m_NoteData.type));
        //tags
        String tags = MyApp.mUserDB.getNoteTags(mNoteID);

        if (tags.equals("")) tags = MyApp.Res.getString(R.string.no_tag_defined);
        m_atvTags.setText(tags);
        m_atvTags.setPaintFlags(m_atvTags.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
        m_atvTags.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                if (MyApp.mC.hasFlag(Cookies.FL_Tagging, mContext, true)) {
                    Intent intent = new Intent(mContext, TagEdit.class);
                    intent.putExtra("TAGEDIT_NOTEID", mNoteID);
                    intent.putExtra("TAGEDIT_EDIT_TAGS_MODE", 1);

                    startActivity(intent);
                }

            }
        });


    } catch (Exception e) {
        Toast.makeText(mContext, e.getMessage(), Toast.LENGTH_LONG).show();
        e.printStackTrace();
    }

    return rootView;
}

private void openText(int iScroll) {

    Intent intent = new Intent(mContext, DisplayText.class);
    intent.putExtra("rowID", m_TextRowID);
    intent.putExtra("Scroll", iScroll);
    intent.putExtra("Language", m_dblang);
    intent.putExtra("DBType", m_dbtype);
    startActivity(intent);
}


public void onPause() {
    super.onPause();

    mScrollPos=m_Scroll.getScrollY();
    Log.v("DEBUG", "DisplayNoteFragment onPause(). Scroll="+mScrollPos);
}


public void onResume() {
    Log.v("DEBUG", "DisplayNoteFragment onResume(). Scroll="+mScrollPos);
    super.onResume();
    if(mScrollPos!=0) {
        m_Scroll.scrollTo(0, mScrollPos);
        Log.v("DEBUG", "DisplayNoteFragment onResume(). Scrolled to="+mScrollPos);
    }

}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    if(outState==null) return;
    Log.v("DEBUG", "DisplayNoteFragment onSaveInstanceState(). Scroll="+mScrollPos);
    outState.putInt("mScrollPos", mScrollPos);

}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if(savedInstanceState==null) return;
    mScrollPos = savedInstanceState.getInt("mScrollPos");
    Log.v("DEBUG", "DisplayNoteFragment onActivityCreated(). Scroll="+mScrollPos);
}

}


2
由于您从OnResume中调用了RefreshFragment()函数; - Divyesh Patel
1
我猜他的意图是在每次事务中刷新片段的UI元素。 - Sreehari
我找不到更好的方法来刷新片段中用户编辑数据后的字段数据。这就是为什么我从活动的onResume()中调用RefreshFragment()的原因。你能指导我正确的做法吗?到目前为止,我还没有在谷歌上找到... - Ivan
将RefreshFragment()方法添加到“SAVE”按钮监听器中(如果您在某个地方有一个),当用户对字段进行更改并点击保存按钮时,您可以刷新UI。 - MatPag
我没有这样的“保存”按钮。编辑发生在另一个活动中,该活动将更改保存到数据库中。当我回到我的DisplayNoteActivity时,我需要使用数据库中的新数据刷新片段。 - Ivan
在我的应用程序中,fragmentManager.executePendingTransactions(); 是问题的根源。 - fastr.de
2个回答

3

Fragment被替换了两次,这就是为令onResume()方法被调用两次的原因。您应该只在activity的onCreate()方法中调用RefreshFragment(),而不需要在activity的onResume()方法中调用。


好的,现在滚动保存已经可以工作了,我在活动的onResume()中注释掉了RefreshFragment()。然而,当用户编辑片段的字段后,片段并没有得到刷新。我该怎么做才能使片段的字段更新为新值? - Ivan
你可以将片段的引用保留为活动类的成员变量,并通过一些公共方法更新值。 - Manpreet Singh
在活动的onResume()中,我应该调用Fragment类的哪个方法来重新绘制保存的片段实例? - Ivan
您需要重构您的代码,以便在第一次运行时使用 getArguments 中的数据,并在将来的更新中从新方法中获取数据。 - Manpreet Singh

1
首先,我认为您应该检查DisplayNoteActivityonResume()是否也被调用了两次?如果是, 1. 检查在启动DisplayNoteActivity时是否调用了requestPermission()。 2. 检查是否没有处理onConfigurationChanged()
如果DisplayNoteActivityonResume()只被调用一次,则检查DisplayNoteFragment有什么问题。

谢谢。我之前在onViewCreated()中调用了requestPermission(),导致onResume()被调用,然后是onPause()和再次的onResume()。由于我已经获得了权限,因此不会显示权限对话框,但当然方法被调用了。 - Shubham Gupta
欢迎你。 在使用 ActivityCompat.requestPermissions() 之前,应先检查权限是否已授予,可使用 ActivityCompat.checkSelfPermission() 进行检查。 - EffectiveMatrix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接