xamarin android中網絡請求的框架非常多,在項目中使用的是第三方的一個網絡請求框架restsharp,應該是github上.net網絡請求最多star的框架,沒有之一。這里就簡單匯總了其他的一些網絡請求的例子,主要還是分為android和.net兩種平台。.net 中可以使用HttpWebRequest、HttpClient、RestSharp第三框的一些框架,android的有HttpURLConnectin、HttpClient、OkHttp、Retrofit、Volley
下面就用.net中的httpwebrequest、httpclient、restsharp和android中的httpURLConnection、okhttp實現一個get方式獲取圖片、post方式提交表單,適合新手入門看看總結一下。
效果圖如下:
1.HttpWebRquest、HttpWebResponse
命名空間: System.Net;程序集: System(位於 System.dll)
1 public class HttpWebRequestUtil 2 { 3 //發送get請求獲取bytes 4 public static async System.Threading.Tasks.Task<byte[]> GetBytes(string path) 5 { 6 try 7 { 8 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(path); 9 request.Method = "get"; 10 request.Timeout = 500; 11 //request.Proxy設置代理 12 //path 中可添加querystring參數 13 //request.UserAgent 請求的代理 14 HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); 15 if (response.StatusCode == HttpStatusCode.OK) 16 { 17 Stream responseStream = response.GetResponseStream(); 18 //將流轉成字節 19 byte[] bytes = StreamUtil.StreamToBytes(responseStream); 20 return bytes; 21 } 22 else 23 return null; 24 } 25 catch (Exception ex) 26 { 27 return null; 28 } 29 } 30 31 public static async System.Threading.Tasks.Task<bool> PostForm(string path, string name, string pwd) 32 { 33 try 34 { 35 string formData = "name=" + name +"&pwd=" +pwd ; 36 byte[] bytes = Encoding.UTF8.GetBytes(formData); 37 StringBuilder strBuilder = new StringBuilder(); 38 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(path); 39 request.Method = "get"; 40 request.Timeout = 500; 41 request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8"; 42 request.ContentLength = bytes.Length; 43 request.Method = "Post"; 44 Stream requestStream = request.GetRequestStream(); 45 requestStream.Write(bytes, 0, bytes.Length); 46 requestStream.Close(); 47 48 HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); 49 if (response.StatusCode == HttpStatusCode.OK) 50 { 51 StreamReader streamReader = new StreamReader(response.GetResponseStream(), Encoding.UTF8); 52 string content = JsonConvert.DeserializeObject<string>(streamReader.ReadToEnd()); 53 streamReader.Close(); 54 if (content == "success") 55 { 56 return true; 57 } 58 else 59 return false; 60 } 61 return false; 62 } 63 catch (Exception ex) 64 { 65 return false; 66 } 67 } 68 }
2.RestSharp .net常用的http網絡請求庫
當然重點還是說一下這個的。restsharp在github上的star應該是.net網絡請求庫最多的,(和第二名的差距比較大)。可以在nuget上直接添加引用restsharp。
github地址:https://github.com/restsharp/RestSharp
restSharp官網:http://restsharp.org/
stackoverflow上restsharp的相關問題匯總: https://stackoverflow.com/questions/tagged/RestSharp
restsharp有一下這么幾個重要的有點:
- 輕量級的、基於HttpWebRequest的封裝(不依賴任何第三方組件、支持.net 任何平台上)
- 支持異步操作、支持http的get、post、put、delete等操作
- 使用簡單、易調試、request和response的類型齊全
- 功能齊全,支持oAuth 1, oAuth 2, Basic等授權驗證、可上傳文件
- 自定義序列化和反序列化、自動檢測返回的內容類型
1 public class RestSharpUtil 2 { 3 internal static RestClient Instance(string url) 4 { 5 var restClient = new RestClient(url) 6 { 7 Timeout = 5000, 8 ReadWriteTimeout = 5000 9 }; 10 return restClient; 11 } 12 public static async System.Threading.Tasks.Task<bool> Post(string url, User user) 13 { 14 RestClient restClient = Instance(url); 15 RestRequest request = new RestRequest(); 16 //request.AddQueryParameter("id","") 添加url的參數(AddUrlSegment) 17 //request.AddHeader("Authorization","token");添加請求頭參數 18 // request.AddHeader("content-type", "application/x-www-form-urlencoded; charset=UTF-8"); 19 request.AddJsonBody(user); 20 //request.AddParameter("application/x-www-form-urlencoded; charset=UTF-8", user, ParameterType.RequestBody); 21 var response = await restClient.ExecutePostTaskAsync(request); 22 //var response = await restClient.ExecutePostTaskAsync<string>(request); 自動序列化 23 if (response.StatusCode == System.Net.HttpStatusCode.OK) 24 { 25 var result = JsonConvert.DeserializeObject<string>(response.Content); 26 if (result == "success") 27 { 28 return true; 29 } 30 return false; 31 } 32 else 33 { 34 return false; 35 } 36 } 37 public static async System.Threading.Tasks.Task<byte[]> Get(string url) 38 { 39 RestClient restClient = Instance(url); 40 RestRequest request = new RestRequest(); 41 var response = await restClient.ExecuteGetTaskAsync(request); 42 if (response.StatusCode == System.Net.HttpStatusCode.OK) 43 { 44 var bytes = response.RawBytes; 45 return bytes; 46 } 47 return null; 48 } 49 }
post請求和get請求在編碼類型不同,get:僅一種 application/x-www-form-urlencoded,post:application/x-www-form-urlencoded 或 multipart/form-data……等多種編碼方式。
restsharp在發送post請求方式時必須設置header的content-type解碼方式。
request.AddJsonBody(user);等同於:
request.AddParameter(“application/x-www-form-urlencoded; charset=UTF-8”, user, ParameterType.RequestBody);等同於:
request.RequestFormat =DataFormat.Json;
request.AddBody(user);
這里備注一下以前犯的一個錯誤,用了AddBody方法必須添加 request.RequestFormat =DataFormat.Json; ,不然會出異常
我們看看下面的AddBody的源碼可以知道,除restsharp,.net第三方的網絡請求框架還有flurl.http。
1 /// <summary> 2 /// Serializes obj to format specified by RequestFormat, but passes xmlNamespace if using the default XmlSerializer 3 /// The default format is XML. Change RequestFormat if you wish to use a different serialization format. 4 /// </summary> 5 /// <param name="obj">The object to serialize</param> 6 /// <param name="xmlNamespace">The XML namespace to use when serializing</param> 7 /// <returns>This request</returns> 8 public IRestRequest AddBody(object obj, string xmlNamespace) 9 { 10 string serialized; 11 string contentType; 12 13 // TODO: Make it possible to change the serialiser 14 switch (RequestFormat) 15 { 16 case DataFormat.Json: 17 serialized = JsonSerializer.Serialize(obj); 18 contentType = JsonSerializer.ContentType; 19 break; 20 21 case DataFormat.Xml: 22 XmlSerializer.Namespace = xmlNamespace; 23 serialized = XmlSerializer.Serialize(obj); 24 contentType = XmlSerializer.ContentType; 25 break; 26 27 default: 28 serialized = ""; 29 contentType = ""; 30 break; 31 } 32 33 // passing the content type as the parameter name because there can only be 34 // one parameter with ParameterType.RequestBody so name isn't used otherwise 35 // it's a hack, but it works :) 36 return AddParameter(contentType, serialized, ParameterType.RequestBody); 37 } 38 39 /// <summary> 40 /// Serializes obj to data format specified by RequestFormat and adds it to the request body. 41 /// The default format is XML. Change RequestFormat if you wish to use a different serialization format. 42 /// </summary> 43 /// <param name="obj">The object to serialize</param> 44 /// <returns>This request</returns> 45 public IRestRequest AddBody(object obj) 46 { 47 return AddBody(obj, ""); 48 } 49 50 /// <summary> 51 /// Serializes obj to JSON format and adds it to the request body. 52 /// </summary> 53 /// <param name="obj">The object to serialize</param> 54 /// <returns>This request</returns> 55 public IRestRequest AddJsonBody(object obj) 56 { 57 RequestFormat = DataFormat.Json; 58 59 return AddBody(obj, ""); 60 }
3.HttpClient
性能上不如httpwebrequest,用的非常少,據說使用的時候要注意不少,這里只是寫一個簡單的例子,不喜勿噴。
需要添加引用System.Http.Http
1 public class HttpClientUtil 2 { 3 public static async System.Threading.Tasks.Task<byte[]> GetBytes(string path) 4 { 5 HttpClient client = new HttpClient(); 6 try 7 { 8 HttpResponseMessage response = await client.GetAsync(path); 9 if (response.StatusCode == System.Net.HttpStatusCode.OK) 10 { 11 byte[] bytes = await response.Content.ReadAsByteArrayAsync(); 12 return bytes; 13 } 14 return null; 15 } 16 catch (Exception ex) 17 { 18 return null; 19 } 20 finally 21 { 22 client.Dispose(); 23 } 24 } 25 26 public static async System.Threading.Tasks.Task<bool> PostForm(string path, Dictionary<string,string> _params) 27 { 28 29 var handler = new HttpClientHandler() { AutomaticDecompression = System.Net.DecompressionMethods.GZip }; 30 HttpClient client = new HttpClient(); 31 try 32 { 33 client.Timeout = TimeSpan.FromSeconds(5); 34 //HttpContent httpContent = new StringContent(postData); 35 //httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded"); 36 HttpContent httpContent = new FormUrlEncodedContent(_params); 37 var response = await client.PostAsync(path, httpContent); 38 if (response.StatusCode == System.Net.HttpStatusCode.OK) 39 { 40 string result = await response.Content.ReadAsStringAsync(); 41 result = JsonConvert.DeserializeObject<string>(result); 42 if (result == "success") 43 return true; 44 return false; 45 } 46 return false; 47 } 48 catch (Exception ex) 49 { 50 return false; 51 } 52 finally 53 { 54 client.Dispose(); 55 } 56 } 57 }
上面介紹了三種.net方面的網絡請求的方法,下面就來說說android方面的網絡請求HttpUrlConnection、第三方okhttp。
4.HttpURLConnection
httpURLConnection和HttpWebRequest很相似,是java平台上的一種多用途、輕量級的http客戶端,提供的api都非常簡單,這一點也是好處,可以使得我們非常方便去拓展他。下面我們簡單看下如何使用HttpURLConnection。
引用來自:Java.Net
- HttpURLConnection conn = (HttpURLConnection)url.OpenConnection();創建一個URL對象
- conn.ConnectTimeout = 5000; conn.RequestMethod = “get”;設置請求方式和連接超時的時間
- inputStream = conn.InputStream;獲取服務器返回的輸入流
- conn.Disconnect();最后調用disconnect方法將http連接關掉
public class HttpUrlConnecUtil { /// <summary> /// get方式獲取byte 數組 /// </summary> /// <param name="path"></param> /// <returns></returns> public static byte[] getImage(string path) { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection)url.OpenConnection(); conn.ConnectTimeout = 5000; conn.RequestMethod = "GET";//小寫會報錯 System.IO.Stream inputStream=null; try { if (conn.ResponseCode == HttpStatus.Ok) { inputStream = conn.InputStream; return StreamUtil.StreamToBytes(inputStream); } return null; } catch (Exception ex) { return null; } finally { inputStream.Close(); conn.Disconnect(); } } public static string post(string path,string name,string pwd) { string result = string.Empty; HttpURLConnection conn = (HttpURLConnection)new URL(path).OpenConnection(); conn.RequestMethod = "POST"; conn.ReadTimeout = 5000; conn.ConnectTimeout = 5000; //設置運行輸入、輸出 conn.DoOutput = true; conn.DoInput = true; //post 方式不能緩存,需要手動設置false conn.UseCaches = false; string data = "name=" + URLEncoder.Encode(name, "UTF-8") + "&pwd=" + URLEncoder.Encode(pwd,"UTF-8"); Stream outSteam=null; //獲取輸出流 try { outSteam = conn.OutputStream; outSteam.Write(Encoding.UTF8.GetBytes(data), 0, data.Length); outSteam.Flush(); if (conn.ResponseCode == HttpStatus.Ok) { Stream input = conn.InputStream; byte[] bytes = StreamUtil.StreamToBytes(input); result = bytes.ToString(); } return result; } catch (Exception ex) { return ""; } finally { outSteam.Close(); conn.Disconnect(); } } } /// <summary> /// 將流轉成byte數組 /// </summary> /// <param name="stream"></param> /// <param name="bytes"></param> public static byte[] StreamToBytes(Stream stream) { MemoryStream memoryStream = new MemoryStream(); byte[] buffer = new byte[64 * 1024]; int i; try { while ((i = stream.Read(buffer, 0, buffer.Length)) > 0) { memoryStream.Write(buffer, 0, i); } var bytes = memoryStream.ToArray(); return bytes; } catch (Exception ex) { return null; } finally { memoryStream.Close(); stream.Close(); } }
5.OkHttp 最火的android網絡請求框架
okhttp是一個第三方的網絡請求框架,被廣泛適用於android中請求網絡數據,是一個一個輕量級的框架,有移動支付Square公司貢獻(Picasso和LeakCanary),和HttpURLConnection和api是一致的。在xamarin android中使用的時候需要在nuget中添加引用OkHttp,命名空間:using Square.OkHttp3;
okhttp官網:http://square.github.io/okhttp/
github地址:https://github.com/square/okhttp
除了okhttp外,android中比較流行的網絡請求框架還有
retrofit,retrofit2依賴於okhttp;github地址:http://square.github.io/retrofit/,拓展性比較強
volley:google在2013年推出的android異步網絡請求框架和圖片加載框架
下面看看,如何在xamarin android中使用okhttp發送get,post請求吧。
public class OkHttpClientUtil { private OkHttpClient httpClient; public OkHttpClientUtil() { httpClient = new OkHttpClient.Builder() .ConnectTimeout(5, TimeUnit.Seconds)//連接超時5秒 .WriteTimeout(5, TimeUnit.Seconds)//寫入數據超時5秒 .ReadTimeout(5, TimeUnit.Seconds)//讀取數據超時5秒 .Build(); } public static OkHttpClientUtil Instance() { return new OkHttpClientUtil(); } public async System.Threading.Tasks.Task<bool> Post(string url, User user) { FormBody.Builder formBody = new FormBody.Builder(); //創建表單請求體 formBody.Add("name", user.Name); formBody.Add("pwd", user.Pwd); Request request = new Request.Builder().AddHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8").Url(url).Post(formBody.Build()).Build(); var response = await httpClient.NewCall(request).ExecuteAsync(); if (response.Code() == 200) { var result =JsonConvert.DeserializeObject<string>(response.Body().String()); if (result == "success") { return true; } return false; } return false; } public async System.Threading.Tasks.Task<byte[]> Get(string url) { Request request = new Request.Builder().Url(url).Build(); Response response = await httpClient.NewCall(request).ExecuteAsync(); if (response.Code() == 200) { var stream = response.Body().ByteStream(); var bytes = StreamUtil.StreamToBytes(stream); return bytes; } return null; } }