You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从SecondActivity返回时MainActivity的savedInstanceState为null问题

问题描述

我在完成Android基础02.2:Activity生命周期与状态的实践项目时,遇到一个问题:从SecondActivity点击左上角返回键回到MainActivity,或是旋转MainActivity屏幕时,MainActivity都会执行onSaveInstanceState方法并销毁重建。但前者重建时onCreate的savedInstanceState参数为null,导致之前显示的回复内容丢失;后者savedInstanceState正常非空,状态恢复正常。

复现步骤

  • 运行应用
  • 在MainActivity的EditText输入内容,点击SEND进入SecondActivity
  • 在SecondActivity的EditText输入内容,点击REPLY返回,此时MainActivity顶部显示回复内容
  • 再次输入内容点击SEND进入SecondActivity
  • 点击SecondActivity左上角返回键回到MainActivity

此时MainActivity顶部的回复内容消失,日志显示MainActivity销毁前已执行onSaveInstanceState,但重建时savedInstanceState为null。旋转屏幕时状态恢复正常,请问该问题的原因是什么?

代码片段

MainActivity.java

package com.example.twoactivities;

public class MainActivity extends AppCompatActivity {
    private static final String LOG_TAG = 
        MainActivity.class.getSimpleName();
    public static final String EXTRA_MESSAGE = 
        "com.example.android.twoactivities.extra.MESSAGE";

    public static final int TEXT_REQUEST = 1;

    private TextView mReplyHeadTextView;
    private TextView mReplyTextView;
    private EditText mMessageEditText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(LOG_TAG, "-------");
        Log.d(LOG_TAG, "onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mMessageEditText = findViewById(R.id.editText_main);
        mReplyHeadTextView = findViewById(R.id.text_header_reply);
        mReplyTextView = findViewById(R.id.text_message_reply);

        if(savedInstanceState != null){
            Log.d(LOG_TAG, "enter saveInstance");
            boolean isVisible = savedInstanceState.getBoolean("reply_visible");
            if(isVisible){
                mReplyHeadTextView.setVisibility(View.VISIBLE);
                mReplyTextView.setText(savedInstanceState.getString("reply_text"));
                mReplyTextView.setVisibility(View.VISIBLE);

            }
        }
    }

    public void launchSecondActivity(View view) {
        Log.d(LOG_TAG, "Button clicked!");
        String message = mMessageEditText.getText().toString();
        Intent intent = new Intent(this, SecondActivity.class);
        intent.putExtra(EXTRA_MESSAGE, message);
        startActivityForResult(intent, TEXT_REQUEST);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data){
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == TEXT_REQUEST){
            if(resultCode == RESULT_OK){
                String reply = data.getStringExtra(SecondActivity.EXTRA_REPLY);
                mReplyHeadTextView.setVisibility(View.VISIBLE);
                mReplyTextView.setText(reply);
                mReplyTextView.setVisibility(View.VISIBLE);
            }
        }
    }

    @Override
    public void onStart(){
        super.onStart();
        Log.d(LOG_TAG, "onStart");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(LOG_TAG, "onPause");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d(LOG_TAG, "onRestart");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(LOG_TAG,"onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(LOG_TAG, "onDestroy");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(LOG_TAG, "onResume");
    }

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.d(LOG_TAG, "saving Instance");
        if(mReplyHeadTextView.getVisibility() == View.VISIBLE){
            outState.putBoolean("reply_visible", true);
            outState.putString("reply_text", mReplyTextView.getText().toString());
        }
    }
}

SecondActivity.java

package com.example.twoactivities;

public class SecondActivity extends AppCompatActivity {
    public static final String LOG_TAG = 
        SecondActivity.class.getSimpleName();
    public static final String EXTRA_REPLY = 
        "com.example.android.twoactivities.extra.REPLY";
    private EditText mReply;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(LOG_TAG, "-------");
        Log.d(LOG_TAG, "Sec onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        mReply = findViewById(R.id.editText_second);
        Intent intent = getIntent();
        String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
        TextView textView = findViewById(R.id.text_message);
        textView.setText(message);
    }

    public void returnReply(View view) {
        String reply = mReply.getText().toString();
        Intent replyIntent = new Intent();
        replyIntent.putExtra(EXTRA_REPLY, reply);
        setResult(RESULT_OK, replyIntent);
        finish();
        Log.d(LOG_TAG, "End SecondActivity");
    }

    @Override
    public void onStart(){
        super.onStart();
        Log.d(LOG_TAG, "Sec onStart");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(LOG_TAG, "Sec onPause");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d(LOG_TAG, "Sec onRestart");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(LOG_TAG,"Sec onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(LOG_TAG, "Sec onDestroy");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(LOG_TAG, "Sec onResume");
    }
}

问题原因

核心原因是系统仅在「被动销毁Activity(为后续重建做准备)」的场景下,才会传递savedInstanceState给重建的Activity,具体区分两种场景:

  1. 旋转屏幕(配置变更):系统因为屏幕方向变化临时销毁MainActivity,之后会主动重建它,所以会把之前通过onSaveInstanceState保存的Bundle传递给onCreate,状态恢复正常。
  2. 点击返回键回到MainActivity:当你从SecondActivity返回时,如果MainActivity之前因为进入后台被系统销毁(比如内存不足),此时系统重建MainActivity,但用户的返回操作属于「主动结束流程」,系统认为不需要恢复之前的状态,因此不会把之前保存的savedInstanceState传递给onCreate,导致参数为null。

另外需要注意:只要Activity进入后台(比如启动另一个Activity),系统都会调用onSaveInstanceState保存状态,但这个状态是否会在重建时被复用,完全取决于Activity被销毁的原因——只有系统触发的、需要后续重建的销毁,才会传递该Bundle;用户主动触发的销毁(返回键、调用finish())则不会。

内容的提问来源于stack exchange,提问作者AndroidNewbie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 03:49:57