我有一个线程,我需要定期执行一些检查,从Web获取文件,并将消息发送到主UI线程。我甚至需要在工作线程的每个循环上使用UI线程参数(如地图可见区域)。所以我想我需要实现UIthread和workerThread之间的双向通信。 另一个问题是我需要保存添加到地图中的每个标记的标识符。我想将map.addMarker的结果保存在我的工作线程中存储的自定义数组中。这意味着从uithread,我更新地图,我应该告诉workerThread更新标记数组..
这是我的实际工作线程的示例:
class MyThread extends Thread {
private Handler handler;
private MainActivity main;
public MyThread (MainActivity mainClass, Handler handlerClass) {
this.main=mainClass;
this.handler = handlerClass;
}
@Override
public void run(){
while(true){
sleep(2000);
//do my stuffs
//....
//prepare a message for the UI thread
Message msg = handler.obtainMessage();
msg.obj= //here i put my object or i can even use a bundle
handler.sendMessage(msg); //with this i send a message to my UI thread
}
}
}
我的实际问题是,当UI线程结束处理从工作线程收到的消息时,我应该对工作线程执行操作。
我想到了2个解决方案:
1)等待工作线程,直到UI线程处理了消息
2)在UI线程上处理消息,然后向工作线程发送消息。
我不知道如何解决方案1,所以我尝试了解决方案2。我尝试将looper添加到我的工作线程(RUN sub),这样:
class MyThread extends Thread {
private Handler handler;
private MainActivity main;
public MyThread (MainActivity mainClass, Handler handlerClass) {
this.main=mainClass;
this.handler = handlerClass;
}
@Override
public void run(){
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// Act on the message received from my UI thread doing my stuff
}
};
Looper.loop();
while(true){
sleep(2000);
//do my stuffs
//....
//prepare a message for the UI thread
Message msg = handler.obtainMessage();
msg.obj= //here i put my object or i can even use a bundle
handler.sendMessage(msg); //with this i send a message to my UI thread
}
}
}
问题是在Looper.loop()之后没有执行任何代码行。我读到这是正常的。我阅读了很多文章,但我不明白我应该如何允许执行while循环,同时处理来自我的UI线程的消息。 我希望问题很清楚。建议我最好的解决方案。
答案 0 :(得分:2)
不要这样做:
while(true){
sleep(2000);
这么多级别都非常糟糕。如果您需要一些后台处理,请使用AsyncTasks
,如果您需要重复事件,请使用:
private Handler mHandler = new Handler();
private Runnable mSomeTask = new Runnable() {
public void run() {
doSomething();
}
};
然后在代码中的某个地方:
mHandler.postDelayed(mSomeTask, 100);
这将使您的计划更快地工作,减少资源堵塞,并且基本上是一个更好的Android公民。
答案 1 :(得分:1)
我意识到这是一个非常古老的问题,但对于定期任务调度,请使用以下代码:
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
ScheduledFuture<?> periodicTask = scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
// do some magic stuff here
// note however, that you're running in background!
Log.d("PeriodicTask", "Doing something....");
}
}, 0 /* initial delay */, 10 /* start every 10 seconds */, TimeUnit.SECONDS);
当您需要停止定期任务时,只需发出
periodicTask.cancel(true);