Xamarin.Android開發實踐(四)

原文:Xamarin.Android開發實踐(四)html

Xamarin.Android下獲取與解析JSON

1、新建項目

1.新建一個Android項目,並命名爲爲NetJsonListjava

 

2.右擊引用,選擇添加引用,引用System.Json.dlljson

 

2、同步請求

既然是跨平臺,咱們天然不能按照java下的方式進行編寫,不然如何跨平臺呢,因此咱們須要使用Syste.Net命名空間下的兩個類:HttpWebRequestHttpWebResponsec#

 

首先打開Resources/layout/Main.axml文件數組

刪除其餘上面的控件,並拖拽一個Text(large)到其中。網絡

 

接着打開MainActivity.cs文件,並將以下代碼寫入其中app


 1 namespace NetJsonList  2 {  3 [Activity(Label = "NetJsonList", MainLauncher = true, Icon = "@drawable/icon")]  4 public class MainActivity : Activity  5  {  6  TextView tv;  7  8 protected override void OnCreate(Bundle bundle)  9  { 10 base.OnCreate(bundle); 11  SetContentView(Resource.Layout.Main); 12 13 tv = FindViewById<TextView>(Resource.Id.textView1); 14 15  LoadXamarin(); 16  } 17 18 public void LoadXamarin() 19  { 20 //測試用 21 string url = "http://www.xamarin-cn.com/test.json"; 22 23 //建立一個請求 24 var httpReq = (HttpWebRequest)HttpWebRequest.Create(new Uri(url)); 25 26 //獲取響應 27 var httpRes = (HttpWebResponse)httpReq.GetResponse(); 28 29 //讀取響應的字符串 30 String text = new StreamReader(httpRes.GetResponseStream()).ReadToEnd(); 31 tv.Text = text; 32  } 33  } 34 }

 

 

這裏咱們經過HttpWebRequestCreate靜態方法建立了一個請求,那麼下面咱們能夠獲取響應了,筆者這裏直接使用StreamReader讀取了,以便顯示出來。異步

 

注:若是要在在短期內高頻率的使用HTTP請改用HttpURLConnection。async

 

最終顯示的結果以下所示:ide

 

可是咱們在編碼的過程當中絕對不能這麼作,由於這樣會使UI線程阻塞。意思就是用戶使用這個app時會出現卡頓,這樣對於任何一我的使用者來講都是很難忍受的,因此下面咱們要採用異步的方式來實現。

 

3、異步請求

首先咱們先把異步請求回調的方法寫出來:


 1         //異步回調方法  2 public void ReadXamarin(IAsyncResult asyn)  3  {  4 var httpReq = (HttpWebRequest)asyn.AsyncState;  5  6 //獲取響應  7 using (var httpRes = (HttpWebResponse)httpReq.EndGetResponse(asyn))  8  {  9 //判斷是否成功獲取響應 10 if (httpRes.StatusCode == HttpStatusCode.OK) 11  { 12 //讀取響應 13 var text = new StreamReader(httpRes.GetResponseStream()).ReadToEnd(); 14 15 //切換到UI線程,不然沒法對控件進行操做 16 RunOnUiThread(() => 17  { 18 tv.Text = text; 19  }); 20  } 21  } 22 }
 

 

 

經過AsyncState獲取HttpWebRequest的引用,而後再調用其EndGetResponse方法獲取響應,並將響應的字符串顯示,特別須要注意的是咱們這裏使用了RunOnUiThread方法,由於異步回調的方法不是使用UI線程執行的,這也是爲何這樣作就不會阻塞UI線程了。

 

固然有了異步操做的回調方法,天然在調用的時候須要使用特殊的方法:


1         public void LoadXamarin() 2  { 3 //測試用 4 string url = "http://www.xamarin-cn.com/test.json"; 5 6 //建立一個請求 7 var httpReq = (HttpWebRequest)HttpWebRequest.Create(new Uri(url)); 8 httpReq.BeginGetResponse(new AsyncCallback(ReadXamarin), httpReq); 9 }
 

 

 

全部的代碼以下所示:


 1 namespace NetJsonList  2 {  3 [Activity(Label = "NetJsonList", MainLauncher = true, Icon = "@drawable/icon")]  4 public class MainActivity : Activity  5  {  6  TextView tv;  7  8 protected override void OnCreate(Bundle bundle)  9  { 10 base.OnCreate(bundle); 11  SetContentView(Resource.Layout.Main); 12 13 tv = FindViewById<TextView>(Resource.Id.textView1); 14 15  LoadXamarin(); 16  } 17 18 public void LoadXamarin() 19  { 20 //測試用 21 string url = "http://www.xamarin-cn.com/test.json"; 22 23 //建立一個請求 24 var httpReq = (HttpWebRequest)HttpWebRequest.Create(new Uri(url)); 25 httpReq.BeginGetResponse(new AsyncCallback(ReadXamarin), httpReq); 26  } 27 28 //異步回調方法 29 public void ReadXamarin(IAsyncResult asyn) 30  { 31 var httpReq = (HttpWebRequest)asyn.AsyncState; 32 33 //獲取響應 34 using (var httpRes = (HttpWebResponse)httpReq.EndGetResponse(asyn)) 35  { 36 //判斷是否成功獲取響應 37 if (httpRes.StatusCode == HttpStatusCode.OK) 38  { 39 //讀取響應 40 var text = new StreamReader(httpRes.GetResponseStream()).ReadToEnd(); 41 42 //切換到UI線程,不然沒法對控件進行操做 43 RunOnUiThread(() => 44  { 45 tv.Text = text; 46  }); 47  } 48  } 49  } 50  } 51 }
 

 

 

4、利用await的異步請求

經過c# 5.0 的新特性await咱們能夠寫更少的代碼實現異步,咱們修改LoadXamarin方法:


 1         public async void LoadXamarin()  2  {  3 //測試用  4 string url = "http://www.xamarin-cn.com/test.json";  5  6 //建立一個請求  7 var httpReq = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));  8 var httpRes = (HttpWebResponse)await httpReq.GetResponseAsync();  9 if (httpRes.StatusCode == HttpStatusCode.OK) 10  { 11 var text = new StreamReader(httpRes.GetResponseStream()).ReadToEnd(); 12 tv.Text = text; 13  } 14 }
 

 

 

能夠看到咱們給這個方法加了一個async關鍵字,若是不加這個關鍵字,在該方法中是沒法使用await的,下面咱們就看到了這句代碼:

1 var httpRes = (HttpWebResponse)await httpReq.GetResponseAsync();

 

 

當Ui線程執行到這句後,直接就會跳過去,不會等待。固然下面的方法也不會去執行了,只有當這個方法返回告終果以後,UI線程纔會回到這句代碼,並繼續執行下面的方法。固然這些只是障眼法,其實c#已經把下面的代碼做爲了異步回調執行的方法了:

1             if (httpRes.StatusCode == HttpStatusCode.OK) 2  { 3 var text = new StreamReader(httpRes.GetResponseStream()).ReadToEnd(); 4 tv.Text = text; 5 }

 

 

而且執行的線程依然是以前執行該方法的線程,若是你建立一個新的線程去執行。那麼就必須使用RunOnUiThread方法了。還有一個缺點就是不能在其中進行復雜的運算,不然仍是會形成UI線程的阻塞。

 

5、解析JSON

在開始本節前,必須確保引用了正確的System.Json類庫,不然沒法使用。

 

首先咱們先看看json數據的格式:

1 { 2 "T": [ 3 "T1", 4 "T2", 5 "T3", 6 "T4" 7  ] 8 }

 

 

知道了json數據格式了,咱們還要理解下System.Json中有哪些類:

JsonValue:是基礎類,表明一個Json值

JsonObject:繼承JsonValue,表明一個Json對象

JsonArray:繼承JsonValue,表明一個Json數組

JsonPrimitive:繼承JsonValue,組織Json數據時用

JsonType:枚舉,區分是什麼類型

 

而咱們今天只須要使用到JsonObjectJsonArray,首先是JsonObject表明整個Json對象,咱們能夠經過它的靜態方法Load直接讀取流,好比下面的方式:

1 var text = JsonObject.Load(httpRes.GetResponseStream());

 

 

可是Load返回的是JsonValue,可是大多數狀況都是表明一個Json對象,因此咱們須要將它強制轉換成JsonObject類型,這樣咱們就能夠讀取其中的T了:

1                 var text = (JsonObject)JsonObject.Load(httpRes.GetResponseStream()); 2 var array = (JsonArray)text["T"];

 

 

固然咱們還須要使用Linq讀取這個數組(注意要using System.Linq命名空間

1                 var text = (JsonObject)JsonObject.Load(httpRes.GetResponseStream()); 2 var result = (from item in (JsonArray)text["T"] 3 select item.ToString()).ToArray();

 

 

這樣咱們獲取了一個字符串組了,result類型爲string[]。爲了顯示這個數組,咱們須要將當前的活動繼承自ListActivity:

 

而後將代碼修改爲以下所示:


 1 namespace NetJsonList  2 {  3 [Activity(Label = "NetJsonList", MainLauncher = true, Icon = "@drawable/icon")]  4 public class MainActivity : ListActivity  5  {  6 protected override void OnCreate(Bundle bundle)  7  {  8 base.OnCreate(bundle);  9  LoadXamarin(); 10  } 11 12 public async void LoadXamarin() 13  { 14 //測試用 15 string url = "http://www.xamarin-cn.com/test.json"; 16 17 //建立一個請求 18 var httpReq = (HttpWebRequest)HttpWebRequest.Create(new Uri(url)); 19 var httpRes = (HttpWebResponse)await httpReq.GetResponseAsync(); 20 if (httpRes.StatusCode == HttpStatusCode.OK) 21  { 22 var text = (JsonObject)JsonObject.Load(httpRes.GetResponseStream()); 23 var result = (from item in (JsonArray)text["T"] 24 select item.ToString()).ToArray(); 25 ListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, result); 26  } 27  } 28  } 29 }

 

 

6、解決翻轉後重復執行

作到這步的能夠在LoadXamarin中下一個斷點,當你點擊模擬器並按下Ctrl+F12翻轉後你會發現LoadXamarin又從新執行了一次。這樣就帶來了一個問題,有時候咱們僅僅只須要第一次獲取便可,該翻轉則會致使重複執行,那麼就會浪費用戶的流量同時也會浪費資源,因此咱們這裏就須要可以將這種狀態維持,這裏咱們就須要重寫OnRetainNonConfigurationInstance事件,固然該方法須要返回一個Java.Lang.Object類型的返回值,而這個返回值就是咱們須要保存的狀態,固然這個狀態不會存在於OnCreate的bundle中,仍是有一個專門的屬性LastNonConfigurationInstance,這樣咱們能夠將上面的代碼改寫成以下:

 1 namespace NetJsonList  2 {  3 [Activity(Label = "NetJsonList", MainLauncher = true, Icon = "@drawable/icon")]  4 public class MainActivity : ListActivity  5  {  6 class Test : Java.Lang.Object  7  {  8 public string[] Results { get; set; }  9  } 10 11  Test t; 12 13 protected override void OnCreate(Bundle bundle) 14  { 15 base.OnCreate(bundle); 16  LoadXamarin(); 17  } 18 19 //重寫該方法 20 public override Java.Lang.Object OnRetainNonConfigurationInstance() 21  { 22 return t; 23  } 24 25 public async void LoadXamarin() 26  { 27 t = LastNonConfigurationInstance as Test; 28 //判斷是否存在以前的狀態 29 if (t != null) 30  { 31 ListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, t.Results); 32  } 33 else 34  { 35 36 //測試用 37 string url = "http://www.xamarin-cn.com/test.json"; 38 39 //建立一個請求 40 var httpReq = (HttpWebRequest)HttpWebRequest.Create(new Uri(url)); 41 var httpRes = (HttpWebResponse)await httpReq.GetResponseAsync(); 42 if (httpRes.StatusCode == HttpStatusCode.OK) 43  { 44 var text = (JsonObject)JsonObject.Load(httpRes.GetResponseStream()); 45 var result = (from item in (JsonArray)text["T"] 46 select item.ToString()).ToArray(); 47 t = new Test() 48  { 49 Results = result 50  }; 51 ListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, result); 52  } 53  } 54  } 55  } 56 }

 

 

7、小結

經過上面的學習咱們僅僅掌握了在跨平臺下最基礎的網絡訪問以及Json數據解析的方法,還有在活動如何保存當前的狀態。

相關文章
相關標籤/搜索