我一直在阅读很多关于线程,处理程序,loopers等的内容,我很困惑。在我的应用程序中,我希望第一个Activity启动后台工作程序。此后台工作程序将不断地从TCP套接字请求数据,并且(希望)在数据到达时将新信息发布到UI线程。如果用户转换到新的Activity,则后台需要继续执行该操作,但只向UI线程发送不同的消息,以便相应地更新新布局。
这是我到目前为止的...这是我的主要活动文件
public class MyTCPTest extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set the layout
setContentView(R.layout.main);
// create a handler to handle messages from bg thread
Handler handler = new Handler();
BgWorkerThread bgw = new BgWorkerThread();
bgw.start();
}
在另一个文件中我定义了我的后台工作线程......
public class BgWorkerThread extends Thread {
@Override
public void run(){
while(true)
{
try {
// simulate a delay (send request for data, receive and interpret response)
sleep(1000);
// How do I send data here to the UI thread?
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
如果UI切换到不同的Activity,这个线程会继续运行吗?此外,该线程如何知道将消息发送到哪个活动?显然,我希望它始终将数据发送到当前活动的Activity。这会自动发生吗?
最后,当UI切换到不同的活动时,需要通知bgworker,以便它可以开始请求与新Activity布局相关的数据。告知工人改变的最佳方法是什么?难道我不能在BgWorkerThread类中创建一个可在活动加载时调用的公共方法吗?
答案 0 :(得分:3)
我在以下SO Question中说明了相同的代码和更详细的步骤。总而言之,为了通知您的UI并为其提供不同的上下文,我建议如下:
onProgressUpdate
方法,可以更容易编码,以便从后台线程通知UI线程这是BackgroundThread的存根/伪代码
public class ResponseHandler extends AsyncTask<Void, String, Integer> {
boolean isConnectionClosed = false;
Map<Integer, Handler> requestIdToMapHandler;
public ResponseHandler() {
this.requestIdToMapHandler = new HashMap<Integer, Handler>();
}
@Override
protected Integer doInBackground(Void... params) {
int errorCode = 0;
try {
// while not connection is not close
while(!isConnectionClosed){
// blocking call from the device/server
String responseData = getResponse();
// once you get the data, you publish the progress
// this would be executed in the UI Thread
publishProgress(responseData);
}
} catch(Exception e) {
// error handling code that assigns appropriate error code
}
return errorCode;
}
@Override
protected void onPostExecute(Integer errorCode) {
// handle error on UI Thread
}
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
String responseData = values[0];
// the response contains the requestId that we need to extract
int requestId = extractId(responseData);
// next use the requestId to get the appropriate handler
Handler uiHandler = getUIHandler(requestId);
// send the message with data, note that this is just the illustration
// your data not necessary be jut String
Message message = uiHandler.obtainMessage();
message.obj = responseData;
uiHandler.sendMessage(message);
}
/***
* Stub code for illustration only
* Get the handler from the Map of requestId map to a Handler that you register from the UI
* @param requestId Request id that is mapped to a particular handler
* @return
*/
private Handler getUIHandler(int requestId) {
return null;
}
/***
* Stub code for illustration only, parse the response and get the request Id
* @param responseId
* @return
*/
private int extractId(String responseId) {
return 0;
}
/***
* Stub code for illustration only
* Call the server to get the TCP data. This is a blocking socket call that wait
* for the server response
* @return
*/
private String getResponse() {
return null;
}
}
答案 1 :(得分:1)
我认为你正在寻找一种UI回调机制。我在这里回答了类似的问题:Best way to perform an action periodically [while an app is running] - Handler?。如您所见,我通过创建Handler
实例然后调用sendEmptyMessage()
从后台线程向UI发送消息。您可以发送其他类型的消息,但这是一个简单的例子。
希望有所帮助。
答案 2 :(得分:0)
您可以使用
runOnUIThread(new Runnable {
public void run() {
//Update your UI here like update text view or imageview etc
}
});