Xamarin.Android开发实践(四)-程序员宅基地

技术标签: ui  json  移动开发  

原文:Xamarin.Android开发实践(四)

Xamarin.Android下获取与解析JSON

一、新建项目

1.新建一个Android项目,并命名为为NetJsonList

 

2.右击引用,选择添加引用,引用System.Json.dll

 

二、同步请求

既然是跨平台,我们自然不能按照java下的方式进行编写,否则如何跨平台呢,所以我们需要使用Syste.Net命名空间下的两个类:HttpWebRequestHttpWebResponse

 

首先打开Resources/layout/Main.axml文件

删除其他上面的控件,并拖拽一个Text(large)到其中。

 

接着打开MainActivity.cs文件,并将如下代码写入其中


 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。

 

最终显示的结果如下所示:

 

但是我们在编码的过程中绝对不能这么做,因为这样会使UI线程阻塞。意思就是用户使用这个app时会出现卡顿,这样对于任何一个人使用者来说都是很难忍受的,所以下面我们要采用异步的方式来实现。

 

三、异步请求

首先我们先把异步请求回调的方法写出来:


 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 }
 

 

 

四、利用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线程的阻塞。

 

五、解析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 }

 

 

六、解决翻转后重复执行

做到这步的可以在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 }

 

 

七、小结

通过上面的学习我们仅仅掌握了在跨平台下最基础的网络访问以及Json数据解析的方法,还有在活动如何保存当前的状态。

posted on 2015-07-25 09:34 NET未来之路 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/4675293.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30654419/article/details/98680365

智能推荐

H.264、H.265相关知识点笔记_x264官网-程序员宅基地

文章浏览阅读1k次。1、x264官网https://www.videolan.org/developers/x264.html2、x264 git仓库git clone https://code.videolan.org/videolan/x264.git3、H264码流的打包方式一种为annex-b byte stream format 的格式,这个是绝大部分编码器的默认输出格式,就是每个帧的开..._x264官网

java8 lambda 视频_一文搞懂Java8 Lambda表达式(附带视频教程)-程序员宅基地

文章浏览阅读268次。Lambda表达式介绍Java 8的一个大亮点是引入Lambda表达式,使用它设计的代码会更加简洁。通过Lambda表达式,可以替代我们以前经常写的匿名内部类来实现接口。Lambda表达式本质是一个匿名函数;体验Lambda表达式我们通过一个小例子来体验下Lambda表达式;我们定义一个计算接口 只有一个方法add;public classProgram {public static voidma..._java8 lambda视频

JavaScript 中的函数式编程实践_javascript 函数式编程实践指南 修言-程序员宅基地

文章浏览阅读248次。JavaScript 中的函数式编程实践函数式编程与 JavaScript基础知识函数式编程简介说到函数式编程,人们的第一印象往往是其学院派,晦涩难懂,大概只有那些蓬头散发,不修边幅,甚至有些神经质的大学教授们才会用的编程方式。这可能在历史上的某个阶段的确如此,但是近来函数式编程已经在实际应用中发挥着巨大作用了,而更有越来越多的语_javascript 函数式编程实践指南 修言

3dMax一键窗户可入库插件使用方法详解_3dmax一键简易窗户插件 easy windows-程序员宅基地

文章浏览阅读851次。3dMax一键窗户(可入库)插件使用教程_3dmax一键简易窗户插件 easy windows

OpenCV的霍夫变换工具HoughLines使用-程序员宅基地

文章浏览阅读560次。输入图像必须是灰度图,并且检测的是白色直线(点对应的灰度为255),而不是黑色直线(点对应的灰度为0)_houghlines

车载以太网新宠SomeIP及其在AutoSAR的应用_autosar sd config-程序员宅基地

文章浏览阅读3.1k次,点赞11次,收藏73次。作者结合自身的工作经验介绍SomeIP协议以及在AutoSAR中的实现。汽车不断智能化和网联化的趋势,使得原本的通讯方式(CAN)不堪重负,因此新的需求带来了新的技术,SomeIP应运而生。1 SomeIP的由来随着汽车智能化和网络化的发展,汽车自动驾驶、车载娱乐、远程诊断升级等新技术对车载通信提出了更高的要求。如何将现有的以太网技术运用到汽车领域是我们面临的一大挑战。而在汽车领域长期都是CAN通信占据主导地位,在汽车中如何找到一种像CAN、MOST一样通信方式,同时支持现有的TCP、UPD协议,又_autosar sd config

随便推点

有效降低传导辐射干扰-程序员宅基地

文章浏览阅读1.5k次。图2显示了一个不带滤波器的输入引线噪声,包括正向噪声和负向噪声,并标注了这些噪声的峰值水平和平均水平。虽然有了这个屏蔽罩,但一些辐射噪声仍然可以绕过EMI滤波器并耦合到PCB上的电源线,这将会导致比图8更差的噪声特性。有趣的是,图4,图8和图9中(相同的布局布线)高频带的噪声特性几乎相同。因此,为了最大限度地提高滤波器的性能,需要移除滤波器周围所有的覆铜,如图6左侧的布线。结论:通常,DM滤波器主要用于滤除小于30MHz的噪声(DM噪声),CM滤波器主要用于滤除30MHz至100MHz的噪声(CM噪声)。

【JAVA】抽象类和接口的联系与区别_java抽象类和接口的联系和区别-程序员宅基地

文章浏览阅读1.3w次,点赞5次,收藏13次。抽象类和接口的联系与区别抽象类与接口一直是面试中问到的一道比较基础的问题,弄懂它们之间的联系与区别,将会提升我们面向对象编程的功底。联系(1)抽象类和接口都不能被实例化。如果要实例化,则抽象类变量必须指向某一个实现其所有抽象方法的子类对象,接口变量必须指向某一个实现其所有抽象方法的实现类对象。..._java抽象类和接口的联系和区别

(前端面试题)css到小程序_showname() function cat() { let showname = functio-程序员宅基地

文章浏览阅读574次。css如何让一个盒子在水平方向和垂直方向都居中flex display:flex;justify-content:center;//水平居中align-items:center;//垂直居中 grid /* 这里引用复用代码 */.outer { display: grid;}.inner { justify-self: center; /* 水平居中 */ align-self: center; /* 垂直居中 */} absolu..._showname() function cat() { let showname = function () {

php提交之前验证数据ajax提示,在Ajax提交之前进行HTML5验证-程序员宅基地

文章浏览阅读72次。这应该很简单,但是却让我发疯。我有一个用ajax提交的html5表单。如果输入的值无效,则会弹出一个提示您的信息。在运行ajax提交之前,如何检查条目是否有效?形成:Name:Subject:Email:Message:提交:$('#submit').click(function(){var name = $("input#name").val();var subject = $("input#s..._php提交之前验证数据ajax提示

JavaWeb——怎样编写一个Servlet程序_javaweb的servlet怎么写-程序员宅基地

文章浏览阅读3.7k次,点赞6次,收藏14次。文章目录JavaWeb——编写一个Servlet程序1.Servlet简介2.HelloServlrt1.建一个普通的Maven项目2.建一个子项目3.Maven环境优化4.编写一个Servlrt程序编写Servlet映射配置Tomcat启动Tomcat服务器测试JavaWeb——编写一个Servlet程序1.Servlet简介Servlet是Sun公司开发的用于交互式地浏览和生成数据,生成动态Web的技术。狭义的Servlet是指Java语言实现的一个接口但一般情况下,我们把实现了S_javaweb的servlet怎么写

icp算法的实现_几种点云配准算法的优劣-程序员宅基地

文章浏览阅读1.8k次。几种点云配准算法的优劣在逆向工程中通过测量仪器得到的产品外观表面的点数据集合也称之为点云,通常使用三维坐标测量机所得到的点数量比较少,点与点的间距也比较大,叫稀疏点云;而使用三维激光扫描仪或照相式扫描仪得到的点云,点数量比较大并且比较密集,叫密集点云。点云配准是计算机视觉的热门研究方向,目前对于刚性点云配准的研究比较全面,对于非刚性点云配准算法的研究相对较弱,总体上来说,ICP、卡尔曼滤..._不同icp配准算法比较

推荐文章

热门文章

相关标签