一:ANR現(xiàn)象:
==應用程序無響應<Application not Responsed>==
1.單線程模型的原則:
- 主線程UI不能被阻塞
- 非主線程不能更新UI
public class MainActivity extends Activity{
private TextView textView;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInatanceState);
setContentView(R.layout.main_activity);
//違反第二原則:在非主線程更新UI
//CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
new Thread(){
public void run(){
int count = 0;
while(count < 100){
count ++ ;
try{
Thread.sleep(1000);
}
catch(Exception e){
e.printStackTrace;
}
//在非UI線程更新UI
textView.setText("當前count:"+count);
}
};
}.start();
}
//違反第一個原則,導致ANR現(xiàn)象出現(xiàn)
public void click(View view){
try{
Thread.sleep(6000);
}
catch(Exception e){
e.printStackTrace();
}
}
}
二.AsyncTask的基本使用
1.自定義一個類繼承系統(tǒng)的AsyncTask,其參數(shù)說明如下:
- Params:啟動異步任務執(zhí)行的輸入?yún)?shù) 例如HTTP請求的URL一般是String類型
- Progress:后臺執(zhí)行任務的百分比 通常是Integer類型
- Result:后臺執(zhí)行任務最終返回的結果
==注意:AsyncTask的執(zhí)行分為四個步驟 每一步都對應一個回調方法(由應用程序自動調用的方法) 開發(fā)者需要做的就是實現(xiàn)這些方法==
2.為了正確的使用AsyncTask類蒜茴,必須遵守以下幾條準則:
- AsyncTask的實例必須在UI線程中創(chuàng)建
- execute方法必須在UI線程中調用
- 不要手動去調用onPreExecute() doInBaground() onProgressUpdate() onPostExecute()
- AsyncTask的實例只能被執(zhí)行一次 多次調用的時候將會出現(xiàn)異常
==代碼:首先自定義一個類實現(xiàn)系統(tǒng)AsyncTask,異步圖片下載:==
public class MyAsyncTask extends AsyncTask<String , Void , Bitmap>{
//上下文對象
private Context context;
private ProgressDialog dialog;
private ImageView imageView;
//構造
public MyAsyncTask(Context context , ImageView imageView){
super();
this.context = context;
this.imageView = imageView;
}
/**
* 實現(xiàn)四個系統(tǒng)回調的方法
*/
/**
* 1.onPreExecute()方法:在后臺執(zhí)行前的準備工作秕硝,主線程調用
* 準備工作:做什么拢军?>創(chuàng)建進度對話框
*/
@Override
protected void onPreExecute(){
super.onPreExecute();
dialog = new ProgressDialog();
dialog.setIcon(R.drawable.xxx);
dialog.setTitle("友情提示赁项!");
dialog.setMessage("正在玩命為您加載中");
//下面show()方法不要忘了励负,否則不顯示進度對話框
dialog.show();
}
/**
* 2.doInBackground()方法:非主線程調用莺奔,后臺的主要工作線程鸠珠,
* 如耗時的操作(網(wǎng)絡下載圖片饺蔑,下載JSON等)都放在這里執(zhí)行锌介。
* 它是子線程,不可以在這里做UI操作(重要)
* 參數(shù)是String類型字符數(shù)組猾警,通常為傳入的url
*/
@Override
public void doInBackground(String...params){
//網(wǎng)絡請求:
/*創(chuàng)建HttpClient的實例*/
HttpClient httpClient = new DefaultHttpClient();
/*創(chuàng)建連接方法的實例孔祸,HttpGet()的構造中傳入url地址*/
HttpGet httpGet = new HttpGet(params[0]);
try{
/*調用創(chuàng)建好的HttpClient的實例的execute方法來發(fā)送創(chuàng)建好的HttpGet或HttpPost請求,并返回HttpResponse對象*/
HttpResponse httpResponse = httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode() == 200){
/*返回實體對象*/
HttpEntity entity = httpResponse.getEntity();
byte [] data = EntityUtils.toByteArray(entity);
Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length);
return bitmap;
}
}
catch(Exception e){
e.printStackTrace();
}
finally{
httpClient.getConnectionManager().shutdown();
}
}
/**
* 更新顯示進度发皿,主線程調用
*/
@Override
public void onProgressUpdate(Void...values){
super.onProgressUpdate(values);
}
/**
* 在doInBackground執(zhí)行完成之后調用,后臺的計算結果將通過該方法傳遞到UI線程,回到主線程(主線程調用的)
* 可以實現(xiàn)主線程和子線程之間的數(shù)據(jù)交互
*/
public void onPostExcute(Bitmap bitmap){
super.onPostExecute(bitmap);
if(bitmap != null){
imageView.setImageBitmap(bitmap);
}
else{
Toast.makeText(context,"下載圖片失敗",Toast.LENGTH.LONG).show();
}
//關閉進度對話框
dialog.dismiss();
}
}
測試代碼:
public class MainActivity extends Activity{
private ImageView imageView;
private MyAsyncTask myAsyncTask;
private String url = "";http://p5.qhimg.com/dmt/490_350_/t01405cf23f986e5ef6.jpg
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
imageView = (ImageView)findViewById(R.id.iv_imageview);
//創(chuàng)建AsyncTask的實例
myAsyncTask = new MyAsyncTask(this,imageView);
}
//點擊按鈕崔慧,開始異步下載圖片
public void downloadPic(View view){
/*AsyncTask的實例只能被執(zhí)行一次*/
myAsyncTask.execute(url);
}
}