編輯:關於Android編程
Android是一個單線程模型,Android界面(UI)的繪制都只能在主線程中進行,如果在主線程中進行耗時的操作,就會影響UI的繪制和事件的響應。所以在android規定,不可在主線中進行耗時操作,否則將發生程序無響應(ANR)問題。
解決辦法:開啟新的線程進行耗時操作
開啟新的線程可以new Thread() 或實現Runnable接口
什麼要使用AsyncTask呢?
如果是使用Thread的run()方法,run()結束之後沒有返回值。所以必須要自己建立通信機制
AsyncTask將所有的線程通信都封裝成回調函數,調用邏輯容易書寫。尤其是在異步處理結束之後,有回調函數進行收尾處理。咳咳,程序員都懶的麼
Android給我們提供的一個輕量級的用於處理異步任務的類:AsyncTask 當然是那個簡單就用那個咯
最後還有一點就是:Android 4.0後禁止在UI線程中執行網絡操作~不然會報:android.os.NetworkOnMainThreadException
什麼是AsyncTask(原諒寶寶偷的圖 嘿嘿 不過真的解釋的很清楚呢)
注意:
Task的實例必須在UI Thread中創建
execute方法不惜在UI thread中創建
task只能被執行一次 多次調用時會出現異常
通用AsyncTask 以及在主線程中使用網絡請求回返的數據
通用AsyncTask是什麼意思呢 發送不同的請求返回不同類型的數據 難道要一個類型寫個AsyncTask 豈不是麻煩死咯
還有一種情況 我們通過異步任務得到了一個對象然後在一下行立刻使用這個對象邏輯完全沒問題但是運行之後會報空指針異常。這是怎麼回事呢?
AsycnTask開始了一個新的線程,但是主線程並沒有停止還在繼續運行,馬上就使用這個對象,而你新開的線程可能正在訪問網絡這個對象為空
你無法確定AsycnTask什麼時候才能獲取到數據,網快嗖的一下就好了,網慢就要等好久。
看一個簡略的小例子
首先呢 我們使用異步任務的時候要處理不同類型的數據把這個Http設置泛型類第三個參數返回值類型設置為泛型不管你是什麼類型的數據全部ok
我又寫了一個接口作為Http的屬性 在onPostExecute方法調用其中的onResponse方法在Test中實現接口
這個接口的作用完全可以理解為一個監聽事件 checkbox的改變監聽觸發條件是 是否選中這個接口監聽是否有數據 完成網絡訪問有數據的時候就調用
我們在主線程中完成接口的實現已經在主線程中實現了返回來的數據還不是任君宰割阿~~~~~
public class Http<T> extends AsyncTask<String,Void,T> { private OnResponseListener<T> listener; public void setListener(OnResponseListener<T> listener) { this.listener = listener; } @Override protected T doInBackground(String... params) { return null; } @Override protected void onPostExecute(T t) { super.onPostExecute(t); if (listener!=null){ listener.onResponse(t); } } //接口 類似一個監聽事件 public interface OnResponseListener<T>{ void onResponse(T t); } } //獲取數據的測試類 public class Test { //要獲取的user對象 private User user1=null; public void get(){ //創建網絡訪問實例 Http<User> http=new Http<User>(); //重寫接口 http.setListener(new Http.OnResponseListener<User>() { @Override public void onResponse(User user) { user1=user; } }); http.execute("xxx.balabala.com"); } }
在發送請求的時候很容易就帶個參數,請求的方式呢 無非就是get,post 兩者的區別呢大白話的說get不安全參數通過url直接傳過去post安全參數加密一下子
下面貼一下AsyncTask在get和post請求時核心代碼doInBackground方法
GET
protected T doInBackground(String... params) { //網絡連接對象 HttpURLConnection connection=null; //輸入流 獲取網絡數據 InputStream is=null; //字節數組輸出流 ByteArrayOutputStream bos=null; try { //獲取網絡連接對象 connection=(HttpURLConnection) new URL(params[0]).openConnection(); //設置get請求 必須大寫 connection.setRequestMethod("GET"); //獲取網絡請求碼 200 400 500之類 不懂百度 int code=connection.getResponseCode(); if(code==200){ //獲取流 is=connection.getInputStream(); //臨時字節數組 byte [] b=new byte[1024]; int len=-1; bos=new ByteArrayOutputStream(); while ((len=is.read(b))!=-1){ //寫入數據 bos.write(b,0,len); } String json=bos.toString("utf-8"); T t=JSON.parseObject(json,type); return t; }else{ Log.e("error","網絡訪問失敗==========="+code); } } catch (IOException e) { e.printStackTrace(); }finally { try { if (bos!=null){ bos.close(); } if (is!=null){ is.close(); } } catch (IOException e) { e.printStackTrace(); } if (connection!=null){ connection.disconnect(); } } return null; }
POST
post和get的區別 就是post多了一段處理參數的代碼
protected T doInBackground(String... params) { //分割url 分為地址和參數兩部分 String[] strArr=params[0].split("\\?"); HttpURLConnection connection=null; //輸出流 OutputStream os=null; //輸入流 InputStream is=null; ByteArrayOutputStream bos=null; try { connection=(HttpURLConnection) new URL(strArr[0]).openConnection(); connection.setRequestMethod("POST"); //設置允許輸入 輸出 默認值true 不寫也可以 connection.setDoOutput(true); connection.setDoInput(true); os=connection.getOutputStream(); //把參數寫入 os.write(strArr[1].getBytes("utf-8")); os.close(); int code=connection.getResponseCode(); if(code==200){ is=connection.getInputStream(); byte [] b=new byte[1024]; int len=-1; bos=new ByteArrayOutputStream(); while ((len=is.read(b))!=-1){ bos.write(b,0,len); } String json=bos.toString("utf-8"); T t=JSON.parseObject(json,type); return t; }else{ Log.e("error","網絡訪問失敗==========="+code); } } catch (IOException e) { e.printStackTrace(); }finally { try { if (bos!=null){ bos.close(); } if (is!=null){ is.close(); } } catch (IOException e) { e.printStackTrace(); } if (connection!=null){ connection.disconnect(); } } return null; }
以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持本站!
前面寫過了使用ViewFlipper和ViewPager實現屏幕中視圖切換的效果(ViewPager未實現輪播)附鏈接:ANDROID中使用VIEWFLIPPER類實現屏
本文轉載於 huachao1001的專欄相信大家都曾經下定決心把23種設計模式牢記於心,每次看完之後過一段時間又忘記了~,又得回去看,腦子裡唯一依稀記得的是少
最近幫朋友做了一個動畫菜單,感覺有一定的實用價值,就在此給大家分享一下,先看看效果:實現思路:從圖中可以看出,這三個(或更多,需要自己再實現)菜單是圍繞著中心點旋轉的,旋
今天花了整個下午+晚上的的時間學習了Activity的啟動模式,本來以為這個知識點很簡單,但是在學習的過程中發現,Activity的啟動模式並沒有