編輯:關於Android編程
本篇文章我們來一起寫一個最基本的Android異步網絡請求框架,借此來了解下Android中網絡請求的相關知識。由於個人水平有限,文中難免存在疏忽和謬誤,希望大家可以指出,謝謝大家。
1. 同步網絡請求
以HTTP的GET請求為例,我們來介紹一下Android中一個基本的同步請求框架的實現。直接貼代碼:
public class HttpUtils { public static byte[] get(String urlString) { HttpURLConnection urlConnection = null; try { URL url = new URL(urlString); urlConnection = (HttpURLConnection) url.openConnection(); //設置請求方法 urlConnection.setRequestMethod("GET"); //設置超時時間 urlConnection.setConnectTimeout(5000); urlConnection.setReadTimeout(3000); //獲取響應的狀態碼 int responseCode = urlConnection.getResponseCode(); if (responseCode == 200) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); InputStream in = urlConnection.getInputStream(); byte[] buffer = new byte[4 * 1024]; int len = -1; while((len = in.read(buffer)) != -1) { bos.write(buffer, 0, len); } close(in); byte[] result = bos.toByteArray(); close(bos); return result; } else { return null; } } catch (Exception e) { e.printStackTrace(); } finally { if (urlConnection != null) { urlConnection.disconnect(); } } return null; } private static void close(Closeable stream) { if (stream != null) { try { stream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
相信以上的代碼我們大家都不陌生,以上代碼就實現了基本的同步網絡請求功能,get 方法會返回一個byte[]數組,後續我們可以根據返回的相應類型(文本或圖片)對這個字節數組作進一步處理。
2. 異步網絡請求
通常一個異步HTTP GET請求是這樣的:發出get方法的調用後,相關任務會在後台線程中自動執行,而我們在主線程中繼續處理其他工作,它成功獲取GET請求的響應時,就會回調onSuccess方法。最直接的寫法通常如下所示:
public class AsyncHttpUtils {public static byte[] get(String url, ResponseHandler handler) { final Handler mHandler = new Handler(); new Thread(new Runnable() { @Override public void run() { final byte[] result = HttpUtils.get(url); handler.post(new Runnable() { @Override public void run() { responseHandler.onSuccess(result); } }); } }); } }
其中,ResponseHandler接口的定義如下:
public interface ResponseHandler { void onSucess(bytep[] result); }
我們可以看到,以上實現異步GET請求的代碼很直截了當,然而存在著以下問題:每次請求時都會創建一個線程,這樣當請求比較頻繁的情況下會創建大量大線程,這樣的話創建、銷毀線程以及線程調度的開銷會很大。而且Thread對象是一個匿名內部類對象,會隱式持有外圍類引用,可能會引起Memory Leak。
針對以上問題,我們可以使用線程池來復用線程,以避免不必要的創建及銷毀線程的開銷,改進後AsyncHttpUtils類的代碼如下:
public class AsyncHttpUtils { //獲取當前設備的CPU數 public static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); //核心池大小設為CPU數加1 private static final int CORE_POOL_SIZE = CPU_COUNT + 1; //設置線程池的最大大小 private static final int MAX_POOL_SIZE = 2 * CPU_COUNT + 1; //存活時間 private static final long KEEP_ALIVE = 5L; //創建線程池對象 public static final Executor threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); public static void get(final String url, final ResponseHandler responseHandler) { final Handler mHandler = new Handler(Looper.getMainLooper()); //創建一個新的請求任務 Runnable requestRunnable = new Runnable() { @Override public void run() { final byte[] result = HttpUtils.get(url); if (result != null) { mHandler.post(new Runnable() { @Override public void run() { //result不為空表明請求成功,回調onSuccess方法 responseHandler.onSuccess(result); } }); } } }; threadPoolExecutor.execute(requestRunnable); } }
以上代碼主要就是使用了線程池來達到線程的復用的目的,希望本文所述對大家學習Android軟件編程有所幫助。
一、概述運行時變更就是設備在運行時發生變化(例如屏幕旋轉、鍵盤可用性及語言)。發生這些變化,Android會重啟Activity,這時就需要保存activity的狀態及與
簡介:Xposed框架是一款可以在不修改APK的情況下影響程序運行的框架服務,通過替換/system/bin/app_process程序控制zygote進程,使得app
一、概述今天給大家帶來SurfaceView的一個實戰案例,話說自定義View也是各種寫,一直沒有寫過SurfaceView,這個玩意是什麼東西?什麼時候用比較好呢?可以
今天這一篇小案例模擬模糊查詢,即輸入一個字符,顯示手機對應的所有存在該字符的路徑。布局: