Android OnCreate 输入包始终为空

Posted

技术标签:

【中文标题】Android OnCreate 输入包始终为空【英文标题】:Android OnCreate input bundle always null 【发布时间】:2020-08-08 12:49:35 【问题描述】:

我正在进行项目,但我在活动和保存状态方面遇到了一些问题。所以我回到了基础,试图了解我错过了什么。但是,即使设置非常简单,我也遇到了同样的问题。

所以我从一个空项目开始,在 activity_main.xml 上放置了 2 个 textView 和 1 个按钮,在 activity_2.xml 上放置了 1 个按钮。用户将在文本框中输入一些文本,按下按钮前进到 Activity2 Activity,然后按下按钮(在 Activity2 布局中)返回到 MainActivity。

我希望输入到文本框中的文本已被重写的 onSaveInstanceState 方法保存,然后 OnCreate 中的 bundle 参数将保存此值。但是,当 MainActivity 被点击时,尽管在按下启动 Activity2 的按钮时调用了 onSaveInstanceState,但捆绑包仍然为 null。

我错过了什么吗? onSaveInstanceState 方法肯定是启动的,并在其中填充了 savedInstanceState,那么为什么当 MainActivity 再次启动并调用 onCreate 时,Bundle savedInstanceState 为空?这是我设置开始其他活动的方式吗?

感谢您的帮助!

作为参考,这是我的设置:

我的主要活动:

public class MainActivity extends AppCompatActivity 

    Button forwardButton;
    TextView editText;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        forwardButton = findViewById(R.id.buttonForward);
        editText = findViewById(R.id.editText);
        forwardButton.setOnClickListener(new View.OnClickListener() 
            public void onClick(View v) 
                // Code here executes on main thread after user presses button
                Intent activity2 = new Intent(MainActivity.this,Activity2.class);
                startActivity(activity2);
            
        );
    

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) 
        String textToSave = editText.getText().toString();
        savedInstanceState.putString("editText",textToSave);
        super.onSaveInstanceState(savedInstanceState);
    
``

我的 Activity2 课:

public class Activity2 extends AppCompatActivity 

    Button goBack;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_2);

        goBack = findViewById(R.id.goBack);
        goBack.setOnClickListener(new View.OnClickListener() 
            public void onClick(View v) 
                // Code here executes on main thread after user presses button
                Intent activity2 = new Intent(Activity2.this,MainActivity.class);
                startActivity(activity2);
            
        );
    

Activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_
        android:layout_
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/buttonForward"
        android:layout_
        android:layout_
        android:layout_marginStart="162dp"
        android:layout_marginTop="232dp"
        android:layout_marginEnd="162dp"
        android:layout_marginBottom="76dp"
        android:text="Forward"
        app:layout_constraintBottom_toTopOf="@+id/textView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/editText"
        android:layout_
        android:layout_
        android:layout_marginStart="96dp"
        android:layout_marginTop="43dp"
        android:layout_marginEnd="102dp"
        android:layout_marginBottom="268dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="Enter"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity_2.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    tools:context=".Activity2">

    <Button
        android:id="@+id/goBack"
        android:layout_
        android:layout_
        android:layout_marginStart="162dp"
        android:layout_marginTop="232dp"
        android:layout_marginEnd="162dp"
        android:layout_marginBottom="76dp"
        android:text="Go back"
        app:layout_constraintBottom_toTopOf="@+id/textView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

【问题讨论】:

"那么为什么当 MainActivity 再次启动并调用 onCreate 时,Bundle savedInstanceState 为空?" -- 因为它是一个完全不同的活动实例。除了属于同一类之外,它与您的原始实例完全无关,因为您启动了第二个实例。如果您想让Activity2 返回到您现有的MainActivity 实例,请在您的onClick() 方法中调用finish(),而不是startActivity() @CommonsWare 好的,谢谢 - 这是有道理的。所以说我想添加第三个活动,当完成后返回到第二个活动,finish() 方法如何知道然后返回到哪个活动 - 它是活动开始的地方吗?其次,假设应用程序是从头开始加载的,它需要上一个会话的数据——我是否需要在 onDestroy() 上序列化上一个会话的数据,然后在 MainActivity 的第一个 onCreate 上重新加载?跨度> 另外,这是否意味着 onCreate 和输入包参数在 Activity 更改之间根本没有被调用或有用?即它们仅在发生方向更改或应用程序从头开始完全重新启动并且需要从存储中加载数据时使用?在后一种情况下,输入的 bundle 参数仍然是 null 正确的吗? “finish() 方法如何知道要返回哪个活动 - 它是活动开始的地方吗?” -- 控制返回到它在后堆栈上的任何活动。 “我是否需要在 onDestroy() 上序列化上一个会话中的数据,然后在 MainActivity 中的第一个 onCreate 上重新加载?” -- 您需要将数据保存在某个地方。通常,当数据发生变化时,您会这样做,因为不能保证调用onDestroy() “它们仅在发生方向变化等情况时使用”——这是主要场景。有关更多信息,请参阅the documentation 和有关 Android 应用程序开发的书籍。 【参考方案1】:

在你的Activity2

    goBack.setOnClickListener(new View.OnClickListener() 
        public void onClick(View v) 
            Activity2.this.finish();
        
    );

并从onRestoreInstanceState 获取您在MainActivity 中保存的实例

//this will trigger when the same instance of activity is restored
//by the back press that finishes the Activity2
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) 
  super.onRestoreInstanceState(savedInstanceState);

  String data = savedInstanceState.getString("editText");


【讨论】:

好的,所以这适用于保存在 onSavedInstanceState 中的数据,似乎在 Activity2.this.finish(); 之后重新加载回 MainActivity。但是调试显示,重新进入时MainActivity中没有调用onRestoreInstanceState。同样 onCreate() 没有被调用 - 我假设 onDestroy() 在它移动到 Activity2 之前没有。 onSavedInstanceState 将在您的 Activity 再次可见时被调用,onCreate 仅在您创建 Activity 时被调用,例如直接通过 Intent 调用它或当您仍在 Activity 上旋转设备时。跨度> 你的数据在finish()的时候被恢复,这意味着onSavedInstanceState 被触发了。 我知道在我离开 MainActivity 时会调用 onSavedInstanceState。但是,如果在重新进入活动时未调用 onCreate 并且我知道由于调试而未调用 onRestoreInstanceState - MainActivity 的状态如何持续到下一次激活? 另外,为什么当我调用 Activity2.this.finish(); 时,在 Activity2 类中没有调用 onSavedInstanceState?这肯定会调用 onStop 和 onDestroy,然后需要调用 onSavedInstanceState?

以上是关于Android OnCreate 输入包始终为空的主要内容,如果未能解决你的问题,请参考以下文章

使用导航组件时,片段 savedInstanceState 始终为空

为啥 Bundle 对象在 onCreate() 上总是为空?

Android GooglePlay LocationClient 为空,尽管在 onCreate() 中初始化

Android的onCreate里边savedInstanceState啥时候不为空

活动被销毁后,savedInstanceState 始终为空

Android:捆绑始终为空