标签:style blog http color os io 使用 ar for
最近要开发一个新闻应用,暂定从Api获取新闻html,再放在WebView中展示(WP8.1已经把WebBrowser改成了WebView)。
Api还没开发好,因此参考知乎日报的Api:https://github.com/izzyleung/ZhihuDailyPurify/wiki/%E7%9F%A5%E4%B9%8E%E6%97%A5%E6%8A%A5-API-%E5%88%86%E6%9E%90
新闻应用的难点之一在于如何实现缓存,参考了一些文章,在WP上实现缓存的思路是:获取目标网址的HTML代码,放到WebView中展示,同时用正则表达式提取出图片url,下载后保存到本地储存,然后通过正则表达式把html代码中图片的路径改为指向本地,最后将html代码保存到数据库。
大概思路就是这样,不过我注意到两个问题:(1)把图片url取出后进行http请求,是从缓存中读取还是再次进行一次请求(若再次请求,等于耗了两倍流量)。(2)用户可能在网页图片没加载完的情况下退出,应该如何设计缓存逻辑。
首先先验证一下网页加载完之后再次对图片url地址进行请求,是否消耗两倍流量,方法为网页加载完后把手机调到飞行模式,再手动触发图片url的请求。
首先是xaml代码(Button用于手动触发请求):
<WebView x:Name="webView" Margin="0,0,0,32"/> <Button Margin="142,575,0,-52" Click="Button_Click" Height="72"/>
接下来是后台代码,使用的是知乎日报的api,返回Json格式数据。
private string body; public MainPage() { this.InitializeComponent(); this.NavigationCacheMode = NavigationCacheMode.Required; startRequest(); } private void startRequest() { HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://news-at.zhihu.com/api/3/news/4129407"); request.Method = "GET"; IAsyncResult result = (IAsyncResult)request.BeginGetResponse(ResponseCallBack,request); } private void ResponseCallBack(IAsyncResult result) { HttpWebRequest request = (HttpWebRequest)result.AsyncState; HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result); if (response.StatusCode == HttpStatusCode.OK && response.ContentLength > 0) { using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { string contents = reader.ReadToEnd(); startParse(contents); } } }
返回的Json结构如下:
用于测试就不加载css了,只加载body,通过NavigateToString方法加载html代码:
private async void startParse(string contents) { JObject json = JObject.Parse(contents); body = (string)json["body"]; var dispatcher = CoreApplication.MainView.CoreWindow.Dispatcher; await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { webView.NavigateToString(body); }); }
这里有个要注意的问题,就是在异步中对UI线程进行操作的问题。以往都是通过Windows.Deployment.Current.Dispatcher.BeginInvoke()方法在异步中对UI线程操作,但是WP8.1的工程(非Sliverlight)中没有找到Windows.Deployment命名空间。在网上查找到了另外的方法。
按钮点击事件:
private void Button_Click(object sender, RoutedEventArgs e) { Regex regex = new Regex("<img.src=\\\"(.*)\\\".alt",RegexOptions.IgnoreCase); MatchCollection result = regex.Matches(body); foreach (Match each in result) { string b = each.Groups[1].Value; var httpWebRequest = (HttpWebRequest)WebRequest.Create(url); httpWebRequest.AllowReadStreamBuffering = true; httpWebRequest.BeginGetResponse(ResponseCallBack_i, httpWebRequest); } } private void ResponseCallBack_i(IAsyncResult asyncResult) { var httpWebRequest = asyncResult.AsyncState as HttpWebRequest; if (httpWebRequest == null) return; var response = httpWebRequest.EndGetResponse(asyncResult); var stream = response.GetResponseStream(); }
经过实机测试,在开启了飞行模式之后再手动发送请求,不会报错,stream的length与图片字节相符,因此可以得出再次发送请求时会先从缓存中读取。
那就到第二个问题,目前思路为:获得api返回的json数据之后马上取出url并发送请求,图片下载后保存到本地储存,并把文件名加入一个List<string>中。当用户后退的时候触发事件,根据List中的成员统一替换body中的路径(不应网页加载完后再进行缓存)。
使用上述思路,又会出现一个问题:网页加载的同时进行Http请求,是否会消耗更多流量。
另外因为http请求为异步,由于知识不足,其实通过队列对body进行替换更好。
缓存研究就先写到这里。
小弟愚笨,只能想出如此方法去验证,不知是否有人研究过这个问题,望告知。另外有什么错误或不足也请指出,而有其他实现逻辑则希望能共同探讨。
WindowsPhone 8.1 新闻应用开发--缓存研究(1)
标签:style blog http color os io 使用 ar for
原文地址:http://www.cnblogs.com/ACzero/p/3952381.html