Android客户端使用线程与服务器通信的最佳实践

时间:2013-08-18 21:33:51

标签: java android client-server

我正在构建一个Android应用程序,只要应用程序正在运行,它就会定期与服务器通信。

我通过在应用启动时启动与服务器的连接来实现此目的,然后我有一个单独的thread用于接收名为ReceiverThread的消息,此threadsocket读取消息{1}},分析它,并将其转发到应用程序的适当部分。

这个thread在循环中运行,读取它必须读取的内容,然后在read()命令上阻塞,直到新数据到达,因此它将大部分时间用于阻止。

我处理通过名为SenderThread的其他线程发送消息。我想知道的是:我应该以类似的方式构建SenderThread吗?我应该为这个线程维护一些形式的队列,让它发送队列中的所有消息,然后阻塞,直到新消息进入队列,或者每次需要发送消息时我应该只是启动线程的新实例,让它发送消息,然后“死”?我倾向于第一种方法,但我不知道在性能方面(在内存中保持阻塞线程与初始化新线程)以及代码正确性方面实际上更好。

此外,由于我的所有活动都需要能够发送和接收消息,我持有对Application类中的两个线程的引用,这是一种可接受的方法还是应该以不同的方式实现它?

我遇到的一个问题是,有时如果我关闭我的应用程序并再次运行它实际上有两个ReceiverThread实例,所以我得到一些消息两次。

我猜这是因为我的应用程序实际上没有关闭,前一个线程仍处于活动状态(在read()操作中被阻止),当我再次打开应用程序时,新的线程被初始化,但两者都是已连接到服务器,因此服务器将消息发送到两者。有关如何解决此问题的任何提示,或者如何完全重新组织它以使其正确无误?

我尝试查找这些问题,但发现了我的第一个问题的一些相互矛盾的例子,没有任何有用的东西适用于我的第二个问题......

1 个答案:

答案 0 :(得分:19)

1。如果真的需要不惜一切代价在服务器和客户端之间保持开放连接,那么您的方法是可以的。但是我会使用异步连接,比如向服务器发送HTTP请求,然后在服务器感觉到它时得到回复。

如果您需要服务器稍后回复客户端,但您不知道何时,您还可以查看Google Cloud Messaging framework,它为您提供透明且一致的发送小消息的方式从您的服务器到您的客户。

在开发移动应用程序时,您需要考虑一些事情。

  1. 智能手机没有无穷无尽的电量。

  2. 智能手机的互联网连接有些不稳定,您将在不同时间失去互联网连接。

  3. 当您始终保持与服务器的直接连接时,您的应用程序会继续发送保持活动的数据包,这意味着您将非常快地吸干手机。 当互联网连接与移动宽带上的连接一样不稳定时,您有时会丢失连接并需要从中恢复。因此,如果您使用TCP,因为您希望确保收到数据包,则需要多次重新发送相同的数据包,因此会产生大量开销。

    如果你自己在服务器上打开线程,你可能会遇到服务器端的线程问题,这听起来像。假设您有200个客户端同时连接到服务器。每个客户端在服务器上打开1个线程。如果服务器需要同时为200个不同的线程服务,那么最终这对服务器来说可能是一项非常耗费性能的任务,你也需要自己做很多工作。

    2。当您退出应用程序时,您需要在清理完毕后进行清理。这应该在onPause处于有效状态的Activity方法中完成。

    这意味着,杀死所有活动线程(或者至少中断它们),保存UI的状态(如果需要),并刷新和关闭与服务器的任何打开连接。

    就使用Threads而言,我建议使用一些内置线程工具,例如Handlers或实施AsyncTask

    如果您真的认为Thread是可行的方法,我肯定会建议您使用Singleton pattern作为线程的“经理”。

    这个管理员会控制你的线程,所以你不会在任何给定的时间内与服务器交换多个Thread,即使你在应用程序的另一部分。

    Application类实现而言,请查看Application class documentation

      

    需要维护全局应用程序状态的基类。您可以通过在AndroidManifest.xml的标记中指定其名称来提供自己的实现,这将导致在创建应用程序/包的过程时为您实例化该类。

         

    通常不需要子类Application。在大多数情况下,静态单例可以以更模块化的方式提供相同的功能。

    建议您远离实施自己的Application课程,但是如果您让Activities个人初始化您自己的Singleton课程来管理Threads和关联你可能(只是可能)遇到麻烦,因为单例的初始化可能会“绑定”到特定的Activity,所以如果从屏幕上删除特定的Activity并暂停它可能会被杀死所以单身人士也可能被杀死。因此,在Application实现中初始化单例可能会有用。

    对不起文字的墙,但你的问题是“开放式的”,所以我试图给你一个有点开放式的问题 - 希望它有所帮助; - )