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); } }