Android基础之进程和线程 AsyncTask , Handler

进程Process

默认情况下,一个应用程序的所有组件都在一个进程之中.

但也可以通过Manifest.xml文件中的android:process来指定某个<activity><service><provider><receiver>控件属于哪个进程,也可以为<application>指定进程

通过android:process可以让同一个应用的组件运行在不同的进程中,也可以使不同应用的组件运行在一个进程中

在系统内存较低的时候,Android系统会按一定规律选择性关闭一些进程.


线程Thread

不要阻塞UI线程(main线程)

不要从UI线程之外的线程来操纵UI,比如imgView.setImageBitmap(...)等


从别的线程来更改UI时,可以用Activity.runOnUiThread(Runnable),View.post(Runnable),View.postDelayed(Runnable,long)

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
            mImageView.post(new Runnable() {
                public void run() {
                    mImageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();
}
但遇到更加复杂的情形时会很乱,应该使用一个Handler或者继承AsyncTask类,


AsyncTask异步任务类

继承AsyncTask类时,不用自己去管理线程,onPreExcute是在调用前执行的块,onProgressUpdate,onPostExcute都是在原来的线程中进行的操作

doInBackground是在新的线程中的操作,其返回值返回给了onPostExcute方法

任何时候都可以在doInBackground中使用publishProcess()方法来执行onProgressUpdate.

任何时候都可以取消新线程.


public void onClick(View v) {
    new DownloadImageTask().execute("http://example.com/image.png");
}

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    /** The system calls this to perform work in a worker thread and
      * delivers it the parameters given to AsyncTask.execute() */
    protected Bitmap doInBackground(String... urls) {
        return loadImageFromNetwork(urls[0]);
    }
    
    /** The system calls this to perform work in the UI thread and delivers
      * the result from doInBackground() */
    protected void onPostExecute(Bitmap result) {
        mImageView.setImageBitmap(result);
    }
}

Handler

Handler的作用
1.可以安排在未来的某时进行一些操作
2.在不同的线程中执行一些操作,并支持线程之间的通信

一个Handler对应着一个线程以及它的消息队列
当你创建一个Handler的时候,它就和创建它的线程/消息队列相绑定
之后,这个handler就要开始处理这个消息队列中的消息了
Looper是一个消息队列的监听器,并不是每一个thread都有looper,主线程在创建时,系统自动为其创建了looper,而用HandlerThread创建的Thread都有looper

可以构建Handler对象与Looper沟通,以便send新消息到messageQueue.
或者接收Looper从MessageQueue中取出的消息.



在子线程中使用主线程的Handler发送消息(向主线程的MessageQueue发送消息)
拿一个常用的功能举例子:比如要从网络上获得一张图片,并且更新到当前Activity的imageView上
首先要新建一个线程,在其run方法中来从网络上下载图片                                                                     //下载这种操作比较费时,当然要用异步
在Activity中调用这个线程.start()来启动线程                                                                                  
在线程中下载完成时引用主线程的handler.sendMessage()来通知主线程下载好了开始更新       //在这个功能中handler是主线程的,消息队列也是主线程的,此时的主线程没有必                                                                                                                                                                           有handler和 looper,也就没必要用HandlerThread,普通的Thread即可
在主线程的handler中的handleMessage方法中更新UI                     //handler是主线程的,当然里面的handleMessage方法也在主线程中执行,在UI线程中更新UI
具体实现如下:
在Activity中:
Handler activityHandler=new Handler(){                                                       //因为handler需要重写handlMessage方法来决定其处理消息的方式,要new一个
              public void    handleMessage(Message msg){                
                             if(msg.arg1==UPDATE_UI){                                     
                                            imageView.setBitmap(....);                        //如果接受的消息一个参数是UPDATE_UI常量,更新UI
                              }
              }
}

启动一个新的线程:
class ImageThread extends Thread{
             public void run(){
                      //从网络上获得图片
                      //获得完毕之后
                      Message msg=new Message();            //生成一个消息对象
                      msg.arg1=UPDATE_UI;                           //设置其参数
                      activityHandler.sendMessage(msg);    //调用主线程的activityHandler,向主线程的消息队列发送消息
                      //或者这里调用
              }
}

ImageThread it=new ImageThread();
it.start();


所以如果两个线程之间要相互通信,就要两个线程都拥有handler,looper,消息队列了



而还有handler.post(Runnable)  postDelayed(Runnable,long)等,这些线程执行都是在调用它们的handler所在线程执行的








一些简单的实验:
//创建一个Hanlder对象
Handler handler=new Handler();
//把所要进行操作的线程对象用handler.post()或者.postDealyed()方法添加到线程队列中
handler.post(updateThread);                                  //handler.removeCallbacks(updateThread)来从消息队列中去除掉这个线程
Runnable updateThread =new Runnable(){
         public void run(){
                      //线程中的复杂操作
                     System.out.println("Thread Start");
        }
}



//下面这个是可以处理消息的Handler

Handler handler=new Handler(){

       public void handleMessage(Message msg){

                      System.out.println(msg.arg1+""); 

        }

}


handler.post(updateThread);             //把新线程加入到消息队列中

Runnable updateThread=new Runnable(){

                  public void run(){

                       Message msg=handler.obtainMessage();  //获得handler中消息队列的一个消息

                       msg.arg1=50;   //为msg携带的值赋值

                       handler.sendMessage(msg);               //把消息加入handler的消息队列

                }

}

但是上述两个Handler其实都没有真正的启动另外的线程,而还是在原来的main线程中执行!!!!


如果要使用Handler来生成新线程来执行复杂操作可以使用HandlerThread类,

HandlerThread类会启动一个带有looper的新的线程,而这个looper一会儿可以用来创建Handler

HandlerThread handlerThread=new HandlerThread("handler_thread");        //创建一个HandlerThread线程对象,如果要执行有意义的操作,继承这个类,重写run方法

handlerThread.start();

MyHandler myHandler=new MyHandler(handlerThread.getLooper());                       //用新线程的looper来创建一个handler对象


Message msg=myHandler.obtainMessage();

msg.sendToTarget();



class MyHandler extends Handler{

            public void handleMessage(Message msg){

                    

            }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值