Android 开发中用到的几个多线程解析

jopen 13年前

在开发工程中线程可以帮助我们提高运行速度,Android开发中我知道的线程有四个一个是老生长谈的Thread,第二个是asyncTask,第三个:TimetTask,第四个是Looper,四个多线程各有个的有点,Thread的运行速度是最快的,AsyncTask的规范性是最棒的,其它两个也有自己的优点,下面先贴上三个列子

1.Thread与Handler组合,比较常见

Handler主要是帮助我们来时时更新UI线程

这里在后天加载100张图片,然后没加载完成一个用handler 返回给UI线程一张图片并显示

最后加载完成返回一个List给UI线程 ,Handler就是一个后台线程与UI线程中间的桥梁

package com.android.wei.thread;    import java.io.InputStream;  import java.util.ArrayList;  import java.util.List;    import android.app.Activity;  import android.content.Context;  import android.graphics.Bitmap;  import android.graphics.BitmapFactory;  import android.os.Bundle;  import android.os.Handler;  import android.os.Message;  import android.view.View;  import android.view.View.OnClickListener;  import android.widget.Button;  import android.widget.ImageView;  import android.widget.TextView;    public class Activity01 extends Activity {      /** Called when the activity is first created. */          /**读取进度**/      public final static int LOAD_PROGRESS =0;            /**标志读取进度结束**/      public final static int LOAD_COMPLETE = 1;      /**开始加载100张图片按钮**/      Button mButton = null;            /**显示内容**/      TextView mTextView = null;            /**加载图片前的时间**/      Long mLoadStart = 0L;      /**加载图片完成的时间**/      Long mLoadEndt = 0L;            Context mContext = null;      /**图片列表**/      private List<Bitmap> list;      /**图片容器**/      private ImageView mImageView;      //接受传过来得消息      Handler handler = new Handler(){       public void handleMessage(Message msg){        switch(msg.what){        case LOAD_PROGRESS:         Bitmap bitmap = (Bitmap)msg.obj;         mTextView.setText("当前读取到第"+msg.arg1+"张图片");         mImageView.setImageBitmap(bitmap);         break;        case LOAD_COMPLETE:          list = (List<Bitmap>) msg.obj;         mTextView.setText("读取结束一共加载"+list.size()+"图片");         break;        }        super.handleMessage(msg);       }      };      public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          mContext = this;          setContentView(R.layout.main);          mButton =(Button) findViewById(R.id.button1);          mTextView=(TextView) findViewById(R.id.textView1);          mImageView =(ImageView) this.findViewById(R.id.imageview);          mTextView.setText("点击按钮加载图片");          mButton.setOnClickListener(new OnClickListener(){           public void onClick(View v){            //调用方法            LoadImage();           }          });                           }      public void LoadImage(){       new Thread(){        public void run(){         mLoadStart = System.currentTimeMillis();         List<Bitmap> list = new ArrayList<Bitmap>();         for(int i =0;i<100;i++){          Bitmap bitmap=ReadBitmap(mContext,R.drawable.icon);          Message msg = new Message();          msg.what = LOAD_PROGRESS;          msg.arg1 = i+1;          list.add(bitmap);          msg.obj = bitmap;          handler.sendMessage(msg);         }         mLoadEndt = System.currentTimeMillis();         Message msg = new Message();         msg.what = LOAD_COMPLETE;         msg.obj=list;         msg.arg1 = (int) (mLoadEndt - mLoadStart);         handler.sendMessage(msg);                 }       }.start();      }      public Bitmap ReadBitmap(Context context,int resId){       BitmapFactory.Options opt = new BitmapFactory.Options();       opt.inPreferredConfig = Bitmap.Config.RGB_565;       opt.inPurgeable = true;       opt.inInputShareable = true;       InputStream is = context.getResources().openRawResource(resId);       return BitmapFactory.decodeStream(is, null, opt);      }  }

2AsyncTask异步多线程

AsyncTask的规范型很强,能够时时反映更新的情况

它一般有这么几个方法

 * onPreExecute(), 该方法将在执行实际的后台操作前被UI 线程调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条,或者一些控件的实例化,这个方法可以不用实现。
       * doInBackground(Params...), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台处理工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。
      * onProgressUpdate(Progress...),在publishProgress方法被调用后,UI 线程将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
      * onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI 线程调用,后台的计算结果将通过该方法传递到UI 线程,并且在界面上展示给用户.

      * onCancelled(),在用户取消线程操作的时候调用。在主线程中调用onCancelled()的时候调用。

为了正确的使用AsyncTask类,以下是几条必须遵守的准则:

    1) Task的实例必须在UI 线程中创建

    2) execute方法必须在UI 线程中调用

    3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法,需要在UI线程中实例化这个task来调用。

    4) 该task只能被执行一次,否则多次调用时将会出现异常

package com.android.wei.thread;    import java.io.ByteArrayOutputStream;  import java.io.InputStream;  import java.util.ArrayList;  import java.util.List;  import java.util.Timer;  import java.util.TimerTask;    import android.app.Activity;  import android.content.Context;  import android.graphics.Bitmap;  import android.graphics.BitmapFactory;  import android.os.AsyncTask;  import android.os.Bundle;  import android.view.View;  import android.view.View.OnClickListener;  import android.widget.Button;  import android.widget.ImageView;  import android.widget.TextView;    public class Activity02 extends Activity{      /**开始StartAsync按钮**/   Button mButton = null;      Context mContext = null;      //内容显示出来   TextView mTextView = null;      //Timer 对象   Timer mTimer = null;      /** timerTask 对象**/   TimerTask mTimerTask = null;      /**记录TimerId**/   int mTimerId =0;   /**图片列表**/   private List<Bitmap> list;   /**图片容器**/   private ImageView mImageView;   public void onCreate(Bundle s){    super.onCreate(s);    setContentView(R.layout.main);    mContext = this;    mButton =(Button) this.findViewById(R.id.button1);    mImageView =(ImageView)this.findViewById(R.id.imageview);    mTextView =(TextView) this.findViewById(R.id.textView1);    mButton.setOnClickListener(new OnClickListener(){     public void onClick(View v){      StartAsync();     }    });           }   public void StartAsync(){    new AsyncTask<Object,Object,Object>(){              protected void onPreExecute(){               //首先执行这个方法,它在UI线程中,可以执行一些异步操作               mTextView.setText("开始加载进度");               super.onPreExecute();              }     @Override     protected Object doInBackground(Object... params) {      // TODO Auto-generated method stub      //异步后台执行,执行完毕可以返回出去一个结果 Object 对象      //得到开始加载得时间      list = new ArrayList<Bitmap>();      for(int i =0;i<100;i++){       Bitmap bitmap =ReadBitmap(mContext,R.drawable.icon);            final ByteArrayOutputStream os = new ByteArrayOutputStream();       bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);       byte[] image = os.toByteArray();       Bundle bundle = new Bundle();       bundle.putInt("index", i);       bundle.putByteArray("image", image);       publishProgress(bundle);       list.add(bitmap);             }            return list;     }     protected void onPostExecute(Object result){      //doInBackground 执行之后在这里可以接受到返回结果的对象      List<Bitmap> list = (List<Bitmap>) result;      mTextView.setText("一共加载了"+list.size()+"张图片");        super.onPostExecute(result);     }     protected void onProgressUpdate(Object... values){      //时时拿到当前的进度更新UI      Bundle bundle = (Bundle)values[0];      byte[] image = bundle.getByteArray("image");      Bitmap bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);      int index = bundle.getInt("index");      mTextView.setText("当前加载进度"+index);      mImageView.setImageBitmap(bitmap);      super.onProgressUpdate(values);     }         }.execute();   }   public Bitmap ReadBitmap(Context context,int resId){    BitmapFactory.Options opt = new BitmapFactory.Options();    opt.inPreferredConfig = Bitmap.Config.RGB_565;    opt.inPurgeable = true;    opt.inInputShareable = true;    InputStream is = context.getResources().openRawResource(resId);    return BitmapFactory.decodeStream(is, null, opt);   }     }

3TimerTask

可以根据我们的设置来间隔性的运行,可以很好的实现监听功能一般也跟handler一起

package com.android.wei.thread;    import java.util.Timer;  import java.util.TimerTask;    import android.app.Activity;  import android.content.Context;  import android.os.Bundle;  import android.os.Handler;  import android.os.Message;  import android.view.View;  import android.view.View.OnClickListener;  import android.widget.Button;  import android.widget.TextView;    public class TimerTaskActivity extends Activity{   /**执行Timer进度**/   public final static int LOAD_PROGRESS =0;      /**关闭TImer进度**/   public final static int CLOSE_PROGRESS =1;      /**开始TIMERTASK按钮**/   Button mButton0 = null;      /**关闭TIMERTASK按钮**/   Button mButton1 =null;      /**显示内容**/   TextView mTextView = null;      Context mContext = null;      /**timer对象**/   Timer mTimer = null;      /**TimerTask对象**/   TimerTask mTimerTask = null;      /**记录TimerID**/   int mTimerID =0;      Handler handler = new Handler(){    public void handleMessage(Message msg){     switch(msg.what){     case LOAD_PROGRESS:      mTextView.setText("当前得TimerID为:"+msg.arg1);      break;     case CLOSE_PROGRESS:      mTextView.setText("当前Timer已经关闭请重新启动");      break;     }     super.handleMessage(msg);    }   };      protected void onCreate(Bundle s){       setContentView(R.layout.timer);       mContext  = this;       mButton0 = (Button) this.findViewById(R.id.button1);       mButton1 = (Button) this.findViewById(R.id.button2);       mTextView = (TextView) this.findViewById(R.id.textView1);       mTextView.setText("点击按钮开始更新时间");       mButton0.setOnClickListener(new OnClickListener(){        public void onClick(View v){         StartTimer();        }       });       mButton1.setOnClickListener(new OnClickListener(){        public void onClick(View v){         CloseTimer();        }       });       super.onCreate(s);      }     public void StartTimer(){       if(mTimer == null){        mTimerTask = new TimerTask(){        @Override      public void run() {       mTimerID ++;       Message msg = new Message();       msg.what = LOAD_PROGRESS;       msg.arg1 =(int) (mTimerID);       handler.sendMessage(msg);             }                    };        mTimer = new Timer();        //第一个参数为执行的mTimerTask        //第二个参数为延迟得事件,这里写1000得意思是 mTimerTask将延迟1秒执行        //第三个参数为多久执行一次,这里写1000 表示没1秒执行一次mTimerTask的Run方法        mTimer.schedule(mTimerTask, 1000,1000);       }     }     public void CloseTimer(){      if(mTimer !=null){       mTimer.cancel();       mTimer = null;      }      if(mTimerTask!= null){       mTimerTask = null;      }      mTimerID =0;      handler.sendEmptyMessage(CLOSE_PROGRESS);     }  }