我有以下代码。
//This is global for the activity.
Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
//update the UI
}
};
在我的onResume()中,我启动了一个运行runnable的新线程。
protected void onResume()
{
super.onResume();
Thread t = new Thread(runnable);
t.start();
}
我的runnable如下:
Runnable runnable = new Runnable()
{
public void run()
{
// some networking stuff
// some db stuff
// whatever
handler.sendEmptyMessage(0);
handler.postDelayed(new Runnable()
{
public void run()
{
new Thread(runnable).start();
}
}, 30000);
}
}
我在onPause()中有这个:
protected void onPause()
{
super.onPause();
handler.removeCallbacks(runnable);
}
最后我调用了handler.sendEmptyMessage(0);
以便调用handleMessage(Message msg)
并进行UI更改,然后重复执行任务但是启动一个新的runnable,它会启动一个运行该命令的新线程同样可以运行。
澄清问题:
我在onResume()中启动一个新线程,这意味着runnable没有在UI线程上运行,但是,处理程序是在UI线程上创建的,并且自然地附加到UI线程。如何完美地改变UI?
假设是handler.removeCallbacks(runnable),但是,每当我缩小应用程序时,runnable仍然会每30秒继续运行一次。 (这可能是因为它位于新线程上,与创建的Handler无关)。我怎么能让它停下来?
答案 0 :(得分:1)
public class MainActivity extends Activity {
public static final int UPDATE = 1;
public static final int WORK = 2;
private Handler uiHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE:
// Perform UI updates here
....
// UI Updates done, schedule WORK in 30 seconds:
this.sendMessageDelayed(this.obtainMessage(WORK), 30000);
break;
case WORK:
new Thread(doWork).start();
break;
default:
super.handleMessage(msg);
}
}
};
private WeakReference<Handler> handlerRef = new WeakReference<Handler>( uiHandler );
private Runnable doWork = new Runnable() {
@Override
public void run() {
// This will run on a different thread.
// If UI is still around, tell it to update
Handler ui = handlerRef.get();
if( ui != null )
ui.sendEmptyMessage(MainActivity.UPDATE);
}
};
@Override
protected void onPause() {
uiHandler.removeMessages(WORK);
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
// Resume UI updates in 500ms, allowing UI to settle
uiHandler.sendMessageDelayed(uiHandler.obtainMessage(WORK), 500);
}
....
}
此模式在UI线程上使用单个Handler。后台工作在Runnable中完成,ui Handler将发布到新线程,因此避免NetworkOnMainThreadException
- 更重要的是 - 无响应的UI。此外,在后台进程完成后30秒安排新的更新,以避免对长时间运行的更新征税。后台线程使用WeakReference
到ui处理程序,因此如果在线程工作时Activity
被终止,它将不会向其发送UI更新。