Android 在活动和服务之间共享大量数据

Android 在活动和服务之间共享大量数据,android,multithreading,service,Android,Multithreading,Service,好的,我已经研究了解决这个问题的最佳方法一段时间了,所以让我为您详细介绍一下我的需求和发现 需要: 活动[SendMsg]构成一个消息正文,其中可能包含高达5MB的图像附件 当用户发送此消息时,必须将该消息上载到我的服务器 这个上传必须同步进行,因为我会阻止用户使用应用程序,直到它完成或失败 完成后,如果发送成功,SendMsg活动将被销毁,否则将显示错误对话框 在任何电话轮换或主页按钮按下/电话呼叫等情况下,上传和用户体验必须持续 最后一颗子弹是最硬的 调查结果: 我曾想过只在静态异步任务

好的,我已经研究了解决这个问题的最佳方法一段时间了,所以让我为您详细介绍一下我的需求和发现

需要:

  • 活动[SendMsg]构成一个消息正文,其中可能包含高达5MB的图像附件
  • 当用户发送此消息时,必须将该消息上载到我的服务器
  • 这个上传必须同步进行,因为我会阻止用户使用应用程序,直到它完成或失败
  • 完成后,如果发送成功,SendMsg活动将被销毁,否则将显示错误对话框
  • 在任何电话轮换或主页按钮按下/电话呼叫等情况下,上传和用户体验必须持续
最后一颗子弹是最硬的

调查结果:

我曾想过只在静态异步任务中完成这项工作,但我认为这对我来说并不适用——状态变得非常混乱,似乎我无法保证当应用程序在后台时,操作系统不会杀死线程

我决定使用一个服务,在该服务中创建并绑定/解除与活动的绑定。该服务生成一个异步任务,执行该工作,然后根据其结果(成功/失败)向活动发送信号。除了我的大消息之外,这个范例似乎工作得很好。服务/活动通信消息不是为编组如此大的有效负载而进行的*注意:如果不清楚,当用户点击send时,此表单数据和文件必须可供服务使用。在某些情况下,这是从相机拍摄的图像,在应用程序中磁盘上不存在,也不可能存在

显然,我想要的是某种共享内存存储,在这里我可以保存活动中的数据。然后,活动可以向服务发出信号,表明它可以继续并上传数据

内存中是否存在这样的共享区域?我可以从服务获取应用程序对象并将数据存储在那里吗

另一个问题发生在上传完成但没有活动绑定到服务时,但我想我可能已经解决了这个问题。请让我知道以下内容是否合理:

  • 服务完成上传
  • 服务检查活动当前是否已绑定
  • 如果是,则返回活动通过其消息队列处理的错误消息
  • 如果否,则将返回代码存储在该共享内存区域中,并在那里标记一个布尔值
  • 创建/恢复客户端活动时,应首先检查此布尔值,以查看流程是否已完成。如果是这样,将消息分派给它自己的处理程序,并像以前一样处理代码

  • 创建一个带有静态变量的类,并让您的活动设置该类的所有值。然后启动一个IntentService,让该服务查看上面的类。IntentService处理完消息后,它将广播消息,如果有任何活动等待广播,它们将收到消息。

    首先,您还应将服务切换到前台服务,并通过调用
    startService()
    来触发该服务(而不是绑定到服务)。这将确保服务尽可能长时间保持活动状态。绑定到服务将在您的活动完成后停止服务(用户离开应用时可能会发生这种情况)

    我还将利用前台服务使用的通知,让用户知道他们上传的状态

    要将信息从服务传递回您的活动,您可以查看ResultReceiver类。具体来说,请查看Google在其一个IO应用程序中实现的DetachableResultReceiver范例


    由于除了通信需求外,还需要大量内存,因此可能只需要创建一个单例对象,以便在活动和服务之间共享数据和状态

    为了满足您的内存需求,我可能会使用UUID的
    映射
    到包含所有消息详细信息的holder类。将此
    映射
    存储为
    应用程序
    子类中的成员变量或静态变量确保在任务完成或失败时清除此项。如果您确定不会同时处理多个此类请求,那么您可以使用单个类,而不是映射或列表

    然后,您可以在的帮助下使用完成您的需求。我倾向于避免Android中的绑定服务,因为由于屏幕旋转,它们很难使用。只需在启动
    IntentService
    的意图中从映射中传入标识符

    在我看来,从您的服务回到您的活动的最佳沟通方式是使用
    pendingent
    。基本上,您从活动开始服务,并在启动服务的意图中传递一个
    pendingent
    。当您的服务完成其工作或失败时,您可以在PendingEvent上调用
    send()
    。然后,您的活动将在其
    onActivityResult()
    方法中获得回调

    这样做有几个好处:

    • 它是线程安全的。您可以在
      IntentService
      中的一个单独线程中完成一个长时间运行的任务,并在完成任务后在UI线程上收到通知
    • 这支持屏幕旋转!您可以随心所欲地旋转活动,仍然可以在activityresult()上获得回调。相反,即使在发送PendingEvent之前
      finish()
      您的活动并开始一个新的活动,它也不会被交付,这几乎总是您想要的
    我有一个例子可以说明这种方法。基本上,您有一个启动一些工作的程序,并通过一个进度对话框阻止UI。如果屏幕显示错误,将再次显示此对话框