一切搞定,以為高枕無憂了,結果還是有問題!
log開始報錯了,獲取更新信息異常!!!debug一下,發現Exception:android.os.NetworkOnMainThreadException
這個異常大概意思是在主線程訪問網絡時出的異常。 Android在4.0之前的版本 支持在主線程中訪問網絡,但是在4.0以后對這部分程序進行了優化,也就是說訪問網絡的代碼不能寫在主線程中了。
查看網上的解決方法,在Android中實現異步任務機制有兩種方式,Handler和AsyncTask。
> Handler模式需要為每一個任務創建一個新的線程,任務完成后通過Handler實例向UI線程發送消息,完成界面的更新,這種方式對于整個過程的控制比較精細,但也是有缺點的,例如代碼相對臃腫,在多個任務同時執行時,不易對線程進行精確的控制。
為了簡化操作,Android1.5提供了工具類android.os.AsyncTask,它使創建異步任務變得更加簡單,不再需要編寫任務線程和Handler實例即可完成相同的任務。
這里我們采用AsyncTask的處理方式。
### 先來看看AsyncTask的定義:
public abstract class AsyncTask<Params, Progress, Result> {
三種泛型類型分別代表“啟動任務執行的輸入參數”、“后臺任務執行的進度”、“后臺計算結果的類型”。在特定場合下,并不是所有類型都被使用,如果沒有被使用,可以用java.lang.Void類型代替。
### AsyncTask的執行分為四個步驟
每一步都對應一個回調方法,這些方法不應該由應用程序調用,開發者需要做的就是實現這些方法。
1) 子類化AsyncTask
2) 實現AsyncTask中定義的下面一個或幾個方法
onPreExecute(), 該方法將在執行實際的后臺操作前被UI thread調用。可以在該方法中做一些準備工作,如在界面上顯示一個進度條。
doInBackground(Params...), 將在onPreExecute 方法執行后馬上執行,該方法運行在后臺線程中。這里將主要負責執行那些很耗時的后臺計算工作。可以調用 publishProgress方法來更新實時的任務進度。該方法是抽象方法,子類必須實現。
onProgressUpdate(Progress...),在publishProgress方法被調用后,UI thread將調用這個方法從而在界面上展示任務的進展情況,例如通過一個進度條進行展示。
onPostExecute(Result), 在doInBackground 執行完成后,onPostExecute 方法將被UI thread調用,后臺的計算結果將通過該方法傳遞到UI thread.
### 為了正確的使用AsyncTask類,以下是幾條必須遵守的準則:
1) Task的實例必須在UI thread中創建
2) execute方法必須在UI thread中調用
3) 不要手動的調用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)這幾個方法
4) 該task只能被執行一次,否則多次調用時將會出現異常
doInBackground方法和onPostExecute的參數必須對應,這兩個參數在AsyncTask聲明的泛型參數列表中指定,第一個為 doInBackground接受的參數,第二個為顯示進度的參數,第第三個為doInBackground返回和onPostExecute傳入的參數。
### 下面是項目中具體的處理方法:
~~~
package com.liuhao.mobilesafe.engine;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.content.Context;
import android.os.AsyncTask;
import com.liuhao.mobilesafe.domain.UpdateInfo;
public class UpdateInfoService {
private Context context; //應用程序環境的上下文信息
public UpdateInfoService(Context context) {
this.context = context;
}
// 將與網絡通信的過程封裝在ServiceInBackGround的doInBackground方法中
private class ServiceInBackGround extends AsyncTask<Integer, Void, UpdateInfo>{
@Override
protected UpdateInfo doInBackground(Integer... params) {
String path = context.getResources().getString(params[0]); //根據urlId獲取資源文件中對應的內容
UpdateInfo info = new UpdateInfo();
URL url;
try {
url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(20000);
conn.setRequestMethod("GET");
InputStream is = conn.getInputStream(); //得到url對應的文件流,應該是xml文件流,需要對其進行解析
info = UpdateInfoParser.getUpdateInfo(is); //對xml文件流進行解析,獲取到更新信息實體
} catch (Exception e) {
e.printStackTrace();
}
return info;
}
@Override
protected void onPostExecute(UpdateInfo result) {
super.onPostExecute(result);
}
}
/**
* @param urlId
* 服務器資源路徑對應的id
* @return 更新信息
* @throws Exception
*/
public UpdateInfo getUpdateInfo(int urlId) throws Exception {
// new serviceInBackGround().execute(urlId).get();
return new ServiceInBackGround().execute(urlId).get();
}
}
~~~
最后需要說明AsyncTask不能完全取代線程,在一些邏輯較為復雜或者需要在后臺反復執行的邏輯就可能需要線程來實現了。
異常都解決后,再次運行程序:
點擊進入程序,會彈出升級對話框:
[](http://img.blog.csdn.net/20140928161730904)
查看日志:
[](http://img.blog.csdn.net/20140928161552828)
用戶點擊確定:
[](http://img.blog.csdn.net/20140928161553718)
點擊取消:
[](http://img.blog.csdn.net/20140928161733680)
參考:
[http://www.cnblogs.com/dawei/archive/2011/04/18/2019903.html](http://www.cnblogs.com/dawei/archive/2011/04/18/2019903.html "http://www.cnblogs.com/dawei/archive/2011/04/18/2019903.html")
[http://daoshud1.iteye.com/blog/1843655](http://daoshud1.iteye.com/blog/1843655 "http://daoshud1.iteye.com/blog/1843655")
- 前言
- Appcompat_V7問題
- This Android SDK requires Android Developer Toolkit version 23.0.0 or above
- 創建Android項目不自動生成Activity,layout目錄為空
- 新建android項目gen目錄下未生成R文件
- 手機安全衛士02:splash界面ui
- 知識點:Android控件系列之Toast
- 手機安全衛士03:獲取更新的服務器配置,顯示更新對話框
- 異常處理:android.os.NetworkOnMainThreadException--多線程問題
- 知識點:Android控件系列之對話框AlertDialog.Builder
- 手機安全衛士04_01:界面(Activity)之間的切換,Activity和任務棧
- 知識點:Android控件系列之ProgressDialog與ProgressBar
- 手機安全衛士04_02:從服務器下載并安裝新版本安裝包
- 知識點:Intent
- 知識點:Adapter適配器
- 手機安全衛士05_1:程序主界面
- 手機安全衛士05_2:程序主界面,為每個條目添加事件
- 知識點:動態設置布局LayoutInflater
- 知識點:SharedPreferences
- 手機安全衛士06-手機防盜之自定義對話框
- 手機安全衛士07-手機防盜之進入限制
- 手機安全衛士08-一些布局和顯示的細節:State List
- 手機安全衛士09-手機防盜界面設置向導1
- 手機安全衛士10-設置向導之綁定SIM卡