我一直在安卓SDK平台上工作,现在还不清楚如何保存应用程序的状态。因此,考虑到“你好,Android”示例的这个小的重新设计:

package com.android.hello;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloAndroid extends Activity {

  private TextView mTextView = null;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mTextView = new TextView(this);

    if (savedInstanceState == null) {
       mTextView.setText("Welcome to HelloAndroid!");
    } else {
       mTextView.setText("Welcome back.");
    }

    setContentView(mTextView);
  }
}

我认为这对于最简单的情况来说已经足够了,但无论我如何离开应用程序,它总是以第一条消息来响应。

我确信解决方案就像重写onPause之类的东西一样简单,但我已经在文档中翻了大约30分钟,没有发现任何明显的东西。


当前回答

相反,您应该使用ViewModel,它将在活动生命周期之前保留数据。

其他回答

现在,您可以使用实时数据和生命周期感知组件

https://developer.android.com/topic/libraries/architecture/lifecycle

使用Android ViewModel和SavedStateHandle持久化可序列化数据

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
        binding.setViewModel(new ViewModelProvider(this).get(ViewModel.class));
        binding.setLifecycleOwner(this);
        setContentView(binding.getRoot());
    }

    public static class ViewModel extends AndroidViewModel {

        //This field SURVIVE the background process reclaim/killing & the configuration change
        public final SavedStateHandle savedStateHandle;

        //This field NOT SURVIVE the background process reclaim/killing but SURVIVE the configuration change
        public final MutableLiveData<String> inputText2 = new MutableLiveData<>();


        public ViewModel(@NonNull Application application, SavedStateHandle savedStateHandle) {
            super(application);
            this.savedStateHandle = savedStateHandle;
        }
    }
}

在布局文件中

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="viewModel"
            type="com.xxx.viewmodelsavedstatetest.MainActivity.ViewModel" />
    </data>

    <LinearLayout xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">


        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:autofillHints=""
            android:hint="This field SURVIVE the background process reclaim/killing &amp; the configuration change"
            android:text='@={(String)viewModel.savedStateHandle.getLiveData("activity_main/inputText", "")}' />

        <SeekBar
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="100"
            android:progress='@={(Integer)viewModel.savedStateHandle.getLiveData("activity_main/progress", 50)}' />

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="This field SURVIVE the background process reclaim/killing &amp; the configuration change"
            android:text='@={(String)viewModel.savedStateHandle.getLiveData("activity_main/inputText", "")}' />

        <SeekBar
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="100"
            android:progress='@={(Integer)viewModel.savedStateHandle.getLiveData("activity_main/progress", 50)}' />

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="This field NOT SURVIVE the background process reclaim/killing but SURVIVE the configuration change"
            android:text='@={viewModel.inputText2}' />

    </LinearLayout>
</layout>

测试:

1. start the test activity
2. press home key to go home
3. adb shell kill <the test activity process>
4. open recent app list and restart the test activity

科特林

必须重写onSaveInstanceState和onRestoreInstanceState以存储和检索要持久化的变量

生命周期图

存储变量

public override fun onSaveInstanceState(savedInstanceState: Bundle) {
    super.onSaveInstanceState(savedInstanceState)

    // prepare variables here
    savedInstanceState.putInt("kInt", 10)
    savedInstanceState.putBoolean("kBool", true)
    savedInstanceState.putDouble("kDouble", 4.5)
    savedInstanceState.putString("kString", "Hello Kotlin")
}

检索变量

public override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)

    val myInt = savedInstanceState.getInt("kInt")
    val myBoolean = savedInstanceState.getBoolean("kBool")
    val myDouble = savedInstanceState.getDouble("kDouble")
    val myString = savedInstanceState.getString("kString")
    // use variables here
}

相反,您应该使用ViewModel,它将在活动生命周期之前保留数据。

现在,在视图模型中使用两种方法是有意义的。如果要将第一个保存为保存的实例:您可以像这样在视图模型中添加状态参数https://developer.android.com/topic/libraries/architecture/viewmodel-savedstate#java

或者您可以在视图模型中保存变量或对象,在这种情况下,视图模型将保存生命周期,直到活动被破坏。

public class HelloAndroidViewModel extends ViewModel {
   public Booelan firstInit = false;

    public HelloAndroidViewModel() {
        firstInit = false;
    }
    ...
}

public class HelloAndroid extends Activity {

  private TextView mTextView = null;
  HelloAndroidViewModel viewModel = ViewModelProviders.of(this).get(HelloAndroidViewModel.class);
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mTextView = new TextView(this);

    //Because even if the state is deleted, the data in the viewmodel will be kept because the activity does not destroy
    if(!viewModel.firstInit){
        viewModel.firstInit = true
        mTextView.setText("Welcome to HelloAndroid!");
    }else{
       mTextView.setText("Welcome back.");
    }

    setContentView(mTextView);
  }
}