java在UI线程和后台网络线程之间交换消息
我目前正在开发一款安卓应用程序,仅供个人使用。该应用程序通过TCPsocket与服务器通信。如果用户输入,需要立即发送。此外,在任何给定的时间,都可能有来自服务器的消息需要显示在UI上。对于所有的社交活动,我都有一个背景线索
由于我需要在任何用户输入时将消息从UI传递到网络线程,并且在任何给定时间将消息从网络线程传递到UI,因此我的问题如下:如何传递消息?我已经读了3个小时关于Handler类的书,但我什么都想不出来。处理程序是如何工作的?什么是一个整洁而平稳的实现呢?我更多的是寻找实现这一目标的策略,而不一定是实施细节
提前非常感谢
# 1 楼答案
在这种情况下,可以使用
AsyncTask
。 您可以在UI线程上调用它,并在onPostExecute中对消息执行您想要执行的操作。 这比在那里做所有肮脏的网络工作要干净得多# 2 楼答案
http://developer.android.com/reference/android/os/AsyncTask.html使用这个,我在处理程序方面也有很多问题,但是异步任务可以为您处理所有这些烦人的工作。确保使用onPrexecute()和onPostExecute()更新UI。希望这有帮助
# 3 楼答案
首先,我会说我自己也在学习,但我已经成功地在原型中实现了这个精确的设置。如果有人看到一些需要改进的东西,请务必告诉我
其次,我使用的是空消息,这样我们就有了实际工作的代码。我认为创建消息对象已经足够简单了
第1部分-用户界面到网络线程
就我所见,Handler是你需要的答案,但它不是全部。Deucalion关于Looper的评论是你接下来需要关注的地方
http://developer.android.com/reference/android/os/Looper.html
这种设置首先是违反直觉的,您需要在
Looper.prepare()
和Looper.loop()
调用之间,在run()
方法内部创建处理程序对象。我不知道幕后的魔力,也没有机会深入兔子洞那么深重要提示: 此示例显示正在创建的匿名处理程序()。我强烈建议您在自己的类中对处理程序进行子类化,然后使用该类的实例。这只是可重用性的问题,很多网络代码最终都是一样的
因此,将
LooperThread
重命名为NetworkThread
,或者你想要的任何东西,并将连接代码放在run()
方法中,但放在Looper.prepare() / Looper.loop()
块之外(同样,我不知道这个魔法是如何工作的,所以我只是假设这样做比把它放在里面更好)倾向于这样:
LooperThread示例有
public Handler mHandler;
,但我更喜欢将处理程序设置为私有,并创建一个方法来返回它。我这样做只是为了防止在建立网络连接之前访问处理程序。没有连接,与信息无关因此,在活动代码的某个地方创建
NetworkThread
对象,运行它,然后从中获取处理程序然后根据需要向处理程序发送消息
第2部分-网络线程到用户界面
有几种不同的方法来处理这个问题。可以在Activity类中创建一个处理程序。所有活动都已经设置了Looper,因此调用Looper。准备好活套。循环似乎会导致问题
在我的代码中,我在
onCreate()
方法中创建了一个处理程序,然后将其传递到我的NetworkThread
对象中。可能有更好的地方可以创建这个处理程序,我不知道如果你的应用程序被挂起,然后用onResume()
或onRestart()
再次启动,会发生什么然后我需要在其他任何地方向UI发送消息:
我更喜欢这种方法,因为执行实际工作的处理程序代码要么存在于实际响应消息的类中(使用匿名处理程序对象),要么存在于同一个包中的处理程序子类中
您还可以将
Activity
或View
传递给网络线程,并从该调用runOnUIThread(Runnable)
传递,但这需要传递一个Runnable。因此,用于UI的代码正在网络类中编写或引用更新
你也可以使用服务来实现这一点。当活动和网络具有相同的生命周期时,上述方法有效。如果我们只需要在活动期间连接网络
如果你在活动结束后还需要网络连接,比如在音乐流应用程序中,那么使用服务将是更好的选择。看起来这并不是你想问的问题