首先,我会说我自己正在学习这个,但我已经设法让这个精确的设置在原型中工作。如果有人看到应该更改以在 Android 中更好地工作的东西,请务必告诉我。
其次,我使用空消息,以便我们拥有可以实际工作的代码。我认为创建消息对象是直截了当的。
第 1 部分 - 网络线程的 UI
据我所知,Handler 是您需要的答案,但它不是全部。Deucalion 对 Looper 的评论是您接下来需要关注的地方。
http://developer.android.com/reference/android/os/Looper.html
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
这个设置一开始是反直觉的,你需要在你的方法内部Looper.prepare()
和Looper.loop()
调用之间创建 Handler 对象。run()
我不知道幕后的魔力,还没有机会在兔子洞里走得那么远。
重要说明:该示例显示了正在创建的匿名 Handler()。我强烈建议在您自己的类中子类化 Handler,然后使用它的实例。这只是可重用性的问题,很多网络代码最终都是一样的。
所以,重命名LooperThread
为NetworkThread
,或者任何你想要的名字,并将你的连接代码放在run()
方法中,但在Looper.prepare() / Looper.loop()
块之外(我不知道魔法是如何工作的,所以我只是假设这更好做的比把它放在里面)。
// process incoming messages here
往往看起来像这样:
switch(msg.what)
{
case 1:
break;
default:
break
}
LooperThread 示例有public Handler mHandler;
,但我更喜欢将处理程序设为私有并创建一个方法来返回它。我这样做只是为了防止处理程序在建立网络连接之前无法访问。没有联系,与消息无关。
因此,在您的活动代码中的某处,您创建NetworkThread
对象、运行它,然后从中获取处理程序。
NetworkThread network = new NetworkThread();
new Thread(network).run();
//Handler networkHandler = network.handler;
Handler networkHandler = network.getHandler();
然后,您只需根据需要向该处理程序发送消息。
networkHandler.sendEmptyMessage(1);
第 2 部分 - 到 UI 的网络线程
有几种不同的方法来处理这个问题。您可以在 Activity 类中创建一个处理程序。所有活动都已经设置了 Looper,因此调用 Looper.prepare 和 Looper.loop 似乎会导致问题。
在我的代码中,我在onCreate()
方法中创建了一个处理程序,然后将它传递给我的NetworkThread
对象。可能有更好的地方来创建这个处理程序,我不知道如果您的应用程序被暂停然后稍后再次启动会发生什么onResume()
或onRestart()
public NetworkThread(Handler mainHandler)
{
this.mainHandler = mainHandler;
}
然后在其他任何地方我需要向 UI 发送消息:
this.mainHandler.sendEmptyMessage(1);
我更喜欢这种方法,因为执行实际工作的 Handler 代码要么存在于实际响应消息的类中(使用匿名 Handler 对象),要么存在于可能位于同一包中的 Handler 子类中。
您也可以将Activity
or传递View
给网络线程并从该 callrunOnUIThread(Runnable)
传递,但这需要您传递 Runnable。因此,在网络类中编写或引用了用于 UI 的代码。
更新
您也可以为此使用服务。当 Activity 和 Networking 具有相同的生命周期时,上述方法有效。如果我们只需要在 Activity 处于活动状态时进行网络连接。
如果您需要 Activity 生命周期之外的网络连接,例如在音乐流媒体应用中,那么使用 Service 将是更好的选择。看起来这并不是您要寻找的问题。