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数据解析的方法,还有在活动如何保存当前的状态。

相关文章
相关标签/搜索