现在我们来做一个简单的例子。如下图:
layout文件如下:
<?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" >
<Button android:id="@+id/btnStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Thread" />
<Button android:id="@+id/btnStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop Thread" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="30dip"
android:textColor="#ffff0000"
android:text="0"
android:layout_marginLeft="30dip"
android:id="@+id/txtShow" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button android:id="@+id/btnStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Thread" />
<Button android:id="@+id/btnStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop Thread" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="30dip"
android:textColor="#ffff0000"
android:text="0"
android:layout_marginLeft="30dip"
android:id="@+id/txtShow" />
</LinearLayout>
我们来看看源代码:
public
class
TestThreadActivity
extends
Activity
{
//声明变量
private Handler mHandler = null;
private MyThread mThread = null;
private TextView mTextView;
private Button mButtonStart;
private Button mButtonStop;
//用来计数的变量
private int mSecond = 0;
//用来设置线程是否停止
private boolean mStop = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//赋值
mThread = new MyThread();
mHandler = new MyHandler();
mTextView = (TextView)findViewById(R.id.txtShow);
mButtonStart = (Button)findViewById(R.id.btnStart);
mButtonStop = (Button)findViewById(R.id.btnStop);
mButtonStart.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//启动线程
startThread();
}
});
mButtonStop.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//停止线程
stopThread();
}
});
}
//启动线程
private void startThread()
{
mStop = false;
mThread.start();
}
//停止线程
private void stopThread()
{
mStop = true;
}
//自定义Handler,用来显示屏幕上的数字
private class MyHandler extends Handler
{
@Override
public void handleMessage(Message msg)
{
switch(msg.what)
{
case 1:
{
mSecond ++; //second increase
//改变UI
mTextView.setText(Integer.toString(mSecond));
break;
}
}
}
}
//自定义线程,通过Message传递消息给Handler,让Handler改变UI显示
private class MyThread extends Thread
{
@Override
public void run()
{
while(!mStop)
{
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
//do something
Message msg = new Message();
msg.what = 1;
//send message
mHandler.sendMessage(msg);
}
}
}
}
//声明变量
private Handler mHandler = null;
private MyThread mThread = null;
private TextView mTextView;
private Button mButtonStart;
private Button mButtonStop;
//用来计数的变量
private int mSecond = 0;
//用来设置线程是否停止
private boolean mStop = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//赋值
mThread = new MyThread();
mHandler = new MyHandler();
mTextView = (TextView)findViewById(R.id.txtShow);
mButtonStart = (Button)findViewById(R.id.btnStart);
mButtonStop = (Button)findViewById(R.id.btnStop);
mButtonStart.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//启动线程
startThread();
}
});
mButtonStop.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//停止线程
stopThread();
}
});
}
//启动线程
private void startThread()
{
mStop = false;
mThread.start();
}
//停止线程
private void stopThread()
{
mStop = true;
}
//自定义Handler,用来显示屏幕上的数字
private class MyHandler extends Handler
{
@Override
public void handleMessage(Message msg)
{
switch(msg.what)
{
case 1:
{
mSecond ++; //second increase
//改变UI
mTextView.setText(Integer.toString(mSecond));
break;
}
}
}
}
//自定义线程,通过Message传递消息给Handler,让Handler改变UI显示
private class MyThread extends Thread
{
@Override
public void run()
{
while(!mStop)
{
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
//do something
Message msg = new Message();
msg.what = 1;
//send message
mHandler.sendMessage(msg);
}
}
}
}
这样这个例子就完成了。
但这例子有bug。如果点了停止按钮后,我们再点Start Thread按钮,就有问题了。Exception如下:
private
void
startThread()
{
//将标志位设为false,表示线程开始运行
mStop = false;
//如果线程还没有开始过,就调用start。如果已经开始了,用start就会出错了
if(mThread.getState() == Thread.State.NEW)
mThread.start();
}
{
//将标志位设为false,表示线程开始运行
mStop = false;
//如果线程还没有开始过,就调用start。如果已经开始了,用start就会出错了
if(mThread.getState() == Thread.State.NEW)
mThread.start();
}
在自定义的MyThread增加对停止线程的处理,如下:
private
class
MyThread
extends
Thread
{
@Override
public void run()
{
while(!mStop)
{
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
Message msg = new Message();
msg.what = 1;
//send message
mHandler.sendMessage(msg);
}
//在这里增加对停止线程的处理。停止线程用interrupt
if(mStop)
this.interrupt();
}
}
{
@Override
public void run()
{
while(!mStop)
{
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
Message msg = new Message();
msg.what = 1;
//send message
mHandler.sendMessage(msg);
}
//在这里增加对停止线程的处理。停止线程用interrupt
if(mStop)
this.interrupt();
}
}
这时候,点击start thread按钮,开始运行线程。屏幕上开始计数。点击stop thread,停止线程。屏幕上的数字维持不变。这时候再次点击start thread,不会出现异常。点击stop thread,也不会出现异常。这时候又有新问题了。屏幕上的数字就不会再变化了。
我们可不可以在点击start thread按钮的时候,让它继续计数呢?如何实现呢?
private
void
startThread()
{
//设置标志位为false,表示运行线程
mStop = false;
//如果线程从来没有开始过,运行start
if(mThread.getState() == Thread.State.NEW)
{
mThread.start();
}
else if(mThread.getState() == Thread.State.TERMINATED)
{
//如果线程已经被interrupt了,那么它的状态就是terminated。即这个线程完整的结束了。
//这时候就重新new一个线程,再start
try
{
mThread = new MyThread();
mThread.start();
}
catch(Exception e)
{
}
}
}
{
//设置标志位为false,表示运行线程
mStop = false;
//如果线程从来没有开始过,运行start
if(mThread.getState() == Thread.State.NEW)
{
mThread.start();
}
else if(mThread.getState() == Thread.State.TERMINATED)
{
//如果线程已经被interrupt了,那么它的状态就是terminated。即这个线程完整的结束了。
//这时候就重新new一个线程,再start
try
{
mThread = new MyThread();
mThread.start();
}
catch(Exception e)
{
}
}
}
这时候再次点击start thread,屏幕上从当前数字开始继续计数。直到按下stop thread为止。
既然如此,不如精简下代码,每次按下start thread,我都new thread,看看效果:
private
void
startThread()
{
mStop = false;
mThread = new MyThread();
mThread.start();
}
{
mStop = false;
mThread = new MyThread();
mThread.start();
}
显示效果和上面一样。而且从logcat中也没有发现任何内存泄露等不好的东西。