編輯:關於Android編程
安卓異步任務 ---AsyncTask
為什麼要異步任務:
1.Android單線程模型
2.耗時操作放在非主線程中執行
AsyncTask為何而生
1.子線程中更新UI
2.封裝,簡化異步操作
構造AsyncTask子類的參數
AsyncTask
Params: 啟動任務時輸入的參數的類型,也就是execute()方法中,傳入的參數
Progress: 後台任務執行中返回進度值的類型,進度更新時用到
Result 後台執行任務完成後返回結果的類型,如果後台是從網絡上獲取一張圖片,那麼就返回Bitmap類型
構建AsyncTask子類的回調方法
(插入知識:什麼是回調函數)你到一個商店買東西,剛好你要的東西沒有貨,於是你在店員那裡留下了你的電話,過了幾天店裡有貨了,店員就打了你的電話,然後你接到電話後就到店裡去取了貨。在這個例子裡,你的電話號碼就叫回調函數,你把電話留給店員就叫登記回調函數,店裡後來有貨了叫做觸發了回調關聯的事件,店員給你打電話叫做調用回調函數,你到店裡去取貨叫做響應回調事件。(轉自知乎作者:常溪玲)
doInBackground 必須重寫,異步執行後台線程將要完成的任務
onPreExecute 執行後台耗時操作前被調用,通常用戶完成一些初始化操作
onPostExecute 當doInBackground()完成後,系統會自動調用,並將doInBackground方法返回的值傳給該方法。
onProgressUpdate 在doInBackground()方法中調用publishProgress()方法更新任務的執行進度後,就會觸發該方法。可以很清楚的了解耗時操作的完成進度
函數執行順序演示代碼:
MyAsynTask.java
package com.example.app; import android.os.AsyncTask; import android.util.Log; public class MyAsynTask extends AsyncTask{ @Override protected Void doInBackground(Void... arg0) { // TODO Auto-generated method stub Log.d("sr", "doInBackground"); publishProgress(); return null; } @Override protected void onPostExecute(Void result) { // TODO Auto-generated method stub super.onPostExecute(result); Log.d("sr", "onPostExecute"); } @Override protected void onPreExecute() { // TODO Auto-generated method stub super.onPreExecute(); Log.d("sr", "onPreExecute"); } @Override protected void onProgressUpdate(Void... values) { // TODO Auto-generated method stub super.onProgressUpdate(values); Log.d("sr", "onProgressUpdate"); } }
package com.example.app;
import android.os.Bundle;
import android.app.Activity;
import android.app.TaskStackBuilder;
import android.view.Menu;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyAsynTask task = new MyAsynTask();
task.execute();
}
}
輸出結果:

下面是實例演示(加載一張網絡圖片):<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PC9wPgo8cD7S7LK9z9+zzKO6z8LU2M28z/E8L3A+CjxwPlVJz9+zzKO6yejWw828z/E8L3A+CjxwPru5ysfU2tStwLS1xLmks8zW0KO6PC9wPgo8cD7Qwr2oSW1hZ2VUZXN0LmphdmHA4KOsvMyz0EFjdGl2aXR5o6y0tL2oT25DcmVhdGUoKbe9t6iho9DCvaiyvL7WzsS8/mltYWdlLnhtbKOswO/D5tPQ0ru49mltYWdlVmlld8/Uyr7NvMasILrN0ru49r34tsjM9TwvcD4KPHA+PGJyPgo8L3A+CjxwPmltYWdlLnhtbDxicj4KPC9wPgo8cD48L3A+CjxwcmUgY2xhc3M9"brush:java;">
package com.example.app;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.ProgressBar;
public class ImageTest extends Activity {
private ImageView mImageView;
private ProgressBar mProgressBar;
private static String URL = "http://image.zhaiba.com/2015/7/1/201507011732462088603781.jpg";//網路圖片地址
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.image);
mImageView = (ImageView) findViewById(R.id.image);
mProgressBar = (ProgressBar)findViewById(R.id.progressbar);
}
}
接下來創建AsynTask異步處理
在ImageTest.java中創建內部類MyAsyncTask 繼承AsyncTask
ImageTest.java
package com.example.app;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
public class ImageTest extends Activity {
private ImageView mImageView;
private ProgressBar mProgressBar;
private static String URL = "http://image.zhaiba.com/2015/7/1/201507011732462088603781.jpg";//網路圖片地址
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.image);
mImageView = (ImageView) findViewById(R.id.image);
mProgressBar = (ProgressBar)findViewById(R.id.progressbar);
//設置傳遞進去的參數
new MyAsyncTask().execute(URL);//可以傳入一個,或多個參數
}
class MyAsyncTask extends AsyncTask
//第一個參數傳入URL,所以是String,第二個參數不需要返回加載的進度,所以設置為Void,第三個值為返回值類型,這裡是圖片,所以設置為Bitmap
{
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
//將隱藏的進度條顯示出來,提示用戶等待
mProgressBar.setVisibility(View.VISIBLE);//顯示進度條
}
@Override
protected void onPostExecute(Bitmap result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
//操作UI 設置圖像
mProgressBar.setVisibility(View.GONE);
mImageView.setImageBitmap(result);
}
@Override
protected Bitmap doInBackground(String... params) {//參數為不定長的數組,這是從execute()方法中傳入的參數
// TODO Auto-generated method stub
//獲取傳遞進來的參數
String url = params[0];//上面execute方法中傳入的參數第一個參數為URL
Bitmap bitmap = null;
URLConnection connection;
InputStream is;
try {
connection = new URL(url).openConnection();
is = connection.getInputStream();//獲取輸入流
BufferedInputStream bis = new BufferedInputStream(is);
//通過decodeStream方法解析輸入流
bitmap = BitmapFactory.decodeStream(bis);//將輸入流解析為圖像
is.close();
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//將bitmap作為返回值返回後面調用的方法
return bitmap;//返回圖像
}
}
}
配置AndroidManifest增加網絡權限,聲明activity
在主頁上添加一個按鈕,點擊,進入ImageTest那個activity
Activity_main.xml
MainActivity.java
package com.example.app;
import android.os.Bundle;
import android.app.Activity;
import android.app.TaskStackBuilder;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyAsynTask task = new MyAsynTask();
task.execute();
}
public void loadImage(View view)
{
startActivity(new Intent(this, ImageTest.class));
}
}
下面的例子就是模擬進度條的更新。
進度條布局progressbar.xml
package com.example.app;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ProgressBar;
public class ProgressBarTest extends Activity {
private ProgressBar mProgressBar;
private MyAsyncTask mTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.progressbar);
mProgressBar = (ProgressBar)findViewById(R.id.pg);
mTask = new MyAsyncTask();
mTask.execute();
}
class MyAsyncTask extends AsyncTask //第二個參數因為要實時的返回進度條的狀態,所以要Integer參數
{
@Override
protected Void doInBackground(Void... arg0) {
// TODO Auto-generated method stub
//模擬進度更新
for(int i = 0; i < 100; i ++){
publishProgress(i); //去調用下面那個onProgressUpdate方法
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
//獲取進度更新值
mProgressBar.setProgress(values[0]);//當前進度值
}
}
}
為主頁添加一個測試進度條按鈕,設置點擊方法後,運行:

可以看到進度條在動態的更新
但是這樣存在一個問題,返回後重新加載,再返回後重新加載,發現進度條不發生變化,因為每次返回加載都啟動了一個異步任務,當前需要加載時有可能上次的任務還沒有執行完,所以當前的進度條不更新。
把任務的生命周期設置為activity一樣
在ProgressBarTest.java 中重寫onPause()方法
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
if(mTask != null && mTask.getStatus() == AsyncTask.Status.RUNNING){//任務不為空切正在運行
mTask.cancel(true);
//cancel方法只是將對應的AsyncTask標記為cancel狀態,並不是真正的取消線程的執行
}
}
將當前任務設置為cancel狀態,然後在doInBackground方法和onProgressUpdate方法中中判斷一下
protected Void doInBackground(Void... arg0) {
// TODO Auto-generated method stub
//模擬進度更新
for(int i = 0; i < 100; i ++){
if(isCancelled())
break;
publishProgress(i); //去調用下面那個onProgressUpdate方法
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
if(isCancelled())
return ;
//獲取進度更新值
mProgressBar.setProgress(values[0]);//當前進度值
}
使用AsyncTask注意事項
必須在UI線程中創建AsyncTask的實例
必須在UI線程中調用AsyncTask的execute()方法
重寫的四個方法時系統調用的,不能手動調用
每個AsyncTask只能被調用(execute())一次,多次調用將會引發異常(它的四個方法只有doInBackground是異步處理,不能直接更新UI,其他三個方法可以更新UI。
源代碼下載:AsyncTask加載網路圖片,模擬進度條的更新
附上網友寫的一篇筆記:http://www.cnblogs.com/caobotao/p/5020857.html
Android消息推送:手把手教你集成小米推送(附demo)
前言在Android開發中,消息推送功能的使用非常常見。為了降低開發成本,使用第三方推送是現今較為流行的解決方案。今天,我將手把手教大家如何在你的應用裡集成小米推送目錄1
Android開發之控制手機音頻
本實例通過MediaPlayer播放一首音樂並通過AudioManager控制手機音頻,關於AudioManager的詳解可參照:Android開發之AudioManag
MUI事件管理
1、事件綁定除了可以使用addEventListener()方法監聽某個特定元素上的事件外, 也可以使用.on()方法實現批量元素的事件綁定。.on( event , s
安卓CountDownTimer實現全民奪寶搶購倒計時和短信驗證碼倒計時
在sina裡看到了什麼全民奪寶的鏈接,然後忍不住1元的誘惑被坑了10多塊,什麼都沒有抽到,但是還是有人抽到了不知道是不是坑爹的,然後也就動手做一下倒計時的功能。先看全民奪