我一直在安卓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分钟,没有发现任何明显的东西。


当前回答

Kotlin解决方案:对于onSaveInstanceState中的自定义类保存,您可以将类转换为JSON字符串并使用Gson转换进行恢复,对于单字符串、双精度、Int、Long值保存和恢复,如下所示。以下示例适用于片段和活动:

对于活动:

对于将数据放入saveInstanceState:

override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)

        //for custom class-----
        val gson = Gson()
        val json = gson.toJson(your_custom_class)
        outState.putString("CUSTOM_CLASS", json)

        //for single value------
        outState.putString("MyString", stringValue)
        outState.putBoolean("MyBoolean", true)
        outState.putDouble("myDouble", doubleValue)
        outState.putInt("MyInt", intValue)
    }

还原数据:

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

    //for custom class restore
    val json = savedInstanceState?.getString("CUSTOM_CLASS")
    if (!json!!.isEmpty()) {
        val gson = Gson()
        testBundle = gson.fromJson(json, Session::class.java)
    }

  //for single value restore

   val myBoolean: Boolean = savedInstanceState?.getBoolean("MyBoolean")
   val myDouble: Double = savedInstanceState?.getDouble("myDouble")
   val myInt: Int = savedInstanceState?.getInt("MyInt")
   val myString: String = savedInstanceState?.getString("MyString")
 }

您也可以在Activity onCreate上恢复它。

对于碎片:

对于saveInstanceState中的put类:

 override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        val gson = Gson()
        val json = gson.toJson(customClass)
        outState.putString("CUSTOM_CLASS", json)
    }

还原数据:

 override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        //for custom class restore
        if (savedInstanceState != null) {
            val json = savedInstanceState.getString("CUSTOM_CLASS")
            if (!json!!.isEmpty()) {
                val gson = Gson()
                val customClass: CustomClass = gson.fromJson(json, CustomClass::class.java)
            }
        }

      // for single value restore
      val myBoolean: Boolean = savedInstanceState.getBoolean("MyBoolean")
      val myDouble: Double = savedInstanceState.getDouble("myDouble")
      val myInt: Int = savedInstanceState.getInt("MyInt")
      val myString: String = savedInstanceState.getString("MyString")
    }

其他回答

不确定我的解决方案是否受到反对,但我使用绑定服务来保持ViewModel状态。是将其存储在服务的内存中,还是将其持久化并从SQLite数据库中检索,取决于您的需求。这就是任何类型的服务所做的,它们提供诸如维护应用程序状态和抽象公共业务逻辑之类的服务。

由于移动设备固有的内存和处理限制,我以类似于网页的方式处理Android视图。页面不维护状态,它纯粹是一个表示层组件,其唯一目的是显示应用程序状态并接受用户输入。web应用程序架构的最新趋势采用了古老的模型、视图、控制器(MVC)模式,其中页面是视图,域数据是模型,控制器位于web服务后面。同样的模式可以在Android中使用,视图是,嗯。。。View,模型是您的域数据,Controller作为Android绑定服务实现。每当您希望视图与控制器交互时,在开始/恢复时绑定它,在停止/暂停时解除绑定。

这种方法为您提供了实施关注点分离设计原则的额外好处,因为您的所有应用程序业务逻辑都可以移动到您的服务中,这减少了多个视图中的重复逻辑,并允许视图实施另一个重要的设计原则,即单一责任。

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

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

当“活动”转到后台时,确实会调用onSaveInstanceState()。

引用文档:“在活动被终止之前调用此方法,以便在将来某个时候返回时恢复其状态。”来源

2020年,我们有一些变化:

如果您希望“活动”在进程终止并再次启动后恢复其状态,则可能需要使用“保存状态”功能。以前,需要重写Activity中的两个方法:onSaveInstanceState和onRestoreInstanceState。您还可以在onCreate方法中访问恢复的状态。类似地,在Fragment中,您有onSaveInstanceState方法可用(恢复的状态在onCreate、onCreateView和onActivityCreated方法中可用)。

从AndroidX SavedState 1.0.0开始,它是AndroidX Activity和AndroidX Fragment的依赖项,您可以访问SavedStateRegistry。您可以从Activity/Fragment获取SavedStateRegistry,然后注册SavedStateProvider:

class MyActivity : AppCompatActivity() {

  companion object {
    private const val MY_SAVED_STATE_KEY = "MY_SAVED_STATE_KEY "
    private const val SOME_VALUE_KEY = "SOME_VALUE_KEY "
  }
    
  private lateinit var someValue: String
  private val savedStateProvider = SavedStateRegistry.SavedStateProvider {    
    Bundle().apply {
      putString(SOME_VALUE_KEY, someValue)
    }
  }
  
  override fun onCreate(savedInstanceState: Bundle?) {    
    super.onCreate(savedInstanceState)
    savedStateRegistry.registerSavedStateProvider(MY_SAVED_STATE_KEY, savedStateProvider)
    someValue = savedStateRegistry.consumeRestoredStateForKey(MY_SAVED_STATE_KEY)?.getString(SOME_VALUE_KEY) ?: ""
  }
  
}

如您所见,SavedStateRegistry强制您对数据使用键。这可以防止您的数据被附加到同一Activity/Fragment的另一个SavedStateProvider损坏。此外,您还可以将SavedStateProvider提取到另一个类中,以便通过使用所需的抽象来处理数据,从而在应用程序中实现干净的保存状态行为。

当系统需要内存并终止应用程序时,调用onSaveInstanceState。当用户刚刚关闭应用程序时,不会调用它。所以我认为应用程序状态也应该保存在onPause中。

它应该保存到一些持久性存储中,如Preferences或SQLite。