新浪微博PC客户端(DotNet WinForm版)—— 初探
最近興趣使然嘗試了一下使用DotNet技術實現新浪微博PC客戶端,幾天時間,目前實現登錄、微博列表、發布純文本微博功能,新浪API調用基本沒什么難度,在微博列表形式處理上著實讓我煩躁了一陣子,Windows Form使用不多,這次開發也感覺有些捉襟見肘。
?
環境:
操作系統:Windows 7 Ultimate
集成開發環境:Visual Studio 2010 Ultimate
.NET Framework:3.5
?
先看一下截圖:
1、登錄界面
?
2、 登錄
?
3、第一次運行主界面加載
?
4、主頁面
?
5、翻頁?
?
?6)如果博文中有圖,點擊小圖可以查看大圖
?
新浪微博API返回的數據類型有兩種:XML和JSON。在登錄時,我直接用DataSet讀的XML數據存儲到一個靜態用戶信息類中;而博客列表數據我讀取的是JSON格式的數據,并將JSON格式的數據反序列化為泛型對象(類)集合,這里的類是嵌套類。?
?
然后繪制列表,顯示數據的控件全部是動態添加的,這里最煩的是位置,可能也是這個原因導致每頁20條數據加載比較慢(接口默認一頁返回20條),最快也要2秒,經常要4-6秒,后面提供下載,大家可以試試。另外,影響速度的原因可能還有:1)網速;2)輸出圖片,有的是直接輸出大圖,在回復的源微博中如果有圖片,總是獲取不到縮略圖,只好依次判斷小圖、中圖、大圖,先有哪個輸出哪個。?用Label顯示文本行間距沒法調,只好做了個自定義控件,主要是根據字體大小了增大行距。?
?
界面雖然使用皮膚(ssk),比Window Form原始的界面好看的多,但是比起Adobe的那個AIR還是有差距,或許可以嘗試使用WPF。?
?
后續要實現的功能(還沒全部看API,有的功能不一定提供API):
1)轉發、收藏、回復
2)發帖可以使用表情、可以上傳圖片
3)關注、粉絲列表
4)查看自己微博、他人微博列表
5)個人的一些配置信息
6)主界面左邊想放新浪微博登錄后,個人首頁右邊的內容?
... ...
工作量還挺大:(的。?
?
目前經過處理,程序運行后占用的內存在4M-25M這樣的一個范圍 ,如果不處理會一直攀升,100M、200M、... ... 。
在翻頁時,加載顯示瞬時CPU占用率能夠達到30%左右,一般比較低,5%以下。
滾屏時,CPU占用率一般18%以下,都是瞬時的。?
大家看到的數據異步加載使用了多線程,主要是使用了BackgroundWorker。
?
除了上面的問題,在滾屏時,滾動的內容有點閃,還沒找到好的解決辦法。
?
歡迎有興趣的人一起討論,提寶貴意見。有經驗的人做個指導:)。?
?
最后附上讀取新浪微博API的部分代碼:
using ?System;using ?System.Collections.Generic;
using ?System.Text;
using ?System.IO;
using ?System.Net;
using ?MBClient.Entities;
using ?System.Runtime.Serialization.Json;
using ?System.Data;
using ?System.Drawing;
namespace ?MBClient.API
{
???? internal ? class ?ReadDataBySinaAPI
????{
???????? internal ?ReadDataBySinaAPI()?{?}
???????? /// ? <summary>
???????? /// ?根據用戶登錄信息登錄并讀取用戶信息到DataSet
???????? /// ?如果用戶新浪通行證身份驗證成功且用戶已經開通微博則返回?http狀態為?200;
???????? /// ?如果是不則返回401的狀態和錯誤信息。此方法用了判斷用戶身份是否合法且已經開通微博。
???????? /// ? http://open.t.sina.com.cn/wiki/index.php/Account/verify_credentials
???????? /// ? </summary>
???????? /// ? <param?name="url"> API?URL?(XML?Format) http://api.t.sina.com.cn/account/verify_credentials.xml?source=AppKey
???????? /// ? </param>
???????? /// ? <returns></returns>
???????? internal ? static ?DataSet?ReadXMLDataToDataSet( string ?url)
????????{
????????????CredentialCache?mycache? = ? new ?CredentialCache();
????????????mycache.Add( new ?Uri(url),? " Basic " ,? new ?NetworkCredential(UserInfo.UserName,?UserInfo.Password));
????????????WebRequest?myReq? = ?WebRequest.Create(url);
????????????myReq.Credentials? = ?mycache;
????????????myReq.Headers.Add( " Authorization " ,? " Basic? " ? + ?Convert.ToBase64String( new ?ASCIIEncoding().GetBytes(UserInfo.UserNamePassword)));
????????????WebResponse?wr? = ?myReq.GetResponse();
????????????DataSet?ds? = ? new ?DataSet();
???????????? using ?(Stream?receiveStream? = ?wr.GetResponseStream())
????????????{
????????????????StreamReader?reader? = ? new ?StreamReader(receiveStream,?Encoding.UTF8);
???????????????? // string?content?=?reader.ReadToEnd();
????????????????ds.ReadXml(reader);
????????????????reader.Close();
????????????}
????????????wr.Close();
???????????? return ?ds;
????????}
???????? internal ? static ? string ?ReadXMLDataToString( string ?url)
????????{
????????????CredentialCache?mycache? = ? new ?CredentialCache();
????????????mycache.Add( new ?Uri(url),? " Basic " ,? new ?NetworkCredential(UserInfo.UserName,?UserInfo.Password));
????????????WebRequest?myReq? = ?WebRequest.Create(url);
????????????myReq.Credentials? = ?mycache;
????????????myReq.Headers.Add( " Authorization " ,? " Basic? " ? + ?Convert.ToBase64String( new ?ASCIIEncoding().GetBytes(UserInfo.UserNamePassword)));
????????????WebResponse?wr? = ?myReq.GetResponse();
???????????? string ?strData? = ? null ;
???????????? using ?(Stream?receiveStream? = ?wr.GetResponseStream())
????????????{
????????????????StreamReader?reader? = ? new ?StreamReader(receiveStream,?Encoding.UTF8);
????????????????strData? = ?reader.ReadToEnd();
????????????????reader.Close();
????????????}
????????????wr.Close();
???????????? return ?strData;
????????}
???????? /// ? <summary>
???????? /// ?以JSON格式字符串返回用戶所有關注用戶最新n條微博信息。和用戶“我的首頁”返回內容相同。
???????? /// ? http://open.t.sina.com.cn/wiki/index.php/Statuses/friends_timeline
???????? /// ? </summary>
???????? /// ? <param?name="url"> API?URL?(JSON?Format)? http://api.t.sina.com.cn/statuses/friends_timeline.json?source=AppKey
???????? /// ? </param>
???????? /// ? <returns></returns>
???????? internal ? static ? string ?ReadJsonDataToString( string ?url)
????????{
????????????CredentialCache?mycache? = ? new ?CredentialCache();
????????????mycache.Add( new ?Uri(url),? " Basic " ,? new ?NetworkCredential(UserInfo.UserName,?UserInfo.Password));
????????????WebRequest?myReq? = ?WebRequest.Create(url);
????????????myReq.Credentials? = ?mycache;
????????????myReq.Headers.Add( " Authorization " ,? " Basic? " ? + ?Convert.ToBase64String( new ?ASCIIEncoding().GetBytes(UserInfo.UserNamePassword)));
????????????WebResponse?wr? = ?myReq.GetResponse();
???????????? string ?content? = ? null ;
???????????? using ?(Stream?receiveStream? = ?wr.GetResponseStream())
????????????{
????????????????StreamReader?reader? = ? new ?StreamReader(receiveStream,?Encoding.UTF8);
????????????????content? = ?reader.ReadToEnd();
????????????????reader.Close();
????????????}
????????????wr.Close();
???????????? return ?content;
????????}
???????? /// ? <summary>
???????? /// ?將JSON格式字符串反序列化為Status集合對象
???????? /// ? </summary>
???????? /// ? <param?name="url"> 同ReadJsonDataToString() </param>
???????? /// ? <returns></returns>
???????? internal ? static ?List < Status > ?DeserializeJsonToListObject( string ?url)
????????{
????????????List < Status > ?listObj;
???????????? using ?(MemoryStream?stream? = ? new ?MemoryStream())
????????????{
????????????????DataContractJsonSerializer?ser? = ? new ?DataContractJsonSerializer( typeof (List < Status > ));
????????????????StreamWriter?wr? = ? new ?StreamWriter(stream);
???????????????? string ?strJson? = ?ReadJsonDataToString(url);
????????????????wr.Write(strJson);
????????????????wr.Flush();
????????????????stream.Position? = ? 0 ;
????????????????Object?obj? = ?ser.ReadObject(stream);
????????????????listObj? = ?(List < Status > )obj;
????????????????wr.Close();
????????????}
???????????? return ?listObj;
????????}
???????? /// ? <summary>
???????? /// ?獲取并輸出圖片
???????? /// ? </summary>
???????? /// ? <param?name="imgUrl"> 圖片URL地址 </param>
???????? /// ? <returns></returns>
???????? internal ? static ?Image?GetAvatarImage( string ?imgUrl)
????????{
????????????Uri?myUri? = ? new ?Uri(imgUrl);
????????????WebRequest?webRequest? = ?WebRequest.Create(myUri);
????????????WebResponse?webResponse? = ?webRequest.GetResponse();
????????????Bitmap?myImage? = ? new ?Bitmap(webResponse.GetResponseStream());
???????????? return ?(Image)myImage;
????????}
???????? /// ? <summary>
???????? /// ?發表一條微博
???????? /// ? </summary>
???????? /// ? <param?name="url"> API地址
???????? /// ? http://api.t.sina.com.cn/statuses/update.json
???????? /// ? </param>
???????? /// ? <param?name="data"> AppKey和微博內容
???????? /// ?"source=123456&status="?+?System.Web.HttpUtility.UrlEncode(微博內容);
???????? /// ? </param>
???????? /// ? <returns></returns>
???????? internal ? static ? bool ?PostBlog( string ?url, string ?data)
????????{
???????????? try
????????????{
????????????????System.Net.WebRequest?webRequest? = ?System.Net.WebRequest.Create(url);
????????????????System.Net.HttpWebRequest?httpRequest? = ?webRequest? as ?System.Net.HttpWebRequest;
????????????????System.Net.CredentialCache?myCache? = ? new ?System.Net.CredentialCache();
????????????????myCache.Add( new ?Uri(url),? " Basic " ,
???????????????????? new ?System.Net.NetworkCredential(UserInfo.UserName,?UserInfo.Password));
????????????????httpRequest.Credentials? = ?myCache;
????????????????httpRequest.Headers.Add( " Authorization " ,? " Basic? " ? + ?Convert.ToBase64String(
???????????????????? new ?System.Text.ASCIIEncoding().GetBytes(UserInfo.UserName? + ? " : " ? +
????????????????????UserInfo.Password)));
????????????????httpRequest.Method? = ? " POST " ;
????????????????httpRequest.ContentType? = ? " application/x-www-form-urlencoded " ;
????????????????System.Text.Encoding?encoding? = ?System.Text.Encoding.UTF8; // System.Text.Encoding.ASCII
???????????????? byte []?bytesToPost? = ?encoding.GetBytes(data); // System.Web.HttpUtility.UrlEncode(data)
????????????????httpRequest.ContentLength? = ?bytesToPost.Length;
????????????????System.IO.Stream?requestStream? = ?httpRequest.GetRequestStream();
????????????????requestStream.Write(bytesToPost,? 0 ,?bytesToPost.Length);
????????????????requestStream.Close();
???????????????? return ? true ;
????????????}
???????????? catch
????????????{
???????????????? return ? false ;
????????????}
????????}
????}
}
?
?
?
感謝博客園的這篇文章,參考價值很大:http://www.cnblogs.com/cmt/archive/2010/05/13/1733904.html?
注:AppKey以內置,是我申請的,每IP每用戶一小時內限調用350次API。
PS:別拿來干壞事... ...?
?
附一條完整的博客內容數據(XML格式)
< status >???? < created_at > Wed?Nov?24?21:24:04?+0800?2010 </ created_at >
???? < id > 3858478793 </ id >
???? < text > 很好的推論。?//@白手套的小咪:這是羅永浩流傳最廣的名言之一。給他改一改:沒有哪只鳥來到世間是為了躲槍子兒的。所以,手上拿著槍,并用“槍打出頭鳥”這樣的道理教訓人的那些人,一定要明白,每只鳥都夢想出頭,你打到老死也打不完的。 </ text >
???? < source >
?????? < a? href ="http://t.sina.com.cn" > 新浪微博 </ a >
???? </ source >
???? < favorited > false </ favorited >
???? < truncated > false </ truncated >
???? < geo />
???? < in_reply_to_status_id ></ in_reply_to_status_id >
???? < in_reply_to_user_id ></ in_reply_to_user_id >
???? < in_reply_to_screen_name ></ in_reply_to_screen_name >
???? < user >
?????? < id > 1197161814 </ id >
?????? < screen_name > 李開復 </ screen_name >
?????? < name > 李開復 </ name >
?????? < province > 11 </ province >
?????? < city > 1000 </ city >
?????? < location > 北京 </ location >
?????? < description > 創新工場CEO </ description >
?????? < url > http://blog.sina.com.cn/kaifulee </ url >
?????? < profile_image_url > http://tp3.sinaimg.cn/1197161814/50/1290146312/1 </ profile_image_url >
?????? < domain > kaifulee </ domain >
?????? < gender > m </ gender >
?????? < followers_count > 2384862 </ followers_count >
?????? < friends_count > 132 </ friends_count >
?????? < statuses_count > 1039 </ statuses_count >
?????? < favourites_count > 2 </ favourites_count >
?????? < created_at > Fri?Aug?28?00:00:00?+0800?2009 </ created_at >
?????? < following > false </ following >
?????? < verified > true </ verified >
?????? < allow_all_act_msg > false </ allow_all_act_msg >
?????? < geo_enabled > true </ geo_enabled >
???? </ user >
???? < retweeted_status >
?????? < created_at > Wed?Nov?24?17:35:07?+0800?2010 </ created_at >
?????? < id > 3853748245 </ id >
?????? < text > “希望那些喜歡用“槍打出頭鳥”這樣的道理教訓年輕人,并且因此覺得自己很成熟的中國人有一天能夠明白這樣一個事實,那就是:有的鳥來到世間,是為了做它該做的事,而不是專門躲槍子兒的。” </ text >
?????? < source >
???????? < a? href ="http://t.sina.com.cn" > 新浪微博 </ a >
?????? </ source >
?????? < favorited > false </ favorited >
?????? < truncated > false </ truncated >
?????? < geo />
?????? < in_reply_to_status_id ></ in_reply_to_status_id >
?????? < in_reply_to_user_id ></ in_reply_to_user_id >
?????? < in_reply_to_screen_name ></ in_reply_to_screen_name >
?????? < user >
???????? < id > 1672204023 </ id >
???????? < screen_name > Ran-w </ screen_name >
???????? < name > Ran-w </ name >
???????? < province > 11 </ province >
???????? < city > 5 </ city >
???????? < location > 北京?朝陽區 </ location >
???????? < description > 什么都不知道總比什么都知道要好。慢慢經歷那個不知道的未來。 </ description >
???????? < url > http://blog.sina.com.cn/wongr11 </ url >
???????? < profile_image_url > http://tp4.sinaimg.cn/1672204023/50/1290577674/0 </ profile_image_url >
???????? < domain > wongr </ domain >
???????? < gender > f </ gender >
???????? < followers_count > 757 </ followers_count >
???????? < friends_count > 178 </ friends_count >
???????? < statuses_count > 521 </ statuses_count >
???????? < favourites_count > 4 </ favourites_count >
???????? < created_at > Mon?Dec?21?00:00:00?+0800?2009 </ created_at >
???????? < following > false </ following >
???????? < verified > false </ verified >
???????? < allow_all_act_msg > false </ allow_all_act_msg >
???????? < geo_enabled > true </ geo_enabled >
?????? </ user >
???? </ retweeted_status >
?? </ status >
?status是博主發表的博文,retweeted_status是回復或者轉發了哪條博文。
?
?
下載微博客戶端?
轉載于:https://www.cnblogs.com/Ferry/archive/2010/11/26/1889307.html
總結
以上是生活随笔為你收集整理的新浪微博PC客户端(DotNet WinForm版)—— 初探的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 再论贝叶斯公式
- 下一篇: 2022-2028全球及中国健康资讯交换