Android AsyncTask分析
---恢復(fù)內(nèi)容開始---
因為android的UI線程是不安全的,如果你UI線程里執(zhí)行一些耗時任務(wù),很容易就導(dǎo)致程序崩潰。并且目前網(wǎng)絡(luò)任務(wù)也不能夠在UI線程里執(zhí)行。處理這些問題除了直接寫一個線程以外,Android還提供一個AsyncTask(異步任務(wù)類)來更簡單的處理一些耗時任務(wù)。
?
AsyncTask<>是一個抽象類,通常用于繼承,繼承時需要指定三個泛型參數(shù)。
1、Params:啟動任務(wù)時傳入的參數(shù)的類型。這是一個數(shù)組,可以傳多個參數(shù)。調(diào)用時使用params[0]、params[1]、params[2]來獲取。
2、Progress:后臺任務(wù)完成的進(jìn)度值的類型。
3、Result:后臺任務(wù)執(zhí)行完畢返回結(jié)果的類型。
?
使用AsyncTask需要如下三步:
1、繼承抽象類,實(shí)現(xiàn)一個子類,傳入三個泛型參數(shù)。如果有參數(shù)不需要使用可設(shè)為Void。
2、根據(jù)需要,可實(shí)現(xiàn)以下方法。
- doInBackground(Params...):該方法是必須的,這個方法下寫的是后臺線程要執(zhí)行的任務(wù),并且會在子線程運(yùn)行(其他方法都是在UI線程執(zhí)行)。。該方法可以調(diào)用publicProgress(Progress...values)方法更新任務(wù)的進(jìn)度。
- onProgressUpdate(Progress... values):該方法在上一步調(diào)用publicProgress時觸發(fā)。
- onPreExecute():該方法會在執(zhí)行doInBackground方法前執(zhí)行,用于做一些準(zhǔn)備工作。
- onPostExecute(Result result):當(dāng)doInBackground執(zhí)行結(jié)束之后,系統(tǒng)會自動調(diào)用該方法,返回值也會傳到此函數(shù)。我們可以在這里完成后臺線程執(zhí)行后的結(jié)果。
3、最后用新建我們繼承類后的結(jié)果,然后調(diào)用execute(Params... params)。
注意:對象必須在UI線程中創(chuàng)建、execute方法必須在UI線程中調(diào)用、以上四個方法都需系統(tǒng)自動調(diào)用、每個對象只能被執(zhí)行一次,多次調(diào)用引發(fā)異常。
?
實(shí)例
講了那么多鋪墊,讓我們來講個例子吧~
我現(xiàn)在想從互聯(lián)網(wǎng)上下載一張圖片,就使用這個AsyncTask來做一下吧~
?為讓所有方法都實(shí)現(xiàn)一次,我們用兩種方法實(shí)現(xiàn):1、下載完畢后直接進(jìn)行顯示。2、一邊加載一邊顯示進(jìn)度,加載完畢顯示圖片。
下面是第一種的代碼,相對簡單一點(diǎn),只用了兩個函數(shù)。
public class MainActivity extends Activity {int downloadSize;int fileSize;Button bn;ImageView iv;ProgressBar progressBar;String url = "http://ww1.sinaimg.cn/mw690/6aa88161gw1eqqbw7h821j20hs0hsaba.jpg";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);bn = (Button) findViewById(R.id.down);iv = (ImageView) findViewById(R.id.image);MyOnClickListener myOnClickListener = new MyOnClickListener();bn.setOnClickListener(myOnClickListener);}class MyOnClickListener implements android.view.View.OnClickListener{@Overridepublic void onClick(View v) {AsyncDownload asyncDownload = new AsyncDownload();asyncDownload.execute(url);} }class AsyncDownload extends AsyncTask<String, Integer, Bitmap>{@Overrideprotected Bitmap doInBackground(String... params) {String imageUrl = params[0];URL url;try {url = new URL(imageUrl);InputStream is = url.openStream();BitmapFactory.Options op = new BitmapFactory.Options();op.inSampleSize = 2;Bitmap bitmap = BitmapFactory.decodeStream(is, null,op);} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;}@Overrideprotected void onPostExecute(Bitmap result) {super.onPostExecute(result);iv.setImageBitmap(result);}} }上面的代碼的功能是點(diǎn)擊按鈕,然后doInBackground后臺下載圖片,下載完畢onPostExecute顯示圖片。僅僅使用了兩個函數(shù),但是實(shí)現(xiàn)了AsyncTask的核心功能。
?
然后讓我們感受一下能夠顯示進(jìn)度的。
public class MainActivity extends Activity {int downloadSize;int fileSize;Button bn;ImageView iv;ProgressBar progressBar;String url = "http://ww1.sinaimg.cn/mw690/6aa88161gw1eqqbw7h821j20hs0hsaba.jpg";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);bn = (Button) findViewById(R.id.down);iv = (ImageView) findViewById(R.id.image);progressBar = (ProgressBar) findViewById(R.id.bar);MyOnClickListener myOnClickListener = new MyOnClickListener();bn.setOnClickListener(myOnClickListener);}Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {}};class MyOnClickListener implements android.view.View.OnClickListener{@Overridepublic void onClick(View v) {AsyncDownload asyncDownload = new AsyncDownload();asyncDownload.execute(url);} }class AsyncDownload extends AsyncTask<String, Integer, Void>{@Overrideprotected Void doInBackground(String... params) {String imageUrl = params[0];try {URL url = new URL(imageUrl);URLConnection conn = url.openConnection(); conn.connect(); InputStream is = conn.getInputStream(); fileSize = conn.getContentLength(); publishProgress(0x111);FileOutputStream fos = new FileOutputStream(getPath());byte[] bytes = new byte[1024]; int len = -1; while((len = is.read(bytes))!=-1) { fos.write(bytes, 0, len); downloadSize+=len; publishProgress(0x222);} publishProgress(0x333);is.close(); fos.close(); } catch (MalformedURLException e) {// TODO Auto-generated catch block e.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch block e.printStackTrace();}return null; }@Overrideprotected void onProgressUpdate(Integer... values) {super.onProgressUpdate(values);switch(values[0]){case 0x111:progressBar.setMax(fileSize);break;case 0x222:progressBar.setProgress(downloadSize);break;case 0x333:try { if(getPath().endsWith(".jpg")||getPath().endsWith(".png")){ FileInputStream fis = new FileInputStream(getPath()); iv.setImageBitmap(BitmapFactory.decodeStream(fis)); } downloadSize = 0; fileSize = 0; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } break;}}}public String getPath() {File root = getExternalCacheDir();if (root != null){return root.getAbsolutePath() + "test.jpg";}return null;} }這里實(shí)現(xiàn)的功能是點(diǎn)擊下載按鈕,后臺從互聯(lián)網(wǎng)加載文件,首先獲取文件大小,設(shè)置progressbar最大值,然后一邊下載、一邊存入本地、一邊設(shè)置progressbar的值,實(shí)現(xiàn)進(jìn)度條。下載完畢從本地獲取圖片顯示出來。這一次多使用了顯示進(jìn)度的函數(shù)onProgressUpdate。
?
其實(shí),onProgressUpdate這個函數(shù)一般我們在線程里會用Handler來實(shí)現(xiàn)。
在AsyncTask給我們把平常使用線程進(jìn)行異步操作的所用東西打包在一起了,不得不說確實(shí)省了一些事。
實(shí)際上能夠用AsyncTask實(shí)現(xiàn)的東西完全可以直接用線程來實(shí)現(xiàn)~
?
我在些第二個代碼的時候?qū)戫樍耸?#xff0c;用Handler實(shí)現(xiàn)了一遍,大家在下面可以看一下。
public class MainActivity extends Activity {int downloadSize;int fileSize;Button bn;ImageView iv;ProgressBar progressBar;String url = "http://ww1.sinaimg.cn/mw690/6aa88161gw1eqqbw7h821j20hs0hsaba.jpg";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);bn = (Button) findViewById(R.id.down);iv = (ImageView) findViewById(R.id.image);progressBar = (ProgressBar) findViewById(R.id.bar);MyOnClickListener myOnClickListener = new MyOnClickListener();bn.setOnClickListener(myOnClickListener);}Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {switch(msg.what){case 0x111:progressBar.setMax(fileSize);break;case 0x222:progressBar.setProgress(downloadSize);break;case 0x333:try { if(getPath().endsWith(".jpg")||getPath().endsWith(".png")){ FileInputStream fis = new FileInputStream(getPath()); iv.setImageBitmap(BitmapFactory.decodeStream(fis)); } downloadSize = 0; fileSize = 0; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } break;}}};class MyOnClickListener implements android.view.View.OnClickListener{@Overridepublic void onClick(View v) {AsyncDownload asyncDownload = new AsyncDownload();asyncDownload.execute(url);} }class AsyncDownload extends AsyncTask<String, Integer, Void>{@Overrideprotected Void doInBackground(String... params) {String imageUrl = params[0];try {URL url = new URL(imageUrl);URLConnection conn = url.openConnection(); conn.connect(); InputStream is = conn.getInputStream(); fileSize = conn.getContentLength(); handler.sendEmptyMessage(0x111);FileOutputStream fos = new FileOutputStream(getPath());byte[] bytes = new byte[1024]; int len = -1; while((len = is.read(bytes))!=-1) { fos.write(bytes, 0, len); downloadSize+=len; handler.sendEmptyMessage(0x222);} handler.sendEmptyMessage(0x333);is.close(); fos.close(); } catch (MalformedURLException e) {// TODO Auto-generated catch block e.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch block e.printStackTrace();}return null; }}public String getPath() {File root = getExternalCacheDir();if (root != null){return root.getAbsolutePath() + "test.jpg";}return null;} }?
啦啦啦,就到這里吧~
轉(zhuǎn)載于:https://www.cnblogs.com/glimpse/p/5280942.html
總結(jié)
以上是生活随笔為你收集整理的Android AsyncTask分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 贝叶斯方法之一
- 下一篇: MySQL基于ROW格式的数据恢复