亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Android 實現聯網(三) 在線程中聯網

系統 1811 0

在前面的關于Java I/O的學習中,有一個我們需要牢記的是:對數據流的操作都是阻塞的,在一般情況下,我們是不需要考慮這個問題的,但是在Android 實現聯網的時候,我們必須考慮到這個問題。比如:從網絡上下載一張圖片:
public Bitmap returnBitmap(String url)
{
URL myFileUrl = null;
Bitmap bitmap = null;
try{
myFileUrl = new URL(url);
}catch(MalformedURLException e){
e.printStackTrace();
return null;
};
try{
HttpURLConnection conn = (HttpURLConnection)myFileUrl.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bitmap = BitmapFactroy.decodeStream(is);
is.close();
}catch(IOException e){
e.printStackTrace();
}
return bitmap;
}
由于網絡連接需要很長的時間,需要3-5秒,甚至更長的時間才能返回頁面的內容。如果此連接動作直接在主線程,也就是UI線程中處理,會發生什么情況呢?整個程序處于等待狀態,界面似乎是“死”掉了。為了解決這個問題,必須把這個任務放置到單獨線程中運行,避免阻塞UI線程,這樣就不會對主線程有任何影響。舉個例子如下:
private void connect(String strURL){
new Thread() {
public void run() {
try {
HttpClient client = new DefaultHttpClient();
// params[0]代表連接的url
HttpGet get = new HttpGet(url.getText().toString());
HttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
long length = entity.getContentLength();
InputStream is = entity.getContent();
String s = null;
if (is != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[128];
int ch = -1;
int count = 0;
while ((ch = is.read(buf)) != -1) {
baos.write(buf, 0, ch);
count += ch;
}
s = new String(baos.toByteArray());
Log.V(“moandroid sample”,s);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}

使用Handler更新界面

如何將下載的信息顯示在界面上了,比如說下載的進度。Android SDK平臺只允許在主線程中調用相關View的方法來更新界面。如果返回結果在新線程中獲得,那么必須借助Handler來更新界面。為此,在界面Activity中創建一個Handler對象,并在handleMessage()中更新UI。
//Task在另外的線程執行,不能直接在Task中更新UI,因此創建了Handler
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
String m = (String) msg.obj;
message.setText(m);
}
};
只需要將上面的
Log.V(“moandroid sample”,s);
替換為:
s = new String(baos.toByteArray());
Message mg = Message.obtain();
mg.obj = s;
handler.sendMessage(mg);

AsyncTask

看上去修改后的connect()方法已經可用了,但是這種匿名程的方式是存在缺陷的:

  • 線程的開銷較大,如果每個任務都要創建一個線程,那么應用程 序的效率要低很多;
  • 線程無法管理,匿名線程創建并啟動后就不受程序的控制了,如果有很多個請求發送,那么就會啟動非常多的線程,系統將不堪重負。
  • 另外,前面已經看到,在新線程中更新UI還必須要引入handler,這讓代碼看上去非常臃腫。

為了解決這一問題,Android在1.5版本引入了AsyncTask。AsyncTask的特點是任務在主線程之外運行,而回調方法是在主線程中執行,這就有效地避免了使用Handler帶來的麻煩。閱讀AsyncTask的源碼可知,AsyncTask是使用java.util.concurrent 框架來管理線程以及任務的執行的,concurrent框架是一個非常成熟,高效的框架,經過了嚴格的測試。這說明AsyncTask的設計很好的解決了匿名線程存在的問題。
AsyncTask是抽象類,其結構圖如下圖所示:

AsyncTask定義了三種泛型類型 Params,Progress和Result。

  • Params 啟動任務執行的輸入參數,比如HTTP請求的URL。
  • Progress 后臺任務執行的百分比。
  • Result 后臺執行任務最終返回的結果,比如String。

子類必須實現抽象方法doInBackground(Params… p) ,在此方法中實現任務的執行工作,比如連接網絡獲取數據等。通常還應該實現onPostExecute(Result r)方法,因為應用程序關心的結果在此方法中返回。需要注意的是AsyncTask一定要在主線程中創建實例。
AsyncTask的執行分為四個步驟,每一步都對應一個回調方法,需要注意的是這些方法不應該由應用程序調用,開發者需要做的就是實現這些方法。在任務的執行過程中,這些方法被自動調用,運行過程,如下圖所示:

  • onPreExecute() 當任務執行之前開始調用此方法,可以在這里顯示進度對話框。
  • doInBackground(Params…) 此方法在后臺線程執行,完成任務的主要工作,通常需要較長的時間。在執行過程中可以調用publicProgress(Progress…)來更新任務的進度。
  • onProgressUpdate(Progress…) 此方法在主線程執行,用于顯示任務執行的進度。
  • onPostExecute(Result) 此方法在主線程執行,任務執行的結果作為此方法的參數返回。

舉個簡單的例子如下:
// 設置三種類型參數分別為String,Integer,String
class PageTask extends AsyncTask {
// 可變長的輸入參數,與AsyncTask.exucute()對應
@Override
protected String doInBackground(String… params) {
try {
HttpClient client = new DefaultHttpClient();
// params[0]代表連接的url
HttpGet get = new HttpGet(params[0]);
HttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
long length = entity.getContentLength();
InputStream is = entity.getContent();
String s = null;
if (is != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[128];
int ch = -1;
int count = 0;
while ((ch = is.read(buf)) != -1) {
baos.write(buf, 0, ch);
count += ch;
if (length > 0) {
// 如果知道響應的長度,調用publishProgress()更新進度
publishProgress((int) ((count / (float) length) * 100));
}
// 為了在模擬器中清楚地看到進度,讓線程休眠100ms
Thread.sleep(100);
}
s = new String(baos.toByteArray()); }
// 返回結果
return s;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onCancelled() {
super.onCancelled();
}
@Override
protected void onPostExecute(String result) {
// 返回HTML頁面的內容
message.setText(result);
}
@Override
protected void onPreExecute() {
// 任務啟動,可以在這里顯示一個對話框,這里簡單處理
message.setText(R.string.task_started);
}
@Override
protected void onProgressUpdate(Integer… values) {
// 更新進度
message.setText(values[0]);
}
}
執行PageTask非常簡單,只需要調用如下代碼。
PageTask task = new PageTask();
task.execute(url.getText().toString());

總結說明

Handler在前面我們已經學習過,今天突然看到AsyncTask,以及學習其他人的博客基礎上,做出了上面的總結,感覺自己收獲很多,在這里與大家分享。

Android 實現聯網(三) 在線程中聯網


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 91婷婷色涩涩 | 久久天天躁狠狠躁夜夜爽蜜月 | 久色一区| 亚洲福利精品一区二区三区 | 国产成人精品男人的天堂网站 | 波多野结衣一区二区在线 | 久久久久久久久久免观看 | 久久这里只有精品66re99 | 亚洲欧美久久精品一区 | 亚洲精品视频免费看 | 国产全黄a一级毛片 | 一级毛片视频 | 国产91九色在线播放 | 国产高清不卡一区二区三区 | 可以免费观看欧美一级毛片 | 欧美美女xnxx | 久久国产精品亚洲一区二区 | 日韩 欧美 国产 亚洲 中文 | 久久久久免费观看 | 欧美男女视频 | 性成人动作片在线看 | 福利视频欧美一区二区三区 | 欧美国产亚洲一区二区三区 | 4hu四虎永久免在线视看 | 中文字幕有码在线观看 | 中文亚洲字幕 | 四虎影音在线观看 | 日日添日日摸 | 国产色视频在线 | 久久精品30 | 久草在线2 | 99久久精品免费看国产四区 | s8国产成人精品视频 | 国产91一区二这在线播放 | 日韩专区亚洲国产精品 | 亚洲一区二区三区精品国产 | 国产亚洲精品成人一区看片 | 亚洲国产美女精品久久 | 伊人精品在线视频 | 精品久久久久亚洲 | 久久亚洲在线 |