love超1314的专栏

共同学习共同进步

Android多线程

Android多线程

一个Android的应用程序运行在一个独立的进程中,运行在一个独立的虚拟机(dvk)上。(进程名为包名)
Android应用程序开启后,默认开启一个主线程(UI线程)
Activity,Service,BroadcastReceive组件运行在主线程中
Android 应用程序退出后,保留空UI线程,可以加快应用程序启动速度。
用户不能再UI主线程中做耗时的操作,一旦操作超过5s,应用程序抛出一个ANR(application not respond)

如何避免ANR错误?
将耗时的操作放入到子线程中。(耗时的操作包括:长时间的休眠,计数,联网,复杂的运算)
只有主线程才能操作Widget控件。
如果在子线程中出现操作Widget控件,系统抛出CalledFromWrongThreadException异常。
系统为什么要这么做?
避免出现同步问题。

Handler机制

作用
主要为了解决非UI线程中不能更新Widget控件的问题
Handler机制剖析
子线程发送消息给底层的消息队列。
handler.sendMessage(msg)
主线程查询消息队列,处理消息对象。
handlerMessage(msg)
MessageQueue 消息队列
负责存储消息对象
Looper
给UI线程安排代码,一个UI线程只能有一个Looper对象,否则多个Looper对象都在UI线程上安排代码,解决冲突就是个大问题。
Looper对象会线性安排在UI线程上执行的代码,它通过一个队列管理各个Handler对象提交的代码。
Message消息对象
//从消息池中获取消息对象
Message msg = handler.obtainMessage();
//在消息对象上绑定int类型数据
msg.arg1 = count;
//在消息对象上绑定其它类型数据
msg.setData(Bundle); //Bundler为数据集(类似于HashMap容器)

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
/**
 * @author Administrator
 * 事件驱动的应用程序
 */
public class MainActivity extends Activity implements OnClickListener {
    Button btnStart;
    TextView tv;
    int count = 0;
    boolean isRun;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnStart = (Button) findViewById(R.id.button1);
        btnStart.setOnClickListener(this);
        findViewById(R.id.button2).setOnClickListener(this);
        tv = (TextView) findViewById(R.id.textView1);
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        if(v.getId() == R.id.button1){  
            btnStart.setEnabled(false);
            count = 0;
            isRun = true;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    // 修改Widget控件的值
                    // tv.setText(String.valueOf(count));
                    while (isRun) {
                        count++;
                        // 创建消息对象
                        Message msg = new Message();
                        msg.arg1 = count;
                        //设置消息类型
                        msg.what = 2;
                        // 发送消息 (发给底层的消息队列)
                        handler.sendMessage(msg);

                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }

                    handler.sendEmptyMessage(1);
                }
            }).start();
        }else if(v.getId() == R.id.button2){    
            isRun = false;  
        }
    }
    Handler handler = new Handler(){

        //如果消息队列中有消息,系统自动调用该方法处理消息
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            super.handleMessage(msg);
            if(msg.what == 2){
                int count = msg.arg1;
                tv.setText(String.valueOf(count));
            }else if(msg.what == 1){
                //修改按钮属性
                btnStart.setEnabled(true);
            }
        }
    };
}

向消息队列发送消息,1000毫秒后执行Runnable对象中的代码。

myHandler.postDelayed(new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        Log.e("Test", "thread name = "+Thread.currentThread().getName());
    }
}, 1000);

异步任务(Async Task)

概念
封装多线程和Handler机制。给用户提供重写接口的方式,不需要用户手动创建子线程和Handler对象。
异步任务的优点
Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI主线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但是也有缺点,代码臃肿,在多个任务同时执行时,不易对线程进行精确的控制。为了简化操作,Android1.5提供了一个工具类AsyncTask,它是创建异步任务变的更加简单,不再需要编写任务线程和Handler实例就可完成任务。
异步任务的局限性
多个异步任务不能同时执行,在某个时间内,只能执行一个异步任务。
执行异步任务的步骤:

  • 1 execute(Params … params),执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。
  • 2 onPreExecute(),在execute(Params… params
    )被调用后立即执行,一般用来在执行后台任务前对UI做一些标记。
  • 3 doInBackground(Params…
    params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接受输入参数和返回计算结果在执行过程中可以调用publishProgress(Progress…values)来更新进度信息。作用在非UI线程上。
  • 4 onProgressUpdate(Progress… values),在调用publishProgress(Progress…
    values)时,此方法被执行,直接将进度信息更新到UI组件上。
  • 5 onPostExecute(Result
    result)当后台操作结束时,此方法将被调用,计算结果讲座为参数传递到方法中,直接将结果显示到UI组件上。
import android.os.AsyncTask;
import android.util.Log;
import android.widget.TextView;

//Params 执行异步任务时,传入的参数
//Progress 异步任务的进度
//Result 结果
public class MyTask extends AsyncTask<Void, Integer, Void> {

    TextView tv;
    public MyTask(TextView tv) {
        // TODO Auto-generated constructor stub
        this.tv = tv;
    }

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();
        Log.d("Test", "onPre");
    }
    //该方法运行在非UI线程中
    //该方法中放耗时操作
    @Override
    protected Void doInBackground(Void... params) {
        // TODO Auto-generated method stub
        int count = 0;
        while(!isCancelled() && count < 10){
            count++;
            //发布进度
            //触发系统自动调用onProgressUpdate
            //相当于handler.sendMessage()
            publishProgress(count);

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return null;
    }
    //相当于handlerMessage()
    //该方法运行在UI线程中
    @Override
    protected void onProgressUpdate(Integer... values) {
        // TODO Auto-generated method stub
        super.onProgressUpdate(values);

        if(isCancelled()){
            return;
        }
        //操作UI控件
        int count = values[0];
        tv.setText(String.valueOf(count));
    }

    //该放在在取消异步任务之后运行
    @Override
    protected void onCancelled() {
        // TODO Auto-generated method stub
        super.onCancelled();
    }

    @Override
    protected void onPostExecute(Void result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        Log.d("Test", "onPost");
    }
}
阅读更多
个人分类: android学习
想对作者说点什么? 我来说一句

android多线程后台下载

2013年03月04日 84KB 下载

android多线程机制

2018年01月12日 394KB 下载

android多线程断点续传

2012年05月07日 154KB 下载

Android 多线程断点下载源码demo

2014年08月03日 135KB 下载

Android多线程下载文件实例

2012年04月28日 157KB 下载

android多线程管理

2015年02月02日 360KB 下载

android下载文件

2011年07月28日 3KB 下载

android多线程实例

2013年04月26日 2.81MB 下载

没有更多推荐了,返回首页

不良信息举报

Android多线程

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭