Android有進度條非同步任務下載圖片,
首先在AndroidMainifest中添加上網許可權
<uses-permission android:name="android.permission.INTERNET" />
布局檔案activity_main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/img" android:layout_width="match_parent" android:layout_height="280dp" /> <Button android:id="@+id/btn" android:layout_width="150dp" android:layout_height="50dp" android:text="下載圖片" /></LinearLayout>
Activity代碼:
public class MainActivity extends Activity{private Button button;private ImageView imageView;private ProgressDialog progressDialog;private final String IMATH_PATH = "http://image16-c.poco.cn/best_pocoers/20141010/11092014101016572228935421.jpg";private AsyncTask<String, Integer, byte[]> task;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_main);button = (Button)findViewById(R.id.btn);imageView = (ImageView)findViewById(R.id.img);progressDialog = new ProgressDialog(this);progressDialog.setTitle("提示資訊");progressDialog.setMessage("正在下載中,請稍後");progressDialog.setOnCancelListener(new OnCancelListener() {@Overridepublic void onCancel(DialogInterface arg0) {// TODO Auto-generated method stubtask.cancel(true);}});progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubtask = new MyAsyncTask().execute(IMATH_PATH);}});} class MyAsyncTask extends AsyncTask<String, Integer, byte[]>{ @Overrideprotected void onPreExecute() {// TODO Auto-generated method stubsuper.onPreExecute();progressDialog.setProgress(0);progressDialog.show();} @Overrideprotected void onProgressUpdate(Integer... values) {// TODO Auto-generated method stubsuper.onProgressUpdate(values);progressDialog.setProgress(values[0]);} @Overrideprotected byte[] doInBackground(String... params) {// TODO Auto-generated method stubHttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(params[0]);byte[] image = new byte[]{};try{HttpResponse httpResponse = httpClient.execute(httpGet);HttpEntity httpEntity = httpResponse.getEntity();InputStream inputStream = null;ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();if(httpEntity !=null && httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){long file_length = httpEntity.getContentLength();long total_length = 0;int length = 0;byte[] data = new byte[1024];inputStream = httpEntity.getContent();while(-1 != (length = inputStream.read(data))){total_length += length;byteArrayOutputStream.write(data, 0, length);int progress = ((int)(total_length/(float)file_length)*100);publishProgress(progress);}}image = byteArrayOutputStream.toByteArray();inputStream.close();byteArrayOutputStream.close();}catch(Exception e){ e.printStackTrace();}finally{httpClient.getConnectionManager().shutdown();}return image;}@Overrideprotected void onPostExecute(byte[] result) {// TODO Auto-generated method stubsuper.onPostExecute(result);Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length);imageView.setImageBitmap(bitmap);progressDialog.dismiss();} }}
講解:
syncTask:非同步任務,從字面上來說,就是在我們的UI主線程啟動並執行時候,非同步完成一些操作。AsyncTask允許我們的執行一個非同步任務在後台。我們可以將耗時的操作放在非同步任務當中來執行,並隨時將任務執行的結果返回給我們的UI線程來更新我們的UI控制項。通過AsyncTask我們可以輕鬆的解決多線程之間的通訊問題。
怎麼來理解AsyncTask呢?通俗一點來說,AsyncTask就相當於Android給我們提供了一個多線程編程的一個架構,其介於Thread和Handler之間,我們如果要定義一個AsyncTask,就需要定義一個類來繼承AsyncTask這個抽象類別,並實現其唯一的一個 doInBackgroud 抽象方法。要掌握AsyncTask,我們就必須要一個概念,總結起來就是: 3個泛型,4個步驟。
3個泛型指的是什麼呢?我們來看看AsyncTask這個抽象類別的定義,當我們定義一個類來繼承AsyncTask這個類的時候,我們需要為其指定3個泛型參數:
AsyncTask <Params, Progress, Result>
- Params: 這個泛型指定的是我們傳遞給非同步任務執行時的參數的類型
- Progress: 這個泛型指定的是我們的非同步任務在執行的時候將執行的進度返回給UI線程的參數的類型
- Result: 這個泛型指定的非同步任務執行完後返回給UI線程的結果的類型
我們在定義一個類繼承AsyncTask類的時候,必須要指定好這三個泛型的類型,如果都不指定的話,則都將其寫成Void,例如:
AsyncTask <Void, Void, Void>
4個步驟:當我們執行一個非同步任務的時候,其需要按照下面的4個步驟分別執行
- onPreExecute(): 這個方法是在執行非同步任務之前的時候執行,並且是在UI Thread當中執行的,通常我們在這個方法裡做一些UI控制項的初始化的操作,例如彈出要給ProgressDialog
- doInBackground(Params... params): 在onPreExecute()方法執行完之後,會馬上執行這個方法,這個方法就是來處理非同步任務的方法,Android作業系統會在背景線程池當中開啟一個worker thread來執行我們的這個方法,所以這個方法是在worker thread當中執行的,這個方法執行完之後就可以將我們的執行結果發送給我們的最後一個 onPostExecute 方法,在這個方法裡,我們可以從網路當中擷取資料等一些耗時的操作
- onProgressUpdate(Progess... values): 這個方法也是在UI Thread當中執行的,我們在非同步任務執行的時候,有時候需要將執行的進度返回給我們的UI介面,例如下載一張網狀圖片,我們需要時刻顯示其下載的進度,就可以使用這個方法來更新我們的進度。這個方法在調用之前,我們需要在 doInBackground 方法中調用一個 publishProgress(Progress) 的方法來將我們的進度時時刻刻傳遞給 onProgressUpdate 方法來更新
- onPostExecute(Result... result): 當我們的非同步任務執行完之後,就會將結果返回給這個方法,這個方法也是在UI Thread當中調用的,我們可以將返回的結果顯示在UI控制項上