Android 開發中用到的幾個多線程解析

jopen 12年前發布 | 39K 次閱讀 Android Android開發 移動開發

在開發工程中線程可以幫助我們提高運行速度,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);
   }
}

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!