您的位置:首页 > 产品设计 > UI/UE

[Android开发常见问题-7] 多线程开发的几种方式和子线程操作UI线程控件的问题

2013-06-26 22:21 821 查看
移动开发里面经常会有很多耗时的操作需要放在后台运行,比如联网、大量数据处理等,否则的话就会导致主线程,也就是UI线程卡住,给用户一种程序死掉的感觉,体验极差,所以在这里我就大概的说一下如何进行多线程的开发,以及在多线程开发的过程中有哪些需要注意的问题。

方式1:继承Thread类,创建一个新的线程类。

private class thread extends Thread{
private Context act;
public thread(Context con){
act = con;
}
@Override
public void run() {
super.run();
//想要放到后台线程做的事情都写在这里。
}

}


上面代码就是最基本的代码框架,要使用的时候可以通过下面代码来启动新线程。

//方式1
new thread(this).start();
//方式2
thread tt = new thread(this);
tt.start();


其中run()函数里面就是在新线程里面需要做的事情,但是这里有一点需要注意,那就是子线程不能直接操作主线程(UI线程)里面的UI控件。

比如说主线程里面有一个TextView tv,你想在子线程里面直接tv.setText('aa");这是不可以的,会报错。

又如,你想在子线程里面来一个Toast.show();这也是不可以的。

那么我们怎么在子线程里面更新主线程的UI呢?答案就是Handler。

那么Handler怎么用呢?请往下看

package com.alex.chat.activity;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

import com.alex.chat.R;
import com.alex.chat.util.NetWork;

public class OnCreate extends Activity {
private boolean netState = false;
private TextView tv;
private MyHandler mh;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.oncreate);
tv = (TextView)findViewById(R.id.tv);
mh = new MyHandler();
new thread(this).start();

}

//继承Handler自定义要处理的事件
private class MyHandler extends Handler{

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what){
case 0:
tv.setText("NetWork is not OK!");
break;
case 1:
tv.setText("NetWork is OK!");
break;
}
}

}

//自己定义的新线程
private class thread extends Thread{
private Context act;
public thread(Context con){
act = con;
}
@Override
public void run() {
super.run();
//IsNetworkAvailable()是我自定义的获得当前网络状况的函数,不必细究
//如果想了解具体实现,请参看上一篇文章
netState = NetWork.IsNetworkAvailable(act);
//通过handler发送消息
mh.sendEmptyMessage(netState?1:0);
}

}
}


这样就可以完美解决子线程更新UI线程的问题啦。

方式2:实现runnable接口,其实通过方式1我们也可以看出来,创建一个新的线程类实际上就是利用了父类的runnable接口,所以java提供runnable这个接口来供开发者使用。代码如下:

//实现runable接口
private class thread_run implements Runnable{
private Context act;
public thread_run(Context con){
act = con;
}
@Override
public void run() {
//要在新线程里面进行的任务写在这里
}

}


这种方法实现的新线程也存在方式1一样的问题,就是要操作UI线程必须通过Handler。

这个类的使用方法如下:

//方式1
new thread_run(this).run();
//方式2
thread_run tr = new thread_run(this);
tr.run();

方式3:AsyncTask

为了方便开发者进行简单安全的多线程开发,android推出了一个安全的多线程类,叫做AsyncTask,这个类的用法如下:

private class Thread_Task extends AsyncTask<URL, Integer, Long> {
protected void onPreExecute(){
//在后台线程开始运行之前要做的事情放到这里
}
protected Long doInBackground(URL... urls) {
//在新线程里面需要做的事情放到这里
return totalSize;
}

protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}

protected void onPostExecute(Long result) {
//后台线程执行完需要做的事情放到这里,注意,这里不属于后台线程,可以操作UI。

}
}


调用方法如下:
new Thread_Task().execute(url1, 1, 2);
注意看代码中注释,这样的类就给我们进行多线程开发带来了很大的方便。

关于多线程开发的方式,暂时先介绍以上三种,如果以后遇到新的方式会及时更新,同时也欢迎各位朋友多提建议。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息