刚刚开始接触android线程编程的时候,习惯好像java一样,试图用下面的代码解决问题
new Thread( new Runnable() { public void run() { myView.invalidate(); } }).start();
?
然而发现这样是不行的,因为它违背了单线程模型:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。查阅了文档和apidemo后,发觉常用的方法是利用Handler来实现UI线程的更新的。
?
下面代码的功能很简单:画一个圆出来,每隔0.1秒,圆向10移动10个像素。但可以清楚展示利用Handler更新UI的流程。
?
?
首先创建简单的View,代码如下:
package com.ray.handler;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Point;import android.graphics.drawable.Drawable;import android.view.View;public class BounceView extends View { float x = 40; public BounceView(Context context) { super(context); } @Override protected void onDraw(Canvas canvas) { x+=10; Paint mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setColor(Color.GREEN); canvas.drawCircle(x, 40, 40, mPaint); }}
?
创建Activity,代码如下:
package com.ray.handler;import android.app.Activity;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.view.Window;public class TestHandler extends Activity { protected static final int GUIUPDATEIDENTIFIER = 0x101; Thread myRefreshThread = null; BounceView myBounceView = null; Handler myHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case TestHandler.GUIUPDATEIDENTIFIER: myBounceView.invalidate(); break; } super.handleMessage(msg); } }; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(Window.FEATURE_NO_TITLE); this.myBounceView = new BounceView(this); this.setContentView(this.myBounceView); new Thread(new myThread()).start(); } class myThread implements Runnable { public void run() { while (!Thread.currentThread().isInterrupted()) { Message message = new Message(); message.what = TestHandler.GUIUPDATEIDENTIFIER; TestHandler.this.myHandler.sendMessage(message); try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } } }
1 楼 neverland 2009-09-11
兄弟写的文章很清晰,~~感谢
2 楼 raymondlueng 2009-09-11
呵呵,其实我只是初学者,只能写简单的东西!
3 楼 chenweiguo66 2009-10-15
不用Handler行吗?在你的另一篇文章中http://www.iteye.com/topic/435147,
回帖的那个人贴的代码就没有用Handler。用Handler比不用Handler有什么特别的优势吗?
回帖的那个人贴的代码就没有用Handler。用Handler比不用Handler有什么特别的优势吗?
4 楼 raymondlueng 2009-10-15
chenweiguo66 写道
不用Handler行吗?在你的另一篇文章中http://www.iteye.com/topic/435147,
回帖的那个人贴的代码就没有用Handler。用Handler比不用Handler有什么特别的优势吗?
用handler可以更好地使用消息回帖的那个人贴的代码就没有用Handler。用Handler比不用Handler有什么特别的优势吗?
驱动的程序设计!类似mfc[color=red][/color]
5 楼 crazier9527 2009-12-30
TestHandler.this.myHandler
6 楼 happyljt 2010-01-25
学习ing...
7 楼 kevin2562 2010-03-09
class myThread implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
Message message = new Message();
message.what = TestHandler.GUIUPDATEIDENTIFIER;
TestHandler.this.myHandler.sendMessage(message);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
这段有点不理解,楼主能解释一下么?
尤其是:
while (!Thread.currentThread().isInterrupted()) {
message.what = TestHandler.GUIUPDATEIDENTIFIER;
TestHandler.this.myHandler.sendMessage(message);
Thread.currentThread().interrupt();
作用是什么?
我很喜欢楼主的学习风格,在此表示感谢,你的帖子对我很有帮助。
public void run() {
while (!Thread.currentThread().isInterrupted()) {
Message message = new Message();
message.what = TestHandler.GUIUPDATEIDENTIFIER;
TestHandler.this.myHandler.sendMessage(message);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
这段有点不理解,楼主能解释一下么?
尤其是:
while (!Thread.currentThread().isInterrupted()) {
message.what = TestHandler.GUIUPDATEIDENTIFIER;
TestHandler.this.myHandler.sendMessage(message);
Thread.currentThread().interrupt();
作用是什么?
我很喜欢楼主的学习风格,在此表示感谢,你的帖子对我很有帮助。
8 楼 leon_ch 2012-04-12
楼主既然用到BounceView来继承View,为什么不考虑用子空间的方式来实现呢?
另外,如果用handler来实现的话,那么利用activity内的内部类就可以循环实现,我自己做了一下,楼主看一下是不是可以?
第一种:
package edu.cslg.leon.ballinvalidate;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.View;
public class BallView extends View
{
private Paint paint;
private int BallX=10;
private int BallY=10;
private int WindowWidth=200;
private int WindowHeight=200;
static final int radius=20;
public BallView(Context context, AttributeSet attrs)
{
super(context, attrs);
paint=new Paint();
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
BallX++;
BallY++;
paint.setColor(Color.BLUE);
paint.setStyle(Style.FILL);
canvas.drawCircle(BallX, BallY, radius, paint);
if(BallX<WindowWidth&&BallY<WindowHeight)
{
invalidate();
}
}
}
配置文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<edu.cslg.leon.ballinvalidate.BallView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
第二种:
package edu.cslg.leon.ballinvalidate;
import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
public class BallInvalidate extends Activity
{
private int BallX;
private int BallY;
private Paint paint;
private Canvas canvas;
static final int radius=20;
class MyHandler extends Handler
{
public MyHandler(Looper looper)
{
super(looper);
}
@Override
public void handleMessage(Message msg)
{
super.handleMessage(msg);
paint.setColor(Color.BLUE);
paint.setStyle(Style.FILL);
canvas.drawCircle(msg.arg1,msg.arg2, radius, paint);
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
paint=new Paint();
canvas=new Canvas();
new MyThread().start();
}
class MyThread extends Thread
{
@Override
public void run()
{
super.run();
while (BallX<200&&BallY<200)
{
Looper looper=Looper.getMainLooper();
Handler handler=new MyHandler(looper);
Message msg=handler.obtainMessage(1, BallX,BallY);
handler.sendMessage(msg);
}
}
}
}
另外,如果用handler来实现的话,那么利用activity内的内部类就可以循环实现,我自己做了一下,楼主看一下是不是可以?
第一种:
package edu.cslg.leon.ballinvalidate;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.View;
public class BallView extends View
{
private Paint paint;
private int BallX=10;
private int BallY=10;
private int WindowWidth=200;
private int WindowHeight=200;
static final int radius=20;
public BallView(Context context, AttributeSet attrs)
{
super(context, attrs);
paint=new Paint();
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
BallX++;
BallY++;
paint.setColor(Color.BLUE);
paint.setStyle(Style.FILL);
canvas.drawCircle(BallX, BallY, radius, paint);
if(BallX<WindowWidth&&BallY<WindowHeight)
{
invalidate();
}
}
}
配置文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<edu.cslg.leon.ballinvalidate.BallView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
第二种:
package edu.cslg.leon.ballinvalidate;
import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
public class BallInvalidate extends Activity
{
private int BallX;
private int BallY;
private Paint paint;
private Canvas canvas;
static final int radius=20;
class MyHandler extends Handler
{
public MyHandler(Looper looper)
{
super(looper);
}
@Override
public void handleMessage(Message msg)
{
super.handleMessage(msg);
paint.setColor(Color.BLUE);
paint.setStyle(Style.FILL);
canvas.drawCircle(msg.arg1,msg.arg2, radius, paint);
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
paint=new Paint();
canvas=new Canvas();
new MyThread().start();
}
class MyThread extends Thread
{
@Override
public void run()
{
super.run();
while (BallX<200&&BallY<200)
{
Looper looper=Looper.getMainLooper();
Handler handler=new MyHandler(looper);
Message msg=handler.obtainMessage(1, BallX,BallY);
handler.sendMessage(msg);
}
}
}
}
9 楼 yacobe 2012-04-24
条理很清楚,很受用。感谢
10 楼 yacobe 2012-04-24
条理很清晰,很受用。感谢
11 楼 KwokWing 2012-07-19
最近学习Android游戏开发, 感谢楼主