【问题标题】:Android: IntentService. Where to save files?安卓:意图服务。在哪里保存文件?
【发布时间】:2013-11-30 21:36:47
【问题描述】:

这个问题是我看到ianhanniballake的评论后编辑的。我删除了不相关的部分。

我有一个意图服务被AlarmManager反复调用,并读取一些文件(文件内容很少改变)以提取PublicKey对象。

存储文件(定期访问)的最佳位置是什么?最快的记忆是什么? 我猜是 SharedPreferences、InternalStorage 和最后是 ExternalStorage,但我没有找到这个问题的答案。

有没有什么技术可以有效地进行这样的程序(无需每次都读取文件)?

【问题讨论】:

  • IntentServices 是 Context(与 Service 相同)那么有什么问题?
  • 你是对的。我是我的错。我将编辑我的问题。 10 倍!
  • 具体来说-以下两个选项哪个更有效? (1) 将公钥作为base64字符串保存在SharedPreferences中(代价是从SharedPreferences中读取,解码为字节)。 (2) 将pk作为二进制文件保存在InternalStorage中(成本只是从InternalStorage中读取)。
  • 在下面查看我的答案。我认为使用内部存储器快速且资源消耗更少,每部手机/设备都有内部存储器。这样您就不必依赖具有 sd 卡的设备,但您当然可以更改您的代码以首先检查它,如果手机有它使用它来释放设备数据的内部空间,而不是应用程序数据.

标签: android android-intent android-service alarmmanager intentservice


【解决方案1】:
  1. 这取决于您对文件执行的操作。我建议在使用您的应用程序时缓存文件,然后在调用 onPause() 函数时保存到存储中。至于内部存储与外部存储之间的选择,Android 文档指定了每个 here 和 here 的详细信息,以便您做出正确的决定。
  2. 可以使用任何类型的存储,只需参考文档以了解如何执行此操作。如果您必须在服务的构造函数中传递上下文,或者如果您使用 IntentService 只需使用 getBaseContext()
  3. 使用 Service 类没有任何问题,它为您提供与 IntentService 相同的功能。但它实现起来更复杂,并且包括绑定到服务的功能,你似乎不需要在这里做。 IntentService 只能启动,不能同时处理多个请求(这两个对您的应用程序来说似乎都不是问题)。还有一点需要注意的是,一个覆盖 Service 的类运行在 UI 线程上,所以你必须实现自己的线程。同样,这没什么大不了的,但它增加了代码的复杂性,以访问您甚至可能不需要使用的功能。 From the Android docs:

注意:服务在其托管进程的主线程中运行——该服务不会创建自己的线程,也不会在单独的进程中运行(除非您另有指定)。这意味着,如果您的服务要执行任何 CPU 密集型工作或阻塞操作(例如 MP3 播放或网络),您应该在服务中创建一个新线程来完成这项工作。通过使用单独的线程,您将降低应用程序无响应 (ANR) 错误的风险,并且应用程序的主线程可以保持专用于用户与您的活动的交互。

【讨论】:

  • 感谢您的回答。看到ianhanniballake 的评论后,我编辑了我的问题。一般来说,对于我的情况(PublicKey 对象),保存文件以便快速访问的地方在哪里?
【解决方案2】:

我不确定您要在大局中实现什么目标。但我会尽力回答您更有针对性的问题。

  1. 对于存储文件,您实际上没有太多选择 - 它将是内部或外部文件系统和/或云上。如果您想以非文件格式存储数据,您的选择将扩展到包括内置 SQLite 数据库和 SharedPreferences(持久)
  2. 我看不出您不能将 SharedPreferences 或内部存储与 IntentService 一起使用。 IntentService 和应用程序的其余部分都在相同的 Linux 用户 ID 下运行,即进程。因此,您应该也可以使用 SharedPreferences 或 Internal Storage。
  3. IntentService 扩展 Service 并自动为您创建一个工作线程。它使您可以轻松管理线程。如果你只是使用 Service 代替,你必须自己创建和管理工作线程。所以,IntentService 使用起来更方便一些。使用 IntentService 的唯一缺点是您不能同时处理多个请求,它会将请求排队并一次处理一个。但是使用 Service,您可以编写代码来根据需要处理多个请求。当您使用 RPC 服务(进程间)时,最好不要使用 IntentService 并坚持使用普通服务。

HTH。

【讨论】:

  • 谢谢!我更新了我的问题。我注意到我对 IntentService 的上下文有误。实际上,由于错字,eclipse找不到相关的方法。我添加了有关特定情况的信息:保存公钥(例如,我可以将其保存为 SharedPreferences 中的字符串)。
  • @GariBN SharedPreferences 将是最快和最干净的,因为在卸载应用程序时它们将被删除。因此,您不必主动管理或清理它们。但是您不能将文件保存到 SharedPrefs - 只有原语。请接受其中一个答案,以便对其他人有所帮助。
  • 我明白为什么它是最干净的。你能告诉我为什么它是最快的吗?这是我的直觉,但我找不到任何可靠的信息来源。
  • @GariBN 你不应该担心这样的事情。在应用程序级别,您的重点应该是为您的目的选择最佳工具。当我的意思是最快时,它是从应用程序开发人员的角度来看,您只需保存和检索数据。 SharedPreferences 对象在应用程序启动并准备就绪时已加载。您不必打开文件指针/描述符、设置 SQL 语句等。但最终,所有内容都会写入某个文件,对吗?该速度将是相同的 - 内部存储可能比外部或 Web 快一点。希望能回答你的问题。
  • 我明白了。无论如何,我希望有人能给我发一份参考资料来澄清这一点(哪个选项从正式来源最快)。感谢您的回答!
【解决方案3】:

在我看来,您应该为您的应用程序创建一个私有目录。然后,只要您的应用程序正在运行,您就可以从此私有目录中读取。您可以在 android.developer 页面上查看如何使用 http://developer.android.com/guide/topics/data/data-storage.html#filesInternal 轻松完成此操作。

我建议您这样做并通过在调用时将 Bundle 传递给您的 Intent 服务来处理上下文问题。

这是一个简短的示例解决方案:

将这些成员变量添加到您的类中

// Context for the Current Class context 
Context callingContext = this;

// final String identifier to Identify the Contents For the new Bundle 
private static final String KEY_CONTENTS = "FileContents";
// final String identifier to Identify the Bundle
private static final String KEY_BUNDLE = "FileContentBundle";
// final String File Name Identifier
private static final String FILE_NAME = "private_save_file";

// final Int Value or the Context.MODE_PRIVATE
private static final int PRIVATE = Context.MODE_PRIVATE;

// For the buffer length and file contents
int bufferLength;
String fileContents;

// ***** If your need to write to the file before reading *****
FileOutputStream outputInfo = openFileOutput(FILE_NAME, PRIVATE);
outputInfo.write("Contents to Write to your file.");
outputInfo.close();
// ***** Probably will be using another class to Write to the file ****



// **** Read the information from the file
FileInputStream fileToRead = openFileInput(FILE_NAME);

// Byte Array to write your File Contents To
byte[] buffer = new byte[1024];

// Loop through your files Contents
while((bufferLength = fileToRead.read(buffer) != -1){
   fileContents.append(new String(buffer));
}

// Create your new intent and pass in the information from your file
Intent myNewServiceIntent = new Intent();
myNewServiceIntent.setClass(callingContext, MyNewServiceIntent.class);

// Create a new Bundle to pass the file contents
Bundle args = new Bundle();
args.putString(KEY_CONTENTS,fileContents);
myNewServiceIntent.putExtra(KEY_BUNDLE, args);
startActivity(myNewServiceIntent);

您可以使用静态变量来定义每次调用意图服务的类中要读取的文件名。我不确定您的文件有多大以及捆绑对象的限制,或者这是否是您要查找的内容。希望这可以帮助。

你能发布一些代码吗?

【讨论】:

    猜你喜欢
    • 2017-09-12
    • 2016-11-06
    • 2018-03-01
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 2010-10-11
    • 2016-10-25
    • 2014-09-21
    相关资源
    最近更新 更多