Android——多线程

Android上的进程

在了解Android线程之前得先了解一下Android的进程。当一个程序第一次启动的时候,Android会启动一个LINUX进程和一个主线程。默认的情况下,所有该程序的组件都将在该进程和线程中运行。同时,Android会为每个应用程序分配一个单独的LINUX用户。Android会尽量保留一个正在运行进程,只在内存资源出现不足时,Android会尝试停止一些进程从而释放足够的资源给其他新的进程使用, 也能保证用户正在访问的当前进程有足够的资源去及时地响应用户的事件。Android会根据进程中运行的组件类别以及组件的状态来判断该进程的重要性,Android会首先停止那些不重要的进程。按照重要性从高到低一共有五个级别:
前台进程
前台进程是用户当前正在使用的进程。只有一些前台进程可以在任何时候都存在。他们是最后一个被结束的,当内存低到根本连他们都不能运行的时候。一般来说, 在这种情况下,设备会进行内存调度,中止一些前台进程来保持对用户交互的响应。
可见进程
可见进程不包含前台的组件但是会在屏幕上显示一个可见的进程是的重要程度很高,除非前台进程需要获取它的资源,不然不会被中止。
服务进程
运行着一个通过startService() 方法启动的service,这个service不属于上面提到的2种更高重要性的。service所在的进程虽然对用户不是直接可见的,但是他们执行了用户非常关注的任务(比如播放mp3,从网络下载数据)。只要前台进程和可见进程有足够的内存,系统不会回收他们。
后台进程
运行着一个对用户不可见的activity(调用过 onStop() 方法).这些进程对用户体验没有直接的影响,可以在服务进程、可见进程、前台进程需要内存的时候回收。通常,系统中会有很多不可见进程在运行,他们被保存在LRU (least recently used) 列表中,以便内存不足的时候被第一时间回收。如果一个activity正 确的执行了它的生命周期,关闭这个进程对于用户体验没有太大的影响。
空进程
未运行任何程序组件。运行这些进程的唯一原因是作为一个缓存,缩短下次程序需要重新使用的启动时间。系统经常中止这些进程,这样可以调节程序缓存和系统缓存的平衡。
Android 对进程的重要性评级的时候,选取它最高的级别。另外,当被另外的一个进程依赖的时候,某个进程的级别可能会增高。一个为其他进程服务的进程永远不会比被服务的进程重要级低。因为服务进程比后台activity进程重要级高,因此一个要进行耗时工作的activity最好启动一个service来做这个工作,而不是开启一个子进程特别是这个操作需要的时间比activity存在的时间还要长的时候。例如,在后台播放音乐,向网上上传摄像头拍到的图片,使用service可以使进程最少获取到“服务进程”级别的重要级,而不用考虑activity目前是什么状态。broadcast receivers做费时的工作的时候,也应该启用一个服务而不是开一个线程。

Android上的线程

无论何时启动APP,所有的组件都会运行在一个单独的线程中(默认的)——叫做主线程。这个线程主要用于处理UI的操作并为视图组件和小部件分发事件等,因此主线程也被称作UI线程。
如果你在UI线程中运行一个耗时操作,那么UI就会被锁住,直到这个耗时操作结束。对于用户体验来说,这是非常糟糕的!这也就是为什么我们要理解Android上的线程机制了。理解这些机制就可以把一些复杂的工作移动到其它的线程中去执行。如果你在UI线程中运行一个耗时的任务,那么很有可能会发生ANR(应用无响应),这样用户就会很快地结束掉你的APP。
线程的基本使用方法:
第一种:新建一个类继承自Thread(class MyThread extends Thread),然后重写run方法。启动这个线程,只需要新建对象调用start方法
第二种:新建一个类实现接口Runnable,重写run方法,启动线程时,新建该类对象,此对象可以作为Thread的构造函数中的形参,然后调用Thread的start的方法:例如new Thread(MyThread).start();
第三种:使用匿名类的方式:
new Thread(new Runable(){
重写run方法
}.start();
Android不允许在子线程中进行UI操作,然而有些时候我们必须在子线程中执行一些耗时操作(disk access, network access, or SQL access),然后根据任务结果更新相应的UI控件。为了解决这个问题,Android提供了异步消息处理机制。

解析异步消息处理机制:

1.Message
Mesage是在线程之间传递的消息,可以在内部携带少量的信息,用于在不同的线程之间交换数据。Message的what字段(
用户自定义的消息代码每个handler各自包含自己的消息代码)和obj字段(发送给接收者的对象)
2.Handler
Handler用来发送和处理消息,sendMessage(),handleMessage()
3.MessageQueue
消息队列,用来存放通过Handler发送的消息。每个线程只会有一个MessageQueue对象
4.Looper
Looper是每个线程的MessageQueue的管家
Looper主要作用:
1、 与当前线程绑定,保证一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue。
2、 loop()方法,不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。(handlerMessage)
Android——多线程_第1张图片

注意:
1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
2、Looper.loop()会让当前线程进入一个无限循环,不断从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。

private Handler handler=new Handler() {
 public void  handleMessage(Message msg){
     switch(msg.what){
         case UPDATE:
             // 进行UI操作
             break;
     }
 }
};
@Override
public void onClick(View v) {
    switch (v.getId()){
        case R.id.text:
            new Thread(new Runnable() {
                @Override
                public void run() {
                   Message message=new Message();
                    message.what=UPDATE;
                    handler.sendMessage(message);
                }
            }).start();
    }
}

使用AsyncTask

AsyncTask背后的实现是基于异步处理机制,只是Android帮我们做了很好的封装
AsyncTask的基本用法:AsyncTask是一个抽象类,使用之前必须创建子类继承它。在继承时我们可以为AsyncTask类指定三个泛型参数
1.Params 在执行AsyncTask时需要传入的参数,可以再后台任务中使用
2.Progress 后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
3.Result 当任务执行完后,如果对结果进行返回,则使用这里指定的泛型作为返回值的类型。
AsyncTask常用的四个方法:
1.onPreEXecute()
这个方法会在任务开始执行之前调用,用于在初始界面上的初始化操作,比如显示一个进度条对话框。
2.doInBackground(Params)
这个方法中的所有代码都是在子线程中运行的,所以用来处理耗时操作,不能用来进行UI操作,如果需要更新UI元素,比如反馈当前进度,可以调用publishProgress(Progress)方法。
3.onProgressUpdate(Progress)
在后台调用publishProgress(Progress)方法后,会调用此方法,方法中携带的参数是后台任务传递过来的,在这个方法中可以对UI进行操作。
4.onPostExecute(Result)
后台任务执行完毕,并通过return进行返回时,这个方法就会调用。返回的数据会作为参数传入,可以利用返回的数据进行一些UI操作。可进行任务收尾工作

本文关于进程的描述摘自http://android.blog.51cto.com/268543/343823

你可能感兴趣的:(多线程,android,AsyncTask)