天天看點

xamarin android網絡請求總結

xamarin android中網絡請求的架構非常多,在項目中使用的是第三方的一個網絡請求架構restsharp,應該是github上.net網絡請求最多star的架構,沒有之一。這裡就簡單彙總了其他的一些網絡請求的例子,主要還是分為android和.net兩種平台。.net 中可以使用HttpWebRequest、HttpClient、RestSharp第三框的一些架構,android的有HttpURLConnectin、HttpClient、OkHttp、Retrofit、Volley
xamarin android網絡請求總結

下面就用.net中的httpwebrequest、httpclient、restsharp和android中的httpURLConnection、okhttp實作一個get方式擷取圖檔、post方式送出表單,适合新手入門看看總結一下。 

效果圖如下: 

xamarin android網絡請求總結

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有一下這麼幾個重要的有點:

  1. 輕量級的、基于HttpWebRequest的封裝(不依賴任何第三方元件、支援.net 任何平台上)
  2. 支援異步操作、支援http的get、post、put、delete等操作
  3. 使用簡單、易調試、request和response的類型齊全
  4. 功能齊全,支援oAuth 1, oAuth 2, Basic等授權驗證、可上傳檔案
  5. 自定義序列化和反序列化、自動檢測傳回的内容類型
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

  1. HttpURLConnection conn = (HttpURLConnection)url.OpenConnection();建立一個URL對象
  2. conn.ConnectTimeout = 5000; conn.RequestMethod = “get”;設定請求方式和連接配接逾時的時間
  3. inputStream = conn.InputStream;擷取伺服器傳回的輸入流
  4. 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/ 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;
        }
    }      

繼續閱讀