Xamarin.Android开发实践(四)
Xamarin.Android下获取与解析JSON
一、新建项目
1.新建一个Android项目,并命名为为NetJsonList
2.右击引用,选择添加引用,引用System.Json.dll
二、同步请求
既然是跨平台,我们自然不能按照java下的方式进行编写,否则如何跨平台呢,所以我们需要使用Syste.Net命名空间下的两个类:HttpWebRequest和HttpWebResponse。
首先打开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 }
这里我们通过HttpWebRequest的Create静态方法创建了一个请求,那么下面我们可以获取响应了,笔者这里直接使用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:枚举,区分是什么类型
而我们今天只需要使用到JsonObject和JsonArray,首先是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数据解析的方法,还有在活动如何保存当前的状态。
转载于:https://www.cnblogs.com/ShaYeBlog/p/4615574.html
Xamarin.Android开发实践(四)相关推荐
- Xamarin.Android开发实践(十四)
原文:Xamarin.Android开发实践(十四) Xamarin.Android之ListView和Adapter 一.前言 如今不管任何应用都能够看到列表的存在,而本章我们将学习如何使用Xama ...
- Xamarin.Android开发实践(十七)
Xamarin.Android开发实践(十七) 原文:Xamarin.Android开发实践(十七) Xamarin.Android之定位 一.前言 打开我们手中的应用,可以发现越来越多的应用使用了定 ...
- Xamarin.Android开发实践(一)
原文:Xamarin.Android开发实践(一) 一.准备工作 1.创建一个空的解决方案,并命名为Phoneword 2.右击解决方案 新建->新建项目 并命名为Phoneword_Droid ...
- Xamarin.Android开发实践(十八)
Xamarin.Android之SlidingMenu 一.前言 有位网友在评论中希望能够出个在Xamarin.Android下实现SlidingMenu效果的随笔,刚好昨天在观看官网示例项目的时候也 ...
- Android开发实践:Java层与Jni层的数组传递
Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是Java层把需要发送给客户端的数据流传递到Jni层,由Jni层的Socket代码发送出去,当然,Jni ...
- Xamarin.Android开发及常见问题的解决
一.Xamarin.Android开发环境的搭建 (一)所需组件 1.VS2013(VS2010以上即可) 2.JDK(http://www.oracle.com/technetwork/java/j ...
- Xamarin Android开发实战(上册)
Xamarin Android开发实战(上册)大学霸内部资料 试读文档下载地址:http://pan.baidu.com/s/1jGEHhhO 密码:vcfm 介绍: 本教程是国内唯一的Xamarin ...
- xamarin Android 开发 文件“obj\Debug\android\bin\packaged_resources”不存在
严重性 代码 说明 项目 文件 行 禁止显示状态 错误 文件"obj\Debug\android\bin\packaged_resources"不存在. AndroidTest 各 ...
- android并发命令,Android开发实践:基于命令模式的异步任务线程
关于Android的异步操作,我在文章<Android开发实践:线程与异步任务>中介绍了两种方法,一种是采用线程,另一种是采用AsyncTask,今天再深入探讨下另一种模型:命令式的异步任 ...
最新文章
- JVM调优:基本垃圾回收算法
- 【有图有真相】静态NAT、动态NAT、PAT、端口映射的详细配置过程
- 2011寒假-joomla学习笔记
- 解决方案:用户 'sa' 登录失败。原因: 未与信任 SQL Server 连接相关联。
- linux内核源码剖析 博客,【Linux内存源码分析】页面迁移
- 第一章 QT Creator 简介
- Flink-1.13集成hudi-0.10.0
- Android 和 iOS 各有千秋
- 跟我一起来用C++写Web服务器吧
- 构建 Netflix 分布式追踪(tracing)体系
- VBS表白代码以及一些注意事项
- Windows手动搭建邮箱服务器教程,操作简单易上手
- 解决-win10软件默认安装路径为C盘——修改注册表
- Could not resolve dependencies for project com.koolearn:koo-b2b-tesa-api:jar:1.0-dev-SNAPSHOT
- java进阶知识思维导图
- 最新触摸精灵开发教程(价值300
- HashMap为什么要使用红黑树
- TIOBE 11 月编程语言:Java 首次跌出前二;基于Pytorch的Kornia可微分计算机视觉库开源...
- 【学习笔记】狄利克雷卷积
- 【转】国家天文大地网
热门文章
- 益生菌可能导致的“菌血症”与死亡(调研手稿六)
- 是否应该饮用酵素和自制的葡萄酒
- intellij手动添加依赖jar包
- package.json和package-lock.json
- awk输出csv的一列
- 等式约束和不等式约束下的KKT条件求法
- Java构建工具, ZeroC ICE, word2vec
- html5在li中添加按钮,如何在html5blank_nav()中的ul和li中添加类?
- inode linux x64,又一次在64位ubuntu上安装iNode
- Java设计模式(六)----适配器模式