Android的多线程编程

作者: 见哥哥长高了 | 来源:发表于2019-08-08 13:10 被阅读12次

和Java一样,当我们要执行一些耗时的操作时(例如:发送网络请求),如果不将此类操作放在子线程去执行,就会导致主线程被阻塞,影响程序的正常运行。这个时候需要用到多线程技术,那么我们就来对多线程做进一步的了解吧。

多线程的基本用法

Android的多线程和Java使用相同的语法。定义一个线程,只需要新建一个类继承自Thread,然后重写run()方法,并在方法中编写耗时的操作。启动线程的话直接调用Thread的start()方法即可。

//定义线程
    class MyThread extends Thread{

        @Override
        public void run() {
            super.run();
        }
    }

new MyThread().start(); //启动线程

另外实现Runnable接口的方式也可以定义一个线程。

    class MyThread implements Runnable{

        @Override
        public void run() {
            
        }
    }

//使用线程
MyThread mythred = new MyThread();
new Thread(mythred).start();

Thread的构造函数接收一个Runnable参数,而我们new出来的MyThread正是一个实现了Runnable接口的对象,所以可以直接将它传入到Thread的构造函数里。接着调用Thread的start()方法。run() 中的代码就会在子线程中执行了。

另外,匿名类的方式 也能实现线程定义。

        new Thread(new Runnable() {
            @Override
            public void run() {
                
            }
        }).start();
在子线程中更新UI

我们给一个按钮添加监听,点击按钮的时候提示一个文本信息,在子线程中执行提示操作。代码如下:

        button06.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this,"提示",Toast.LENGTH_LONG).show();
                    }
                }).start();
            }
        });

以上代码并不能顺利的执行。因为Android是不能在子线程执行UI操作的。那么怎么办呢?这个时候我们就要用Handler来解决。

具体用法:
创建Handler对象,重写父类的handleMessage()方法,这handleMessage()方法中对具体的Message信息进行处理。

    private static final int UPDATE_01 = 1;
    
    private Handler handler = new Handler(){

        @Override
        public void handleMessage(Message msg) {

            switch (msg.what){

                case UPDATE_01:

                    Toast.makeText(MainActivity.this,"提示了一下",Toast.LENGTH_LONG).show();

                    break;

                    default:
                        break;
            }
        }
    };

        button06.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        
                        Message message = Message.obtain();
                        message.what =  UPDATE_01;
                        handler.sendMessage(message);
                    }
                }).start();
            }
        });
异步消息处理机制

Android的异步消息处理主要有4个部分组成:
1、Message: 是在线程之间进行传递的消息 消息内部可以携带少量的数据 用于在不同的线程之间进行数据交换。我们前面用到了what字段 其实消息内部还有一些别的字段,我们可以在实际的场景中合理选择。
public int arg1;
public int arg2;
public Object obj;
public Messenger replyTo;
public int sendingUid;
public int what;
2、Handle: 处理消息 一般的做法就是调用sendMessage()方法把消息发送出去,传递到handleMessage()方法中。
3、MessageQueue: 消息队列 存放消息 通过 Handle的sendMessage()发送出去的消息在消息被处理之前 会被存在消息队列中的知道被执行为止。每个线程只有一个MessageQueue。
4、Looper: 是每个线程MessageQueue的管家。执行run()操作后处理循环执行的状态。当发先消息队列中有消息的时候就会把消息取出,调起Handle的handleMessage()方法。每个线程只有一个Looper。

各个部分的关系如图所示:

异步消息处理机制示意图
AsyncTask的使用

AsyncTask是一个抽象类 我们要想使用它 必须新建一个类继承它。在继承的时候 我们需要指定3个范型的参数。
1、Params在执行AsyncTask时候需要传入的参数 在后台任务中使用
2、Progress 后台任务执行的时候 显示进度 需要此参数作为进度单位
3、Result当任务执行完毕 如果要对结果进行返回 则在此指定返回值对类型

请看下面的一个代码实例:

    class DownLoadTask extends AsyncTask<Void,Integer,Boolean>{

        /*
        * 这个方法会在后台开始执行人物之前调用 用于进行一些界面上的初始化操作  比如显示一个进度条对话框
        * */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //显示进度条
        }
        /*
        * 这个方法中虽有的人物都会在子线程执行,处理所有耗时的操作。任务一旦完成就通过return语句返回结果
        * 如果AsyncTask第三个范型参数指定的是Void 就可以不反悔任何的结果。
        * 这个方法中是不进行任何的UI操作的 如果要进行任何的UI操作,比如说返回下载的进度 可以调用onProgressUpdate()
        *
        * */
        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
            //关闭进度提示元素
            if (aBoolean) {
                //任务完成
            }else {
                //任务失败
            }
        }
        /*
        * 当在后台任务中调用了onProgressUpdate()方法后,此方法就会很快被执行
        * 该方法携带的参数 就是在后腰任务中传递过来的 在这个方法中对UI进行操作 利用参数中的数值对界面元素进行调整
        *
        * */
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            //在这里更新下载进度
        }

        /*
        * 当后台任务之ing完毕后  并通过return方法返回时 这个方法很快被调用 返回的参数传递到此方法中 可以利用参数进行页面操作
        * 比如 结束的时候 关闭进度条
        * */
        @Override
        protected Boolean doInBackground(Void... voids) {
            try {
                while (true){
                    int downloadProgress = download();//从此方法中完成操作 并取到进度数值
                    publishProgress(downloadProgress);

                    if (downloadProgress >= 100){
                        break;
                    }
                }

            }catch (Exception e){
                e.printStackTrace();
                return false;
            }
            return true;
        }
    }

在这里将第一个参数指定为void表示后台在执行AsyncTask对时候不需要传入参数
第二个参数为Integer类型 表示使用整形数据来作为进度表示对基本单位
第三个参数Boolean 表示 程序执行后的返回结果是布尔类型

相关文章

  • Android消息机制(六) 总结

    参考Android线程的正确使用姿势Android性能优化典范之多线程篇 Android多线程编程的总结Andro...

  • 关于并发编程的博客收藏

    Android并发编程 开篇http://ddrv.cn/a/23502/ Android并发编程 多线程与锁ht...

  • 育人书籍大全

    android 0-3年 android编程、设计模式、重构、多线程编程 3-5年 一线架构师编程实践、ap...

  • android开发 之 Bolts-Android

    目录 多线程编程对比:-iOS与Android Bolts-AndroidTasksChaining-TasksT...

  • Android多线程基础

    线程的基本用法 Android多线程编程并不比Java多线程编程特殊,基本都是使用相同的语法。那么如何创建一个线程...

  • 《java多线程编程核心技术》读书笔记

    最近读完了《java多线程编程核心技术》(高洪岩)、《Android高性能编程》(叶坤 译)、《Java REST...

  • POSIX线程 (一)

    POSIX POSIX是一种标准,例如有多线程编程标准、网络编程标准等。Android NDK的线程是通过POSI...

  • 多线程编程

    多线程编程之Linux环境下的多线程(一)多线程编程之Linux环境下的多线程(二)多线程编程之Linux环境下的...

  • Android启用线程的方法

    多线程编程经常使用:Handler(处理)、Thread(线程)和Runnable这三个类Android的cpu分...

  • Android多线程编程

    1.在子线程中更新UI Android中更新UI元素,必须在主线程中进行,否则就会出现异常。 运行以上程序,你会发...

网友评论

    本文标题:Android的多线程编程

    本文链接:https://www.haomeiwen.com/subject/rlgtjctx.html