【问题标题】:How to save data in an android app如何在安卓应用中保存数据
【发布时间】:2012-06-09 15:44:38
【问题描述】:

我最近编写了一个 Android 应用程序。它只是一个简单的应用程序,可让您通过几个简单的计数器间隔来保持篮球比赛的得分。我收到了添加保存功能的需求,这样您就可以保存您的分数,然后将它们重新加载。目前,当您停止应用程序时,您的数据会丢失。所以我想知道的是我必须添加什么才能让应用程序保存一个标签(分数)然后重新加载它。谢谢大家,抱歉我对这些东西了解不多。

【问题讨论】:

  • 老实说,我觉得很难通过 android 文档。我们都带着爱在这里

标签: android


【解决方案1】:

你有两个选择,我会留给你选择。

  1. 共享偏好

    这是一个 Android 独有的框架,允许您在键值框架中存储原始值(例如 intboolean,String,尽管严格来说 String 不是原始值) .这意味着您为一个值命名,例如“homeScore”并将该值存储到此键中。

    SharedPreferences settings = getApplicationContext().getSharedPreferences(PREFS_NAME, 0);
    SharedPreferences.Editor editor = settings.edit();
    editor.putInt("homeScore", YOUR_HOME_SCORE);
    
    // Apply the edits!
    editor.apply();
    
    // Get from the SharedPreferences
    SharedPreferences settings = getApplicationContext().getSharedPreferences(PREFS_NAME, 0);
    int homeScore = settings.getInt("homeScore", 0);
    
  2. 内部存储

    在我看来,这就是您可能正在寻找的东西。您可以将所需的任何内容存储到文件中,因此这为您提供了更大的灵活性。但是,这个过程可能会比较棘手,因为所有内容都将存储为字节,这意味着您必须小心让您的读取和写入进程一起工作。

    int homeScore;
    byte[] homeScoreBytes;
    
    homeScoreBytes[0] = (byte) homeScore;
    homeScoreBytes[1] = (byte) (homeScore >> 8);  //you can probably skip these two 
    homeScoreBytes[2] = (byte) (homeScore >> 16); //lines, because I've never seen a                   
                                                  //basketball score above 128, it's
                                                  //such a rare occurance.
    
    FileOutputStream outputStream = getApplicationContext().openFileOutput(FILENAME, Context.MODE_PRIVATE);
    outputStream.write(homeScoreBytes);
    outputStream.close();
    

现在,您也可以查看External Storage,但我不建议在这种特殊情况下这样做,因为以后可能不会有外部存储。 (注意,如果你选择这个,它需要一个权限)

【讨论】:

  • LOL - 我喜欢这样的评论“因为我从未见过超过 128 的篮球得分”:-) 顺便说一句:供您参考:nba.com/pistons/news/highest_score_071211.html
  • 在海拉尔,世界上最富有的人只能拥有 255 卢比。 ;)
  • 我认为你也可以使用 sqlite 进行存储
  • 我也想将游戏(5 个结果)存储到内部存储中。在我显示从内部存储中获取数据的分数之后。有样品吗?
  • 如果我将数据存储在内部存储中,如果我卸载应用程序,文件会被删除吗?
【解决方案2】:

OP 要求一个“保存”功能,它不仅仅是在程序执行期间保存数据(您必须这样做才能使应用有价值。)

我建议将数据保存在 sdcard 上的文件中,这样您不仅可以稍后再调用它,还可以让用户将设备作为外部驱动器安装在自己的计算机上并获取数据以在其他地方使用。

所以你真的需要一个多点系统:

1) 实现onSaveInstanceState()。在这个方法中,你被传递了一个Bundle,它基本上就像一个字典。在捆绑包中存储尽可能多的信息,以便在应用程序停止的位置重新启动应用程序。在您的 onCreate() 方法中,检查传入的包是否为非空,如果是,则从包中恢复状态。

2) 实现onPause()。在此方法中,创建一个 SharedPreferences 编辑器并使用它来保存您下次启动应用程序所需的任何状态。这主要包括用户的偏好(因此得名),但与应用程序的启动状态相关的任何其他内容也应该放在此处。我不会在此处存储分数,只是您需要重新启动应用程序的东西。然后,在onCreate() 中,只要没有捆绑对象,就使用 SharedPreferences 接口来调用这些设置。

3a) 至于分数之类的东西,你可以按照上面 Mathias 的建议,将分数存储在 getFilesDir() 返回的目录中,使用 openFileOutput() 等。我认为这个目录是应用程序私有的,并且存在于 main存储,这意味着其他应用程序和用户将无法访问数据。如果你没问题,那么这可能就是要走的路。

3b) 如果您确实希望其他应用程序或用户能够直接访问数据,或者如果数据将非常大,那么 sdcard 是您的最佳选择。选择一个目录名称,如 com/user1446371/basketballapp/ 以避免与其他应用程序发生冲突(除非您确定您的应用程序名称是合理唯一的)并在 sdcard 上创建该目录。正如 Mathias 所指出的,您应该首先确认 sdcard 已安装。

File sdcard = Environment.getExternalStorageDirectory();
if( sdcard == null || !sdcard.isDirectory()) {
    fail("sdcard not available");
}
File datadir = new File(sdcard, "com/user1446371/basketballapp/");
if( !datadir.exists() && !datadir.mkdirs() ) {
    fail("unable to create data directory");
}
if( !datadir.isDirectory() ) {
    fail("exists, but is not a directory");
}
// Now use regular java I/O to read and write files to data directory

我建议为您的数据提供简单的 CSV 文件,以便其他应用程序可以轻松读取它们。

显然,您必须编写允许“保存”和“打开”对话框的活动。我通常只是调用 openintents 文件管理器并让它完成工作。但是,这需要您的用户安装 openintents 文件管理器才能使用这些功能。

【讨论】:

  • 还有一条评论:如果可能的话,在不同的线程中进行阅读和写作,尤其是写作。否则,您的应用会死机,用户体验会不太理想。
  • 只有一条评论:我九年前写了这个答案,我相信其中一些方法已被弃用。将此答案仅作为粗略指南。
【解决方案3】:

在 onCreate 中:

SharedPreferences sharedPref = getSharedPreferences("mySettings", MODE_PRIVATE);

    String mySetting = sharedPref.getString("mySetting", null);

在 onDestroy 或等效项中:

SharedPreferences sharedPref = getSharedPreferences("mySettings", MODE_PRIVATE);

    SharedPreferences.Editor editor = sharedPref.edit();
    editor.putString("mySetting", "Hello Android");
    editor.commit();

【讨论】:

    【解决方案4】:

    使用 SharedPreferences,http://developer.android.com/reference/android/content/SharedPreferences.html

    这是一个示例: http://developer.android.com/guide/topics/data/data-storage.html#pref

    如果数据结构比较复杂或者数据量大,使用Sqlite数据库;但是对于少量数据和非常简单的数据结构,我想说,SharedPrefs 就可以了,而且数据库可能是开销。

    【讨论】:

    • 没错。使用比这更复杂的东西只是矫枉过正和愚蠢的想法。只需要 SharedPreferences。
    【解决方案5】:

    有很多选项可以存储您的数据,Android 让您可以选择任何人 您的数据存储选项如下:

    共享偏好 将私有原始数据存储在键值对中。 内部存储器 将私有数据存储在设备内存中。 外部存储 将公共数据存储在共享的外部存储上。 SQLite 数据库 将结构化数据存储在私有数据库中。 网络连接 使用您自己的网络服务器将数据存储在网络上

    查看here 获取示例和教程

    【讨论】:

      【解决方案6】:

      2021 年答案

      老问题,但在 2021 年,您可以使用多种方法来保存数据。

      1.使用本地数据库 - 房间图书馆

      Room 是一个库,可让您将数据存储在 Android 设备随附的内部 SqlLite 数据库中,它是一个本地数据库。它既简单又非常强大。

      https://developer.android.com/training/data-storage/room

      2。使用远程数据库 - Firebase / 你自己的数据库实现

      您可以在服务器上使用 Firebase 服务或您自己的数据库实现来远程存储您的数据,这样您就可以通过多个设备访问数据。

      https://firebase.google.com/docs/firestore

      3.存储本地文件

      您可以将所有信息存储在设备外部存储中保存的本地文件中,可能使用带有 \n 作为数据分隔符的 .txt 文件。这个选项在 2021 年看起来真的很“穴居人”。

      https://stackoverflow.com/a/14377185/14327871

      4.使用 SharedPreferences

      正如许多人指出的那样,您还可以使用 sharedPreferences 将少量信息存储为键值对,例如在跨会话保存用户首选项时很有用。

      https://developer.android.com/training/data-storage/shared-preferences?hl=en

      对于 OP 情况,我建议使用第一个或第二个选项。

      【讨论】:

        【解决方案7】:
        1. 共享首选项: android shared preferences example for high scores?

        2. 您的应用程序是否可以访问“外部存储媒体”。如果是这样,那么您可以简单地将值(与时间戳一起存储)写入文件并保存。如果这就是您要查找的内容,时间戳将帮助您显示进度。 {不是一个聪明的解决方案。}

        【讨论】:

        • 关于2)不需要使用外部存储,这总是需要检查(是否安装了sdcard)。为什么不只使用应用程序的缓存或文件目录? (getFilesDir(), getCacheDir())。
        • @MathiasLin 你应该发布一个完整的答案。
        • @thomasfedb 我已经发布了对这个问题的第一个回复,并且通过链接和链接示例,这应该是他所需要的。我错过了什么?
        【解决方案8】:

        请不要忘记一件事 - 卸载应用程序时会删除内部存储数据。在某些情况下,它可能是“意外功能”。那么使用外部存储就好了。

        Google docs about storage - 请特别查看 getExternalStoragePublicDirectory

        【讨论】:

          【解决方案9】:

          快速回答:

          public class MainActivity extends AppCompatActivity implements View.OnClickListener {
          
              Boolean Music;
          
              public static final String PREFS_NAME = "MyPrefsFile";
          
              @Override
              protected void onCreate(Bundle savedInstanceState) {
                  super.onCreate(savedInstanceState);
                  setContentView(R.layout.activity_main);
          
                  //restore preferences
                  SharedPreferences settings = this.getSharedPreferences(PREFS_NAME, 0);
                  Music = settings.getBoolean("key", true);
              }
          
              @Override
              public void onClick() {
          
                          //save music setup to system
                          SharedPreferences settings = this.getSharedPreferences(PREFS_NAME, 0);
                          SharedPreferences.Editor editor = settings.edit();
                          editor.putBoolean("key", Music);
                          editor.apply();
              }
          }
          

          【讨论】:

            【解决方案10】:

            您可以存储您的分数并轻松加载它们!通过使用这种方法 使用这个库Paper Db

            在您的应用中添加此库:

            implementation 'io.github.pilgr:paperdb:2.7.1'
            

            然后在你存储的活动 onCreate() 中初始化一次:

            Paper.init(context)
            

            创建一个密钥来存储您的分数

            int myScore=10;
            Paper.book().write("scores", myScore);
            

            并获取分数的值:

            int mySavedScores=Paper.book().read("scores");
            

            就是这样!!!现在即使应用程序关闭,您也可以保存和访问值 并参考文档以获取更多方法和信息, 阅读文档是一个好习惯。

            【讨论】:

              【解决方案11】:

              在我看来,db4o 是最简单的方法。 在这里你可以找到一个教程: http://community.versant.com/documentation/reference/db4o-7.12/java/tutorial/

              您可以在这里下载库:

              http://www.db4o.com/community/download.aspx?file=db4o-8.0-java.zip

              (只需将 lib 目录中的 db4o-8.0...-all-java5.jar 放入项目的 libs 文件夹即可。 如果您的项目中没有 libs 文件夹,请创建它)

              由于 db4o 是一个面向对象的数据库系统,您可以直接将对象保存到数据库中,然后再将它们取回。

              【讨论】:

              • db4o 对我来说似乎有点开销。如果有的话,由于 Android 带来的支持,sqlite db 可能会更容易,但是对于少量非常基本的数据,我想说,SharedPrefs 就足够了。
              • 在我看来,db4o 比 sql 容易得多,尤其是对于初学者而言。而且比这个丑陋的共享首选项更少摆弄:-)
              • 有点跑题了——但是......:我很久以前就研究过 db4o,用于非 Android 项目,这个想法还不错;我不喜欢 db4o 的地方在于它是专有的。如果不想直接处理sql,我也可以推荐ORMLite作为ORM库(ORM = object-relational-mapping)。尽管如此,毫无疑问,我猜 db4o 也可以很好地完成这样的任务。
              【解决方案12】:

              使用这些方法可以非常轻松地使用 sharedPreferences。

              private val sharedPreferences = context.getSharedPreferences("myPreferences", Context.MODE_PRIVATE)
              
              fun put(key: String, value: String) = sharedPreferences.edit().putString(key, value).apply()
              
              fun put(key: String, value: Int) = sharedPreferences.edit().putInt(key, value).apply()
              
              fun put(key: String, value: Float) = sharedPreferences.edit().putFloat(key, value).apply()
              
              fun put(key: String, value: Boolean) = sharedPreferences.edit().putBoolean(key, value).apply()
              
              fun put(key: String, value: Long) = sharedPreferences.edit().putLong(key, value).apply()
              
              fun getString(key: String, defaultValue: String? = null): String? = sharedPreferences.getString(key, defaultValue)
              
              fun getInt(key: String, defaultValue: Int = -1): Int = sharedPreferences.getInt(key, defaultValue)
              
              fun getFloat(key: String, defaultValue: Float = -1F): Float = sharedPreferences.getFloat(key, defaultValue)
              
              fun getBoolean(key: String, defaultValue: Boolean = false): Boolean = sharedPreferences.getBoolean(key, defaultValue)
              
              fun getLong(key: String, defaultValue: Long = -1L): Long = sharedPreferences.getLong(key, defaultValue)
              
              fun clearAll() = sharedPreferences.edit().clear().apply()
              

              将它们放在一个类中并在其构造函数中获取上下文。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2017-09-12
                • 1970-01-01
                • 1970-01-01
                • 2017-10-12
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多