欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android之多线程与异步浅析

程序员文章站 2022-03-03 22:09:49
一、如何理解同步与异步? 同步:发出动作后,在收到响应前,什么都不能做; 异步:发出动作后,可以去做其他的事情,不用等待响应。 通俗的理解上述两个概念:同步就是我喊你去吃饭,我要一直等到你回应;异步就是我喊你去吃饭,我就去了,不管你是否回应。二、为何要用异步? Android应用程序在启动时,系统会自动的为该程序生成一个UI线程(即我们常说的主线程),更新页面(UI)的操作都必须在UI线程中进行。......

一、如何理解同步与异步?

           同步:发出动作后,在收到响应前,什么都不能做;

           异步:发出动作后,可以去做其他的事情,不用等待响应。

           通俗的理解上述两个概念:同步就是我喊你去吃饭,我要一直等到你回应;异步就是我喊你去吃饭,我就去了,不管你是否回应。

二、为何要用多线程? 

      Android应用程序在启动时,系统会自动的为该程序生成一个UI线程(即我们常说的主线程),更新页面(UI)的操作都必须在UI线程中进行。与此同时,因为只有一个主线程,在程序运行时,添加控件、点击按钮、网络请求、图片加载等都是在主线程中运行,而这些操作会被放在队列中,顺序执行,每次执行一个事件。这时就会出现一个问题,因为顺序执行且每次只执行一个事件,如果某一个事件执行事件过长(耗时操作),则主线程阻塞,界面卡顿(严重的会报ANR),此时对界面进行操作会出现是否停止响应的提示。这种情况严重影响了操作感。

   为了解决此问题,在程序中使用了多线程,即在UI线程(主线程)之外,新建线程(因多用来处理耗时操作,又称之为工作线程)。将主线程中的耗时操作,如网络请求、文件下载等放入工作线程中进行,避免了因耗时操作将主线程阻塞而引起的ANR问题。因此,为了防止出现ANR,才要用多线程。

此外,使用多线程,可以实现异步,也可以进行多任务(多线程下载)。

三、如何处理多线程之间的通信?

     通过上述对多线程的理解,在多线程开发过程中,我们需要注意:

  • 绝对不能在UI线程中进行耗时操作,以防止阻塞UI线程
  • 不能在UI线程之外更新UI

    由此两点,那我们该如何处理主线程和工作线程之间的通信呢?Android系统为我们提供了两种方式,是Handler机制和AsyncTaskLoader机制。

(一)Handler机制

       主要了解四个类:Looper(循环者)、Handler(消息处理)、Message(消息)、MessageQueue(消息队列)

   Looper: 在Android中,一个线程可以产生一个Looper对象,由它来管理该线程中的消息队列(MessageQueue)。调用Looper的Loop()方法后,就会进入一个无限循环中,发现MessageQueue中存在一条消息,就会取出来并传递到Handler的handleMessage()方法中。Looper对象用来为一个线程开启一个消息循环,用来操作MessgeQueue。默认情况下,Android中新创建的线程是没有开启消息循环的(主线程除外)。

    Handler:主要用于发送和处理消息。发送信息一般使用Handler的sendMessage()方法,发出的消息经过一系列辗转处理后,最终会传递到Handler的handleMessage()方法中。消息处理类(Handler)允许发送和处理Message和Runnable对象到其所在线程的MessageQueue中。它主要有两个作用:

  (1)、将Message应用post()方法或sendMessage()方法发送到MessageQueue中,在发送时可以指定延时发送、发送时间等。当MessageQueue循环到该Message时,调用相应的Handler对象的handlerMessage()方法对其进行处理。

  (2)、在子线程中与主线程进行通信,也就是在工作线程中与UI线程进行通信。另外,在一个线程中只能有一个Looper和MessageQueue,但是可以有多个Handler,而且这些Handler可以共享一个Looper和MessageQueue。

    Message:是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同的线程之间交换数据,如Message的what字段,和arg1,arg2来携带一些整型的数据,使用obj字段携带一个Object对象。消息类(Message)被存放在MessageQueue中,一个MessageQueue中可以包含多个Message对象。每个Message对象可以通过Message.obtain()方法或者Handler.obtainMessage()方法获得。

   MessageQueue:它主要用于存放所有通过Handler发送的消息。这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个MessageQueue对象。 

private Handler handler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 1:
                    String message = (String) msg.obj;
                    System.out.println("从子线程中传递过来的消息:"+message);
                    //对UI进行更新
                    break;
                default:
                    break;
            }
        }
    };

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Thread(){
            @Override
            public void run() {
                super.run();
                Message msg = new Message();
                msg.what = 1;
                msg.obj = "要发送的消息";
                handler.sendMessage(msg);
            }
        }.start();
}

   (二)AsyncTaskLoader机制:

       创建一个子类继承 AsyncTaskLoader 并实现一个最重要的方法loadInBackground(),该方法和doInBackground()原理相同。下次再补充了!

    

   

 

 

 

 

 

 

 

 

 

本文地址:https://blog.csdn.net/u013970897/article/details/107407876

相关标签: Android 多线程