【完全开源】博客园客户端UWP版 带源码、带APP(下篇)
APP简介
律师查询是基于聚合数据的律师查询接口做的,这个接口目前处于停用状态,但是,由于我是之前申请的,所以,还可以用,应该是无法再申请了。
效果图
开发
一、HttpHelper
既然是请求接口的,那就少不了请求方式,这里是比较常用的HttpClient,用起来也比较方便,单独封装一个HttpHelper类,专门用来作为基础的连接用
public static class BaseService { /// <summary> /// 访问服务器时的Cookies /// </summary> public static CookieContainer CookiesContainer; /// <summary> /// 向服务器发送GET请求 返回服务器回复的数据 /// </summary> /// <param name="url">地址</param> /// <returns></returns> public async static Task<string> SendGetRequest(string url) { try { HttpClient client = new HttpClient(); HttpResponseMessage response = await client.GetAsync(new Uri(url)); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } catch (Exception ex) { return null; throw(ex); } } /// <summary> /// 向服务器发送POST请求,返回服务器回复数据 /// </summary> /// <param name="url">地址</param> /// <param name="body">报文体</param> /// <returns></returns> public async static Task<string> SendPostRequest(string url,string body) { try { HttpClient client = new HttpClient(); HttpResponseMessage response = await client.PostAsync(new Uri(url), new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("", body) })); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync(); } catch (Exception ex) { return null; throw(ex); } } }
网络请求肯定用异步请求,UWP里比较常用的就是async、await模式,很方便,因为,接口的返回结果用的是Json形式,所以,Newtonsoft.Json来处理序列化和反序列化。
/// <summary> /// Json返回结果 ///说明:必须要重写ErrorMess,否则没有错误返回消息 /// </summary> public abstract class ResultInfoHelper { /// <summary> /// 传入URL和参数,解析返回Json信息,并返回结果 /// </summary> /// <typeparam name="T">参数类型</typeparam> /// <param name="_url">URl地址</param> /// <param name="args">相关参数</param> /// <returns></returns> public async Task<T> GetResultInfoGetHelper<T>(string _url,params object[] args) { string url = string.Format(_url, args); string resultUrl = await BaseService.SendGetRequest(url); ErrorMess<T>(resultUrl); T resultList = JsonConvert.DeserializeObject<T>(resultUrl); return resultList; } /// <summary> /// 传入URL和Body,解析返回Json信息,并返回结果 /// </summary> /// <typeparam name="T">参数类型</typeparam> /// <param name="_url">URL地址</param> /// <param name="body">传入Body</param> /// <returns></returns> public async Task<T> GetResultInfoPostHelper<T>(string _url,string body) { string resultUrl = await BaseService.SendPostRequest(_url, body); ErrorMess<T>(resultUrl); T resultList = JsonConvert.DeserializeObject<T>(resultUrl); return resultList; } /// <summary> /// 错误信息 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="resultUrl"></param> protected abstract void ErrorMess<T>(string resultUrl); }
此处用Abstract,是为了以后其他项目也可以使用这个HttpHelper,重写ErrorMess方便不同的项目抛出不同的错误。
用params object[] args作为参数的好处是,可以不限定参数的类型和个数。
二、SearchLawyer.UWP
1、根据接口返回,设计实体类
律师查询接口的返回都是类似于以上这种形式,就是reason、result、error_code,既然,有统一的规律,那就非常容易建立实体类了,创建一个Info<T>。
Info<T>为所有返回的总体样式,通过传入不同的T类型,来保证result是不同类型的泛型集合,这样,接收返回数据时就很方便了,例如Info<Lawyer>
2、请求接口
写一个GetInfoHelper<M>继承ResultInfoHelper,重写ErrorMess方法
public class GetInfoHelper<M> : ResultInfoHelper { /// <summary> /// 重写错误方法 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="resultUrl"></param> protected override async void ErrorMess<T>(string resultUrl) { if (typeof(T).Name==typeof(Info<M>).Name) { Info<M> error = JsonConvert.DeserializeObject<Info<M>>(resultUrl); if (error.error_code != 0) { await (new MessageDialog("错误代码:" + error.error_code + "\r\n" + "错误信息:" + Constant.ConstantValue.Error[error.error_code])).ShowAsync(); return; } } } }
此处,需要判别typeof(T)和typeof(Info<M>)是不是同一个类型,如果是同一个类型,才能进行下面的操作
这么做的原因,是为了不同的返回类型设计的,而不需要写多个方法
3、写View页面
因为页面要么是律师查询,要么是辩词查询,所以,页面显示的内容格式是一样的,为了不进行重复工作,需要给ListView写一个统一的ItemTemplate(写在样式文件里),如果样式用Binding是没有问题的,但是如果用x:Bind就会出错,但是微软给出了x:Bind要比Binding效率高,所以,咱也不能绕过这个问题,解决花了有小半天时间,给解决了。大家可以参考我这篇帖子
4、写ViewModel页面
由于不涉及到什么复杂的业务逻辑判别,所以VM页面也是蛮简单的,根据不用的按钮,调用不同的请求
需要注意的是,由于UWP里是没有x:static的,所以,如果将枚举作为参数传递的话,必须使用如下写法,这样才能获取到参数值,否则,VM页面接收到的始终是枚举的第一个
<Button Content="查询" Command="{Binding SearchCommand}"> <Button.CommandParameter> <constant:Method>LawyerByProvince</constant:Method> </Button.CommandParameter> </Button>
为了实现向下滑动,动态刷新列表,也就是继续请求数据,类需要继承ObservableCollection<Lawyer>和 ISupportIncrementalLoading,这个我是参见大神的里的方法,但是发现一个问题,如果我的返回个数少的话,出了显示结果,还会弹出一个没有查询到数据的错误提示,跟踪代码发现这个方法会请求两次,因此,做了写修改,就是判断得到的数量是否小于设置的返回条数,如果是的话,就把HasMoreItems设置成false,防止再次请求。
总结
代码方面没什么难度,看过微软提供的那个开发视频,基本都能上手UWP开发,不过,由于一直做WPF,做个UWP练练手,发现,不一样的地方还是挺多的,话说回来,开发UWP还是挺有意思的,开发过程中学到了不少东西,真的是有些东西看起来容易,实现起来真心不一定容易。
希望,能有越来越多的开发者重视UWP开发,能让这个生态圈好起来。
源码已放