08 Android 使用Thread操作UI
Android中线程操作UI比较有趣的地方是Android是线程安全的,所以在一个自己创建的线程中,无法去刷新主线程中UI的状态。必须通过消息通知的方式才能做到。
这里主要使用了两种方式:(其实也尝试着使用AsyncTask,但发现在测试时onProgressUpdate总是没有被调用,所以先不把他总结在这里。)
方式 1:( Runnable + post 或 postDelay )
核心的想法:在线程的run函数中,直接调用UI的post方法,使UI进行更新。API的简单介绍:
public boolean post (Runnable action)Causes the Runnable to be added to the message queue. The runnable will be run on the user interface thread.
一个Runnable 的action对象将会被封装,保存到message queue中,action中的操作将会在UI的线程中被执行。它符合Android的线程安全的操作方式。
public boolean postDelayed (Runnable action, long delayMillis)
Causes the Runnable to be added to the message queue, to be run after thespecified amount of time elapses. The runnable will be run on the user interface thread
一个Runnable 的action对象将会被封装,保存到message queue中,action中的操作会被推迟delayMillis毫秒执行。
View.invalidate
Invalidate the whole view. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future.This must be called from a UI thread. To call from a non-UI thread, call postInvalidate().
这个函数会使整个view失效,从而使整个view调用onDraw进行重绘。这是函数必须在UI thread使用。如果是非UI线程必须使用postInvalidate()。当然还有使View局部失效的函数,可以参考Android的文档。
实例代码:
@Overridepublic void run(){int i = 0;int nTotalSleeping = 0;try{while (bAlive){try {/** * 刷新一次view的显示后,都等待30ms。当图像每秒刷新30次的时候, * 大部分人的眼睛就已经认为图像是连续的了,1000ms/30 = 33.33ms,在这里 省略成30。 */Thread.sleep(m_nSleep);m_GameView.post(new Runnable(){@Overridepublic void run(){m_GameView.setCX(m_x);m_GameView.setCY(m_y);m_x = m_x + 5; m_y = m_y + 5;m_GameView.invalidate();}});}catch (InterruptedException e) {e.printStackTrace();}}}catch(Exception ex){ex.printStackTrace();}}
方式 2:(Thread+Handler)
核心的想法:在Thread中向Handler发送消息,Handler的处理则在View中,Handler会判断消息类型,并根据消息类型更新View。
在途中可以看到,Thread中调用的是Handler.SendMessage,UI Thread中来对相应的消息类型进行处理。
API的简单介绍:
Handler:
A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
Handler允许你在线程间通过消息队列传递消息,并且进行处理。每个Handler的实例都与一个线程的消息队列相关连。当在你创建一个Handler时,它便会与线程/消息队列相绑定。它会在消息队列中传递消息或是runnables 。
Handler的用途主要有两个
1) 传递消息和需要执行的runnables。
2) 在队列中保存会在别的地方运行的action。
实例代码:
Thread Send Message to View
public void run() { while (!Thread.currentThread().isInterrupted()) { Message message = new Message(); message.what = DRAWING; Log.d("MyHandlerThread", "sending message ..."); m_view.getHandler().sendMessage(message); try { m_view.setCX(m_x); m_view.setCY(m_y); m_x = m_x + 5; m_y = m_y + 5; Thread.sleep(300); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }
View handler the message
m_Handler = new Handler(){ public void handleMessage(Message msg) { Log.d("MyHandlerThread", "handling message ..."); switch (msg.what) { case DRAWING: invalidate(); break; default : break; } super.handleMessage(msg); }};
代码实例下载
参考
http://developer.android.com/reference/android/os/Handler.html
http://www.cnblogs.com/playing/archive/2011/03/24/1993583.html
http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html更多相关文章
- Android消息循环分析
- Android异步消息处理之Thread+Handler
- Android线程与异步消息处理机制
- android的消息处理机制(Looper,Handler,Message)
- android ui线程和数据的分离
- Android的消息机制分析