APP簡介 律師查詢是基於聚合數據的律師查詢介面做的,這個介面目前處於停用狀態,但是,由於我是之前申請的,所以,還可以用,應該是無法再申請了。 效果圖 開發 一、HttpHelper 既然是請求介面的,那就少不了請求方式,這裡是比較常用的HttpClient,用起來也比較方便,單獨封裝一個HttpH ...
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); } } }BaseService
網路請求肯定用非同步請求,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); }ResultInfoHelper
此處用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; } } } }GetInfoHelper
此處,需要判別typeof(T)和typeof(Info<M>)是不是同一個類型,如果是同一個類型,才能進行下麵的操作
這麼做的原因,是為了不同的返回類型設計的,而不需要寫多個方法
3、寫View頁面
因為頁面要麼是律師查詢,要麼是辯詞查詢,所以,頁面顯示的內容格式是一樣的,為了不進行重覆工作,需要給ListView寫一個統一的ItemTemplate(寫在樣式文件里),如果樣式用Binding是沒有問題的,但是如果用x:Bind就會出錯,但是微軟給出了x:Bind要比Binding效率高,所以,咱也不能繞過這個問題,解決花了有小半天時間,給解決了。大家可以參考我這篇帖子x:bind不支持樣式文件 或 此Xaml文件必須又代碼隱藏類才能使用{x:Bind} 解決辦法
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,這個我是參見周見智大神的【完全開源】博客園客戶端UWP版 帶源碼、帶APP(下篇)里的方法,但是發現一個問題,如果我的返回個數少的話,出了顯示結果,還會彈出一個沒有查詢到數據的錯誤提示,跟蹤代碼發現這個方法會請求兩次,因此,做了寫修改,就是判斷得到的數量是否小於設置的返回條數,如果是的話,就把HasMoreItems設置成false,防止再次請求。
總結
代碼方面沒什麼難度,看過微軟提供的那個開發視頻,基本都能上手UWP開發,不過,由於一直做WPF,做個UWP練練手,發現,不一樣的地方還是挺多的,話說回來,開發UWP還是挺有意思的,開發過程中學到了不少東西,真的是有些東西看起來容易,實現起來真心不一定容易。
希望,能有越來越多的開發者重視UWP開發,能讓這個生態圈好起來。
源碼已放GitHub