Android基礎(chǔ)07-AsyncTask及JSON解析

一、AsyncTask:

(一)、相關(guān)知識回顧:

1、開發(fā)Android應(yīng)用時必須遵守單線程模型的原則:

????????Android UI操作并不是線程安全的,并且這些操作必須在UI線程中執(zhí)行。

2、單線程模型中始終要記住兩條法則:

1). 不要阻塞UI線程 ;

2). 確保只在UI線程中訪問Android UI控件。

????????當(dāng)一個程序第一次啟動時,Android會同時啟動一個對應(yīng)的主線程(Main Thread),主線程主要負(fù)責(zé)處理與UI相關(guān)的事件,如:用戶的按鍵事件,用戶接觸屏幕的事件以及屏幕繪圖事件,并把相關(guān)的事件分發(fā)到對應(yīng)的組件進行處理。所以主線程通常又被叫做UI線程。

3、Android4.0以上版本中,主線程中不允許訪問網(wǎng)絡(luò)。涉及到網(wǎng)絡(luò)操作的程序一般都是需要開一個新線程完成網(wǎng)絡(luò)訪問。但是在獲得頁面數(shù)據(jù)后,又不能將數(shù)據(jù)返回到UI界面中 。因為子線程(Worker Thread)不能直接訪問UI線程中的成員,也就是說沒有辦法對UI界面上的內(nèi)容進行操作,如果操作,將拋出異常:CalledFromWrongThreadException。

其實,android提供了幾種在其他線程中訪問UI線程的方法:

Activity.runOnUiThread( Runnable )

View.post( Runnable )

View.postDelayed( Runnable, long )

Handler消息傳遞機制(后續(xù)課程中講解)

????????這些類或方法會使代碼很復(fù)雜很難理解。為了解決這個問題,Android 1.5提供了一個工具類:AsyncTask,它使創(chuàng)建與用戶界面長時間交互運行的任務(wù)變得更簡單。AsyncTask更輕量級一些,適用于簡單的異步處理,不需要借助線程和Handler即可實現(xiàn)。

(二)、AsyncTask的代碼實現(xiàn):

1、AsyncTask是抽象類.AsyncTask定義了三種泛型類型 Params,Progress和Result。

Params 啟動任務(wù)執(zhí)行的輸入?yún)?shù),比如HTTP請求的URL。 一般用String類型;

Progress 后臺任務(wù)執(zhí)行的百分比。 一般用Integer類型;

Result 后臺執(zhí)行任務(wù)最終返回的結(jié)果,一般用byte[]或者String。

2、AsyncTask的執(zhí)行分為四個步驟,每一步都對應(yīng)一個回調(diào)方法(由應(yīng)用程序自動調(diào)用的方法),開發(fā)者需要做的就是實現(xiàn)這些方法。

1) 定義AsyncTask的子類;

2) 實現(xiàn)AsyncTask中定義的方法:(可以全部實現(xiàn),也可以只實現(xiàn)其中一部分)

onPreExecute(), 該方法將在執(zhí)行實際的后臺操作前被UI thread調(diào)用。可以在該方法中做一些準(zhǔn)備工作,如在界面上顯示一個進度條。

doInBackground(Params...), 將在onPreExecute 方法執(zhí)行后馬上執(zhí)行,該方法運行在后臺線程中。這里將主要負(fù)責(zé)執(zhí)行那些很耗時的后臺計算工作。可以調(diào)用 publishProgress方法來更新實時的任務(wù)進度。該方法是抽象方法,子類必須實現(xiàn)。

onProgressUpdate(Progress...),在publishProgress方法被調(diào)用后,UI thread將調(diào)用這個方法從而在界面上展示任務(wù)的進展情況,例如通過一個進度條進行展示。

onPostExecute(Result), 在doInBackground 執(zhí)行完成后,onPostExecute 方法將被UI thread調(diào)用,后臺的計算結(jié)果將通過該方法傳遞到UI thread.

3、核心代碼:

publicclassMainActivityextendsActivity?{

privatefinalstaticStringTAG=?"MainActivity";

privateString?urlString?=?"http://www.baidu.com/";

privateTextView?text_main_info;

@Override

protectedvoidonCreate(Bundle?savedInstanceState)?{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

text_main_info?=?(TextView)?findViewById(R.id.text_main_info);

//?調(diào)用異步任務(wù),執(zhí)行網(wǎng)絡(luò)訪問

newMyTask(this).execute(urlString);

}

classMyTaskextendsAsyncTask?{

privateProgressDialog?pDialog;

privateContextcontext=null;

//?構(gòu)造方法,初始化進度對話框

publicMyTask(Context?context)?{

this.context?=?context;

pDialog?=newProgressDialog(context);

pDialog.setIcon(R.drawable.ic_launcher);

pDialog.setTitle("提示:");

pDialog.setMessage("數(shù)據(jù)加載中。。。");

}

//?事先執(zhí)行方法中顯示進度對話框

@Override

protectedvoidonPreExecute()?{

pDialog.show();

super.onPreExecute();

}

//?進度條進度改變方法。一般情況下,可以不寫該方法

@Override

protectedvoidonProgressUpdate(Void...?values)?{

//TODOAuto-generated?method?stub

super.onProgressUpdate(values);

}

//?后臺執(zhí)行方法,這個方法執(zhí)行worker?Thread異步訪問網(wǎng)絡(luò),加載數(shù)據(jù)。該方法中不可以執(zhí)行任何UI操作。

@Override

protectedbyte[]?doInBackground(String...?params)?{

BufferedInputStream?bis?=null;

ByteArrayOutputStream?baos?=newByteArrayOutputStream();

try{

URL?urlObj?=newURL(params[0]);

HttpURLConnection?httpConn?=?(HttpURLConnection)?urlObj.openConnection();

httpConn.setDoInput(true);

// httpConn.setDoOutput(true);

httpConn.setRequestMethod("GET");

httpConn.connect();

if?(httpConn.getResponseCode() == 200) {

bis =?new?BufferedInputStream(httpConn.getInputStream());

byte[] buffer =?new?byte[1024 * 8];

int?c = 0;

while?((c = bis.read(buffer)) != -1) {

baos.write(buffer, 0, c);

baos.flush();

}

// Toast.makeText(context, baos.toByteArray().toString(),

// Toast.LENGTH_LONG).show();

return?baos.toByteArray();

}

}?catch?(Exception e) {

e.printStackTrace();

}?finally?{

try?{

if?(bis !=?null) {

bis.close();

}

if?(baos !=?null) {

baos.close();

}

}?catch?(IOException e) {

e.printStackTrace();

}

}

returnnull;

}

// 事后方法,這個方法主要作用是執(zhí)行對主線程中UI的操作??梢詫崿F(xiàn)主線程和子線程之間的數(shù)據(jù)交互

@Override

protectedvoid?onPostExecute(byte[] result) {

super.onPostExecute(result);

if?(result ==?null) {

text_main_info.setText("網(wǎng)絡(luò)異常,加載數(shù)據(jù)失??!");

}?else?{

text_main_info.setText(new?String(result));

}

pDialog.dismiss();

}

}

@Override

publicboolean?onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.main, menu);

returntrue;

}

}

(三)、增加進度條的異步任務(wù):

1、制作思路:

在異步任務(wù)內(nèi)部類的構(gòu)造方法中new ProgressDialog();

在onPreExecute()中調(diào)用ProgressDialog對象的show()方法,顯示進度對話框;

在doInBackground()方法中計算進度,在while循環(huán)中通過調(diào)用publishProgress()方法將進度數(shù)據(jù)隨時發(fā)布出去;

進度數(shù)據(jù)的計算公式:publishProgress((int) ((count / (double) length) * 100)),其中count為當(dāng)前加載的文件長度,length為文件的總長度;

在onPostExecute()方法中調(diào)用?ProgressDialog對象的dismiss()方法,讓進度條消失。

2、核心代碼:

? ? A、如果計算進度?【在doInBackground()方法中增加如下代碼】

// 獲取內(nèi)容的長度

int length = httpConn.getContentLength();

while ((c = bis.read(buffer)) != -1) {

baos.write(buffer, 0, c);

baos.flush();

count += c;

if (length > 0) {

// 如果知道響應(yīng)的長度,調(diào)用publishProgress()更新進度

publishProgress((int) ((count / (double) length) * 100));

}

}

? ? B、如果更新進度?【在onProgressUpdate()方法中增加如下代碼】

????????????????????????????????????????pDialog.setProgress(values[0]);

(四)、為了正確的使用AsyncTask類,以下是幾條必須遵守的準(zhǔn)則:

  1) Task的實例必須在UI thread中創(chuàng)建;

  2) execute方法必須在UI thread中調(diào)用;

  3) 不要手動的調(diào)用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)這幾個方法 ;

  4)?該task只能被執(zhí)行一次,否則多次調(diào)用時將會出現(xiàn)異常?;

? ? ? doInBackground方法和onPostExecute的參數(shù)必須對應(yīng),這兩個參數(shù)在AsyncTask聲明的泛型參數(shù)列表中指定,第一個為doInBackground接受的參數(shù),第二個為顯示進度的參數(shù),第三個為doInBackground返回和onPostExecute傳入的參數(shù)。


二、JSON:

(一)、概念:JSON(javascript object notation) ,是一種輕量級的數(shù)據(jù)儲存和交換格式。它是完全獨立于語言的文本格式。JSON易于閱讀、編寫,也易于機器解析和生成。

(二)、JSON基本格式:

1、鍵值對對象格式:用“{}”包圍

2、數(shù)組格式:用“[]”包圍.

(三)、JSON PK XML:

1、json和xml在可讀性、可擴展性上都不相上下;

2、解碼難度上看,json更方便和簡潔;

3、json對數(shù)據(jù)描述性上比xml差;

4、應(yīng)用json實現(xiàn)功能的速度要遠(yuǎn)快于xml。

(四)、JSON解析原則:

1、看到{},創(chuàng)建JsonObject對象;

2、看到[],創(chuàng)建JsonArray對象;

3、看到JsonArray,要for循環(huán)遍歷。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android Handler機制系列文章整體內(nèi)容如下: Android Handler機制1之ThreadAnd...
    隔壁老李頭閱讀 3,419評論 1 15
  • 在Android中我們可以通過Thread+Handler實現(xiàn)多線程通信,一種經(jīng)典的使用場景是:在新線程中進行耗時...
    呂侯爺閱讀 2,167評論 2 23
  • Android開發(fā)者:你真的會用AsyncTask嗎? 導(dǎo)讀.1 在Android應(yīng)用開發(fā)中,我們需要時刻注意保證...
    cxm11閱讀 2,772評論 0 29
  • 文章簡介AsyncTask 是Android 開發(fā)一個常用的多線程異步任務(wù)組件。網(wǎng)上資料很多也很雜,所以我決定整理...
    chen_yip閱讀 13,743評論 0 14
  • 上周就有同事推薦去看第三期朗讀者中麥家寫給兒子的信的那一段,今天特意抽時間看了一遍。 一開始是麥家跟主持人的交流,...
    Michiko七七閱讀 939評論 0 1

友情鏈接更多精彩內(nèi)容