Android多线程理解

Android 理解多线程

安卓应用程序通常是应用在一个单独的线程里的,即为主线程,用于显示用户界面以及响应用户的操作。
如果一些耗时任务也同时在主线程里去完成,则会影响用户体验,会阻塞UI主线程。我们会创建一个单独的线程或者子线程,去处理这些耗时操作(如网络请求、数据库操作等)。
那么这些子线程就是AsyncTask、Thread、HandlerThread,它们叫做安卓的工作者线程。
- AsyncTask
- Handler


一、AsyncTask异步任务

AsyncTask是Android的一个轻量级异步类,可以自定义类并继承AsyncTask,实现异步任务处理操作。并且AsyncTask提供了接口返回异步操作的进度,最后会返回结果到UI主线程中。

优点:简单快捷,过程可以控制
缺点:在处理多个异步操作时比较复杂

AsyncTask类

参数 说明
Params 启动任务时输入的执行参数,一般为一个网络地址
Progress 异步任务执行的进度
Result 异步任务执行后的结果的类型

代码实例

这是一个利用AsyncTask加载网络图片的代码:

public class MainActivity extends ActionBarActivity
{
private Button button1;
private ImageView imageview1;
private ProgressDialog dialog;

private String image_uri =”https://imgsa.baidu.com/baike/c0%3Dbaike272%2C5%2C5%2C272%2C90/sign=c4f298bb97ef76c6c4dff379fc7f969f/9358d109b3de9c82f077b3156b81800a19d8431d.jpg”;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dialog = new ProgressDialog(this);
dialog.setTitle(“图片下载”);
dialog.setMessage(“正在下载,请稍后…”);
button1 = (Button) findViewById(R.id.button1);
imageview1 = (ImageView) findViewById(R.id.imageView1);
button1.setOnClickListener(new OnClickListener()
{

        @Override
        public void onClick(View v)
        {
            // TODO Auto-generated method stub
            new DownloadTask().execute(image_uri);
        }
    });
}

//自定义下载类继承AsyncTask
public class DownloadTask extends AsyncTask<String, Void, Bitmap>
{
    // 这个方法会在后台任务开始执行之间调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框等。
    @Override
    protected void onPreExecute()
    {
        // TODO Auto-generated method stub
        dialog.show();
        super.onPreExecute();
    }

    // 这个方法中的所有代码都会在子线程中运行,主要完成耗时任务
    // 注意,在这个方法中是不可以进行UI操作的
    //在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。
    @Override
    protected Bitmap doInBackground(String... params)
    {
        // TODO Auto-generated method stub
        // 使用网络链接类HttpClient完成网络数据的获取
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(params[0]);
        Bitmap bitmap = null;
        try
        {
            HttpResponse httpResponse = httpClient.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode() == 200)
            {
                HttpEntity httpEntity = httpResponse.getEntity();
                byte[] data = EntityUtils.toByteArray(httpEntity);
                bitmap = BitmapFactory
                        .decodeByteArray(data, 0, data.length);
            }
        } catch (Exception e)
        {
            // TODO: handle exception
            e.printStackTrace();
        }

        return bitmap;
    }
    //在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。
    @Override
    protected void onProgressUpdate(Void... values)
    {
        // TODO Auto-generated method stub
        super.onProgressUpdate(values);
    }

    // 可以利用返回的数据来进行一些UI操作,比如说提醒任务执行的结果,以及关闭掉进度条对话框等。
    protected void onPostExecute(Bitmap result)
    {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        imageview1.setImageBitmap(result);
        dialog.dismiss();
    }
}

}

参考:android AsyncTask介绍
详解Android中AsyncTask的使用

二、Handler

1、Handler概念:

I 、Handler 是 Android 给我们提供来更新 UI 的一套机制,也是一套消息处理的机制,我们可以发送消息,也可以通过它来处理消息。
II、Android 在设计的时候,就封装了一套消息创建、传递、处理机制,如果不遵循这样的机制就没有办法更新 UI 信息,就会抛出异常信息。

2、与Handler相关的几个概念:

I、Message 消息,理解为线程间通讯的数据单元。例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程。
II、Message Queue 消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
III、Handler Handler是Message的主要处理者,负责将Message添加到消息队列以及对消息队列中的Message进行处理。
Looper 循环器,扮演Message Queue和Handler之间桥梁的角色,循环取出Message Queue里面的Message,并交付给相应的Handler进行处理。
IV、线程 UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。

3、Handler的一些分发消息的方法

    post(Runnable)
    postAtTime(Runnable,long)
    postDelayed(Runnable long)
    sendEmptyMessage(int)
    sendMessage(Message)
    sendMessageAtTime(Message,long)
    sendMessageDelayed(Message,long)

4、关于Message

创建Handler实例,要重载handleMessage方法,来处理消息
获取Message对象的最好方法是调用Message.obtain()

Message可传递的参数:

①. arg1 arg2 整数类型,是setData的低成本替代品,传递简单类型。
Object 类型 obj
②. what 用户自定义的消息代码,这样接受者可以了解这个消息的信息。每个handler各自包含自己的消息代码,所以不用担心自定义的消息跟其他handlers有冲突
③.其他的可以通过Bundle进行传递
Message可以通过new Message构造来创建一个新的Message,但是这种方式很不好,不建议使用。最好使用Message.obtain()来获取Message实例,它创建了消息池来处理的。

5、代码实例
利用Handler创建一个dialog进度条并显示进度

public class HandlerActivity extends Activity
{
private Button button1;
private static ProgressDialog dialog;
//创建Handler静态对象
private static Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
int index=msg.arg1;
dialog.setProgress(index);
if (msg.what==1)
{
dialog.dismiss();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
button1=(Button)findViewById(R.id.button1);
dialog=new ProgressDialog(this);
dialog.setTitle(“正在下载…”);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
button1.setOnClickListener(new OnClickListener()
{

        @Override
        public void onClick(View v)
        {
            // TODO Auto-generated method stub
            new Thread(new MyThread()).start();
            dialog.show();
        }
    });
}
//创建一个子线程继承Runnable
public class MyThread implements Runnable{
    int count=1;
    int index=0;
    @Override
    public void run()
    {
        // TODO Auto-generated method stub
        while(count<=100){
            try
            {
                Thread.sleep(200);
            } catch (Exception e)
            {
                // TODO: handle exception
                e.printStackTrace();
            }
            Message message=Message.obtain();
            message.arg1=count;
            handler.sendMessage(message);
            count++;
        }
        Message end=Message.obtain();
        end.what=1;
        handler.sendMessage(end);
    }
}

参考:Android中的Handler的机制与用法详解
Android中的Handler总结

猜你喜欢

转载自blog.csdn.net/baidu_30891377/article/details/68062079