在開發工程中線程可以幫助我們提高運行速度,Android開發中我知道的線程有四個一個是老生長談的Thread,第二個是asyncTask,第三個:TimetTask,第四個是Looper,四個多線程各有個的有點,Thread的運行速度是最快的,AsyncTask的規范性是最棒的,其它兩個也有自己的優點,下面先貼上三個列子
1.Thread與Handler組合,比較常見
Handler主要是幫助我們來時時更新UI線程
這裡在後天加載100張圖片,然後沒加載完成一個用handler 返回給UI線程一張圖片並顯示
最後加載完成返回一個List給UI線程 ,Handler就是一個後臺線程與UI線程中間的橋梁
001
package com.android.wei.thread;
002
003
import java.io.InputStream;
004
import java.util.ArrayList;
005
import java.util.List;
006
007
import android.app.Activity;
008
import android.content.Context;
009
import android.graphics.Bitmap;
010
import android.graphics.BitmapFactory;
011
import android.os.Bundle;
012
import android.os.Handler;
013
import android.os.Message;
014
import android.view.View;
015
import android.view.View.OnClickListener;
016
import android.widget.Button;
017
import android.widget.ImageView;
018
import android.widget.TextView;
019
020
public class Activity01 extends Activity {
021
/** Called when the activity is first created. */
022
023
/**讀取進度**/
024
public final static int LOAD_PROGRESS =0;
025
026
/**標志讀取進度結束**/
027
public final static int LOAD_COMPLETE = 1;
028
/**開始加載100張圖片按鈕**/
029
Button mButton = null;
030
031
/**顯示內容**/
032
TextView mTextView = null;
033
034
/**加載圖片前的時間**/
035
Long mLoadStart = 0L;
036
/**加載圖片完成的時間**/
037
Long mLoadEndt = 0L;
038
039
Context mContext = null;
040
/**圖片列表**/
041
private List<Bitmap> list;
042
/**圖片容器**/
043
private ImageView mImageView;
044
//接受傳過來得消息
045
Handler handler = new Handler(){
046
public void handleMessage(Message msg){
047
switch(msg.what){
048
case LOAD_PROGRESS:
049
Bitmap bitmap = (Bitmap)msg.obj;
050
mTextView.setText("當前讀取到第"+msg.arg1+"張圖片");
051
mImageView.setImageBitmap(bitmap);
052
break;
053
case LOAD_COMPLETE:
054
list = (List<Bitmap>) msg.obj;
055
mTextView.setText("讀取結束一共加載"+list.size()+"圖片");
056
break;
057
}
058
super.handleMessage(msg);
059
}
060
};
061
public void onCreate(Bundle savedInstanceState) {
062
super.onCreate(savedInstanceState);
063
mContext = this;
064
setContentView(R.layout.main);
065
mButton =(Button) findViewById(R.id.button1);
066
mTextView=(TextView) findViewById(R.id.textView1);
067
mImageView =(ImageView) this.findViewById(R.id.imageview);
068
mTextView.setText("點擊按鈕加載圖片");
069
mButton.setOnClickListener(new OnClickListener(){
070
public void onClick(View v){
071
//調用方法
072
LoadImage();
073
}
074
});
075
076
077
}
078
public void LoadImage(){
079
new Thread(){
080
public void run(){
081
mLoadStart = System.currentTimeMillis();
082
List<Bitmap> list = new ArrayList<Bitmap>();
083
for(int i =0;i<100;i++){
084
Bitmap bitmap=ReadBitmap(mContext,R.drawable.icon);
085
Message msg = new Message();
086
msg.what = LOAD_PROGRESS;
087
msg.arg1 = i+1;
088
list.add(bitmap);
089
msg.obj = bitmap;
090
handler.sendMessage(msg);
091
}
092
mLoadEndt = System.currentTimeMillis();
093
Message msg = new Message();
094
msg.what = LOAD_COMPLETE;
095
msg.obj=list;
096
msg.arg1 = (int) (mLoadEndt – mLoadStart);
097
handler.sendMessage(msg);
098
099
}
100
}.start();
101
}
102
public Bitmap ReadBitmap(Context context,int resId){
103
BitmapFactory.Options opt = new BitmapFactory.Options();
104
opt.inPreferredConfig = Bitmap.Config.RGB_565;
105
opt.inPurgeable = true;
106
opt.inInputShareable = true;
107
InputStream is = context.getResources().openRawResource(resId);
108
return BitmapFactory.decodeStream(is, null, opt);
109
}
110
}
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隻能被執行一次,否則多次調用時將會出現異常
001
package com.android.wei.thread;
002
003
import java.io.ByteArrayOutputStream;
004
import java.io.InputStream;
005
import java.util.ArrayList;
006
import java.util.List;
007
import java.util.Timer;
008
import java.util.TimerTask;
009
010
import android.app.Activity;
011
import android.content.Context;
012
import android.graphics.Bitmap;
013
import android.graphics.BitmapFactory;
014
import android.os.AsyncTask;
015
import android.os.Bundle;
016
import android.view.View;
017
import android.view.View.OnClickListener;
018
import android.widget.Button;
019
import android.widget.ImageView;
020
import android.widget.TextView;
021
022
public class Activity02 extends Activity{
023
024
/**開始StartAsync按鈕**/
025
Button mButton = null;
026
027
Context mContext = null;
028
029
//內容顯示出來
030
TextView mTextView = null;
031
032
//Timer 對象
033
Timer mTimer = null;
034
035
/** timerTask 對象**/
036
TimerTask mTimerTask = null;
037
038
/**記錄TimerId**/
039
int mTimerId =0;
040
/**圖片列表**/
041
private List<Bitmap> list;
042
/**圖片容器**/
043
private ImageView mImageView;
044
public void onCreate(Bundle s){
045
super.onCreate(s);
046
setContentView(R.layout.main);
047
mContext = this;
048
mButton =(Button) this.findViewById(R.id.button1);
049
mImageView =(ImageView)this.findViewById(R.id.imageview);
050
mTextView =(TextView) this.findViewById(R.id.textView1);
051
mButton.setOnClickListener(new OnClickListener(){
052
public void onClick(View v){
053
StartAsync();
054
}
055
});
056
057
058
}
059
public void StartAsync(){
060
new AsyncTask<Object,Object,Object>(){
061
protected void onPreExecute(){
062
//首先執行這個方法,它在UI線程中,可以執行一些異步操作
063
mTextView.setText("開始加載進度");
064
super.onPreExecute();
065
}
066
@Override
067
protected Object doInBackground(Object… params) {
068
// TODO Auto-generated method stub
069
//異步後臺執行,執行完畢可以返回出去一個結果 Object 對象
070
//得到開始加載得時間
071
list = new ArrayList<Bitmap>();
072
for(int i =0;i<100;i++){
073
Bitmap bitmap =ReadBitmap(mContext,R.drawable.icon);
074
final ByteArrayOutputStream os = new ByteArrayOutputStream();
075
bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
076
byte[] image = os.toByteArray();
077
Bundle bundle = new Bundle();
078
bundle.putInt("index", i);
079
bundle.putByteArray("image", image);
080
publishProgress(bundle);
081
list.add(bitmap);
082
083
}
084
085
return list;
086
}
087
protected void onPostExecute(Object result){
088
//doInBackground 執行之後在這裡可以接受到返回結果的對象
089
List<Bitmap> list = (List<Bitmap>) result;
090
mTextView.setText("一共加載瞭"+list.size()+"張圖片");
091
super.onPostExecute(result);
092
}
093
protected void onProgressUpdate(Object… values){
094
//時時拿到當前的進度更新UI
095
Bundle bundle = (Bundle)values[0];
096
byte[] image = bundle.getByteArray("image");
097
Bitmap bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);
098
int index = bundle.getInt("index");
099
mTextView.setText("當前加載進度"+index);
100
mImageView.setImageBitmap(bitmap);
101
super.onProgressUpdate(values);
102
}
103
104
}.execute();
105
}
106
public Bitmap ReadBitmap(Context context,int resId){
107
BitmapFactory.Options opt = new BitmapFactory.Options();
108
opt.inPreferredConfig = Bitmap.Config.RGB_565;
109
opt.inPurgeable = true;
110
opt.inInputShareable = true;
111
InputStream is = context.getResources().openRawResource(resId);
112
return BitmapFactory.decodeStream(is, null, opt);
113
}
114
115
}
3TimerTask
可以根據我們的設置來間隔性的運行,可以很好的實現監聽功能一般也跟handler一起
001
package com.android.wei.thread;
002
003
import java.util.Timer;
004
import java.util.TimerTask;
005
006
import android.app.Activity;
007
import android.content.Context;
008
import android.os.Bundle;
009
import android.os.Handler;
010
import android.os.Message;
011
import android.view.View;
012
import android.view.View.OnClickListener;
013
import android.widget.Button;
014
import android.widget.TextView;
015
016
public class TimerTaskActivity extends Activity{
017
/**執行Timer進度**/
018
public final static int LOAD_PROGRESS =0;
019
020
/**關閉TImer進度**/
021
public final static int CLOSE_PROGRESS =1;
022
023
/**開始TIMERTASK按鈕**/
024
Button mButton0 = null;
025
026
/**關閉TIMERTASK按鈕**/
027
Button mButton1 =null;
028
029
/**顯示內容**/
030
TextView mTextView = null;
031
032
Context mContext = null;
033
034
/**timer對象**/
035
Timer mTimer = null;
036
037
/**TimerTask對象**/
038
TimerTask mTimerTask = null;
039
040
/**記錄TimerID**/
041
int mTimerID =0;
042
043
Handler handler = new Handler(){
044
public void handleMessage(Message msg){
045
switch(msg.what){
046
case LOAD_PROGRESS:
047
mTextView.setText("當前得TimerID為:"+msg.arg1);
048
break;
049
case CLOSE_PROGRESS:
050
mTextView.setText("當前Timer已經關閉請重新啟動");
051
break;
052
}
053
super.handleMessage(msg);
054
}
055
};
056
protected void onCreate(Bundle s){
057
setContentView(R.layout.timer);
058
mContext = this;
059
mButton0 = (Button) this.findViewById(R.id.button1);
060
mButton1 = (Button) this.findViewById(R.id.button2);
061
mTextView = (TextView) this.findViewById(R.id.textView1);
062
mTextView.setText("點擊按鈕開始更新時間");
063
mButton0.setOnClickListener(new OnClickListener(){
064
public void onClick(View v){
065
StartTimer();
066
}
067
});
068
mButton1.setOnClickListener(new OnClickListener(){
069
public void onClick(View v){
070
CloseTimer();
071
}
072
});
073
super.onCreate(s);
074
}
075
public void StartTimer(){
076
if(mTimer == null){
077
mTimerTask = new TimerTask(){
078
079
@Override
080
public void run() {
081
mTimerID ++;
082
Message msg = new Message();
083
msg.what = LOAD_PROGRESS;
084
msg.arg1 =(int) (mTimerID);
085
handler.sendMessage(msg);
086
087
}
088
089
};
090
mTimer = new Timer();
091
//第一個參數為執行的mTimerTask
092
//第二個參數為延遲得事件,這裡寫1000得意思是 mTimerTask將延遲1秒執行
093
//第三個參數為多久執行一次,這裡寫1000 表示沒1秒執行一次mTimerTask的Run方法
094
mTimer.schedule(mTimerTask, 1000,1000);
095
}
096
}
097
public void CloseTimer(){
098
if(mTimer !=null){
099
mTimer.cancel();
100
mTimer = null;
101
}
102
if(mTimerTask!= null){
103
mTimerTask = null;
104
}
105
mTimerID =0;
106
handler.sendEmptyMessage(CLOSE_PROGRESS);
107
}
108
}
摘自 antkingwei