Android开发中的多线程(4)

现在分析一下上面的案例,在上面的程序中有两个线程:一个主线程和一个子线程,它们的职责如图所示。

  由于labelTimer是一个UI控件,它是在主线程中创建的,但是它却在子线程中被更新了,更新操作在clockThread线程的run()方法中实现,代码如下:

Android开发中的多线程

mThread = new Thread(new Runnable() {

@Override
            public void run() {
                try {
                    while (isRunning) {
                        Thread.currentThread().sleep(1000);
                        timer++;
                        /*Message message = new Message();
                        message.obj = timer;
                        message.what = 0;
                        handler.sendMessage(message);*/
                        mTextView.setText("逝去了:"+timer);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

}
        });

这样的处理违背了Android多线程编程规则,系统会抛出异常“Only the original thread that created a view hierarchy can touch its views”。

  要解决这个问题,就要明确主线程和子线程的职责。主线程的职责是创建、显示和更新UI控件、处理UI事件、启动子线程、停止子线程;子线程的职责是计算逝去的时间和向主线程发出更新UI消息,而不是直接更新UI。

主线程的职责是显示UI控件、处理UI事件、启动子线程、停止子线程和更新UI,子线程的职责是计算逝去的时间和向主线程发出更新UI消息。但是新的问题又出现了:子线程和主线程如何发送消息、如何通信呢?

在Android中,线程有两个对象—消息(Message)和消息队列(MessageQueue)可以实现线程间的通信。下面再看看修改之后的代码清单.

package com.example.testthread4;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.*;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;

public class MainActivity extends Activity {

private Button mButton;
    private TextView mTextView;
    private boolean isRunning = true;
    private Thread mThread;
    private int timer = 0;
    private Handler handler;

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

mButton = (Button) findViewById(R.id.button1);
        mTextView = (TextView) findViewById(R.id.textView1);

mButton.setOnClickListener(new OnClickListener() {

@Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                isRunning = false;
            }
        });
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case 0:
                    mTextView.setText("逝去了:" + msg.obj);
                }
            }
        };
        mThread = new Thread(new Runnable() {

@Override
            public void run() {
                try {
                    while (isRunning) {
                        Thread.currentThread().sleep(1000);
                        timer++;
                        Message message = new Message();
                        message.obj = timer;
                        message.what = 0;
                        handler.sendMessage(message);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

}
        });
        mThread.start();
    }
}

有的时候为了将Android代码变得更加紧凑,把线程的创建和启动编写在一条语句中,如下面

/*mThread = */new Thread(new Runnable() {

@Override
            public void run() {
                try {
                    while (isRunning) {
                        Thread.currentThread().sleep(1000);
                        timer++;
                        Message message = new Message();
                        message.obj = timer;
                        message.what = 0;
                        handler.sendMessage(message);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

}
        }).start();

运行模拟器结果如图8-1所示,加载屏幕后马上开始计时,也可以单击“停止计时”按钮来停止计时。

Android开发中的多线程

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/f1baa8899bd94a6d182a2f2be75f728e.html