【Android】【笔记】《Android 入门经典》part 12 线程与消息处理

来源:互联网 发布:linux服务器访问外网 编辑:程序博客网 时间:2024/06/05 06:10
本文为个人读书笔记,大部分为书中内容摘要。仅供记录和分享学习中遇到的需要留意的问题,如有相关版权问题请及时通知作者。

多线程的基本操作

创建线程
     Android中提供了两种创建线程的方法。
     1、通过Thread类的构造方法创建线程
          Thread(Runnablerunnalbe)
          该构造方法的参数runnable,可以通过创建一个Runnable类的对象并重写其run()方法来实现。
          
     Threadthread=newThread(newRunnable(){
          @Override
          publicvoidrun(){
               //要执行的操作代码,当线程被开启时,run()方法将会被执行
          }
     });
     
     2、通过实现Runnable接口创建线程
          publicclassClassNameextendsObjectimplementsRunnable
          当一个类实现Runnable接口后,还需要实现其run()方法,在run()方法中,可以编写要执行的操作代码
          
     publicclassMainActivityextendsActivityimplementsRunnable{
          @Override
          publicvoidonCreate(Bundle savedInstanceState){
              super.onCreate(savedInstanceState);
              setContentView(R.layout.main);
          }
          @Override
          publicvoidrun(){
              //要执行的操作
          }
     }

开启线程
     Thread类提供了start()方法
          start()

线程的休眠
    让线程暂停多长时间后再次执行,Thread类的sleep()方法
          Thread.sleep(longtime)
          time:休眠时间,单位ms

中断线程
     Thread类提供了interrupt()方法,使用interrupt()方法可以向指定的线程发送一个中断请求,并将该线程标记为中断状态。
          interrupt()
     当线程执行wait()、join()、sleep()方法时,线程的中断状态将被清除,并且抛出InterruptedException,所以,如果在线程中执行了wait()、join()、sleep()方法,那么,想要中断线程时,就需要使用一个boolean型的标记变量来记录线程的中断状态,并通过该标记变量来控制循环的执行与停止。




Handler消息传递机制
     在线程中直接操作操作UI界面会抛出异常,因此在Android中引入了Handler消息传递机制,来实现在新创建的线程中操作UI界面。

Looper循环者     
     MessageQueue消息队列:在Android中,一个线程对应一个Looper对象,一个Looper对象对应一个MessageQueue。MessageQueue用于存放Message消息,在MessageQueue中,存放的消息按照FIFO先进先出原则执行,MessageQueue被封装在Looper对象里。
     Looper对象用来为一个线程开启一个消息循环,用来操作MessageQueue。默认情况下Android中新创建的线程是没有开启消息循环的。但是主线程除外,系统自动为主线程创建Looper对象,开启消息循环。所以,当我们在主线程中,应用下面的代码创建Handler对象时,就不会出错,而如果在新创建的非主线程中,应用下面的代码创建Handler对象时。
          Handlerhandler2=newHandler();
     如果想要在非主线程中,创建Handler对象,首先需要使用Looper类的prepare()方法来初始化一个Looper对象,然后创建这个Handler对象,再使用Looper类的loop()方法,启动Looper,从消息队列里获取和处理消息。
Looper类提供的常用方法
方法描述prepare()初始化Looperloop()调用后,Looper真正开始工作,会从消息队列里获取消息和处理消息myLooper()获取当前线程的Looper对象getTread()获取Looper对象所属的线程quit()结束Looper循环

     写在Looper.loop()之后的代码不会被执行,这个函数内部是一个循环,当调用Handler.getLooper().quit()方法后,loop()方法才会中止,后面的代码才会运行

Handler消息处理类
     允许发送和处理Message或Rannable对象到其所在线程的MessageQueue中。
     Handler有两个主要作用:
     1、将Message或Runnable应用post()方法或sendMessage()方法发送到MessageQueue中,在发送时可以指定延迟时间、发送时间或者要携带的Bundle数据。当MessageQueue循环到该Message时,调用响应的Handler对象的handlerMessage()方法对其进行处理。
     2、在子线程中与主线程进行通信,也就睡在工作线程中与UI线程进行通信。
     在一个线程中,只能有一个Looper和MessageQueue,但是,可以有多个Handler,而且这些Handler可以共享同一个Looper和MessageQueue。
Handler类提供的常用方法
方法描述handleMessage(Message msg)处理消息的方法。通常重写该方法来处理消息,在发送消息时,该方法会自动回调post(Runnable r)立即发送Runnable对象,该Runnable对象最后将被封装成Message对象postAtTime(Runnable r,long uptimeMillis)定时发送Runnable对象,该Runnable对象最后将被封装成Message对象postDelayed(Runnable r,long delayMillis)延迟多少毫秒发送Runnable对象,该Runnable对象最后被封装成Message对象sendEmptyMessage(int what)发送空消息sendMessage(Message msg)立即发送消息sendMessageAtTime(Message msg,long UptimeMillis)定时发送消息sendMessageDelayed(Message msg,long delayMillis)延迟多少毫秒发送消息

Message消息类
     Message被存放在MessageQueue中,一个MessageQueue中可以包含多个Message对象。每个Message对象可以通过Message.obtain()方法或者Handler.obtainMessage()方法获得。一个Message对象具有5个属性
Message类的属性
属性类型描述arg1int存放整型数据arg2int存放整型数据objObject存放发送给接收器的Object类型的任意对象replyToMessenger指定此Message发送到何处的可选Message让对象whatint指定用户自定义的消息代码,以便接受者了解这个消息的信息
     使用Message类的属性可以携带int型和数据,如果要携带其他类型的数据,可以先将要携带的数据保存到Bundle对象中,然后通过Message类的setDate()方法将其添加到Message中
     Message类使用时要注意3点:
     1、尽管Message有public的默认构造方法,但是通常情况下,需要使用Message.obtain()方法或Handler.obtainMessage()方法来从消息池中获得空消息对象,以节省资源。
     2、如果一个Message只需要携带简单的int型信息,应优先使用Message.arg1和Message.arg2属性来传递信息,这比用Bundle省内存。
     3、尽可能使用Message.what来标识信息,以便用不同方式处理Message













0 0
原创粉丝点击