新浪微博客户端开发之adapter


2013年11月23日 新浪微博客户端系列博客记录

之前获取首页微博列表还没有介绍adapter,关于adapter可以分出来一块来讲,用过ListView的童鞋们肯定对adapter不会陌生,下面是Android提供的一些Adapter,适用与一些简单的数据填充。

  • BaseAdapter是一个抽象类,继承它需要实现较多的方法,所以也就具有较高的灵活性;
  • ArrayAdapter支持泛型操作,最为简单,只能展示一行字。
  • SimpleAdapter有最好的扩充性,可以自定义出各种效果。
  • SimpleCursorAdapter可以适用于简单的纯文字型ListView,它需要Cursor的字段和UI的id对应起来。如需要实现更复杂的UI也可以重写其他方法。可以认为是SimpleAdapter对数据库的简单结合,可以方便地把数据库的内容以列表的形式展示出来。

到了新浪微博这里就需要自定义Adapter了,使用Android提供的adapter已经不能满足需求了,目前小巫所开发的有以下自定义adapter:

AppsListAdaper:用于显示联想搜索得到的app列表。
CommentListAdapter:用于显示评论列表。
FaceListAdapter:用于显示表情列表。
MSGAdapter:用于显示消息页面列表。
UsersListAdaper:用于显示联想搜索得到的User列表。
WeiboListAdapter:用于显示微博列表(首页、收藏、@我的)。
WeiboListNoMoreAdapter:在WeboListAdapter基础上去掉“更多”的adapter。


首页界面效果:

新浪微博客户端开发之adapter


今天我只介绍WeiboListAdapter

/xiaowu_twitter/src/com/wwj/sina/weibo/adapters/WeiboListAdapter.java


WeiboListAdapter是稍显复杂的,因为它要显示的数据比较多,涉及到微博图片的显示,转发内容的显示,先来看看代码先吧。

  1. packagecom.wwj.sina.weibo.adapters;
  2. importjava.io.File;
  3. importjava.util.ArrayList;
  4. importjava.util.Date;
  5. importjava.util.List;
  6. importandroid.app.Activity;
  7. importandroid.content.Context;
  8. importandroid.net.Uri;
  9. importandroid.text.Html;
  10. importandroid.view.LayoutInflater;
  11. importandroid.view.View;
  12. importandroid.view.ViewGroup;
  13. importandroid.widget.BaseAdapter;
  14. importandroid.widget.ImageView;
  15. importandroid.widget.LinearLayout;
  16. importandroid.widget.TextView;
  17. importcom.wwj.sina.weibo.R;
  18. importcom.wwj.sina.weibo.interfaces.Const;
  19. importcom.wwj.sina.weibo.library.StorageManager;
  20. importcom.wwj.sina.weibo.library.WeiboManager;
  21. importcom.wwj.sina.weibo.object.Status;
  22. importcom.wwj.sina.weibo.util.Tools;
  23. importcom.wwj.sina.weibo.workqueue.DoneAndProcess;
  24. importcom.wwj.sina.weibo.workqueue.task.ParentTask;
  25. /**
  26. *微博列表适配器主要用来显示首页、提示我的、收藏微博列表
  27. *
  28. *@authorwwj
  29. *
  30. */
  31. publicclassWeiboListAdapterextendsBaseAdapterimplementsConst,
  32. DoneAndProcess{
  33. protectedActivityactivity;
  34. protectedinttype;
  35. protectedLayoutInflaterlayoutInflater;
  36. protectedList<Status>statuses;
  37. publicWeiboListAdapter(Activityactivity){
  38. this.activity=activity;
  39. }
  40. /**
  41. *需要传入一个已经封装微博数据的List对象type表示
  42. *
  43. *@paramactivity
  44. *@paramstatuses
  45. *@paramtype
  46. *表示处理的微博数据类型,在Const中定义相关常量
  47. */
  48. publicWeiboListAdapter(Activityactivity,List<Status>statuses,inttype){
  49. this.activity=activity;
  50. this.type=type;
  51. layoutInflater=(LayoutInflater)activity
  52. .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  53. this.statuses=newArrayList<Status>();
  54. if(statuses!=null)
  55. this.statuses.addAll(statuses);
  56. try{
  57. //保存微博数据
  58. StorageManager.saveList(statuses,PATH_STORAGE,type);
  59. }catch(Exceptione){
  60. e.printStackTrace();
  61. }
  62. }
  63. @Override
  64. publicintgetCount(){
  65. //获取微博数,加1为了最后一项显示"更多"
  66. returnstatuses.size()+1;
  67. }
  68. @Override
  69. publicObjectgetItem(intposition){
  70. returnnull;
  71. }
  72. @Override
  73. publiclonggetItemId(intposition){
  74. return0;
  75. }
  76. //获取制定位置的Status对象
  77. publicStatusgetStatus(intposition){
  78. if(statuses.size()>0){
  79. returnstatuses.get(position);
  80. }else{
  81. returnnull;
  82. }
  83. }
  84. //获取已经显示的微博的最小ID
  85. publiclonggetMinId(){
  86. if(statuses.size()>0)
  87. returnstatuses.get(statuses.size()-1).id;
  88. else
  89. returnLong.MAX_VALUE;
  90. }
  91. //获取已经显示的微博最大ID
  92. publiclonggetMaxId(){
  93. if(statuses.size()>0)
  94. returnstatuses.get(0).id;
  95. else
  96. return0;
  97. }
  98. //添加新的微博
  99. //在刷新、显示更多微博时会根据不同的情况决定如何添加微博
  100. publicvoidputStatuses(List<Status>statuses){
  101. if(statuses==null||this.statuses==null)
  102. return;
  103. if(statuses.size()==0)
  104. return;
  105. if(this.statuses.size()==0){
  106. this.statuses.addAll(statuses);
  107. }elseif(statuses
  108. .get(0)
  109. .getCreatedAt()
  110. .before(this.statuses.get(this.statuses.size()-1)
  111. .getCreatedAt())){
  112. this.statuses.addAll(statuses);
  113. //添加的statuses比原来的新,并且数量小于等于默认返回数量,直接将statuses添加到前面
  114. }elseif(statuses.get(statuses.size()-1).getCreatedAt()
  115. .after(this.statuses.get(0).getCreatedAt())
  116. &&statuses.size()<=DEFAULT_STATUS_COUNT){
  117. this.statuses.addAll(0,statuses);
  118. }else{
  119. this.statuses.clear();
  120. this.statuses.addAll(statuses);
  121. }
  122. try{
  123. //保存微博信息
  124. StorageManager.saveList(this.statuses,PATH_STORAGE,type);
  125. }catch(Exceptione){
  126. e.printStackTrace();
  127. }
  128. //并且刷新ListView
  129. this.notifyDataSetChanged();
  130. }
  131. //控制View行为的
  132. privatebooleanshowMoreAnimFlag=false;
  133. protectedbooleanshowRefreshAnimFlag=false;
  134. publicvoidshowMoreAnim(){
  135. showMoreAnimFlag=true;
  136. notifyDataSetChanged();
  137. }
  138. publicvoidhideMoreAnim(){
  139. showMoreAnimFlag=false;
  140. notifyDataSetChanged();
  141. }
  142. publicvoidshowRefreshAnim(){
  143. showMoreAnimFlag=true;
  144. notifyDataSetChanged();
  145. }
  146. publicvoidhideRefreshAnim(){
  147. showRefreshAnimFlag=false;
  148. notifyDataSetChanged();
  149. }
  150. //通过url装载要显示的图像,如果图像文件不存在,回通过hideView标志决定是否隐藏ImageView组件
  151. //hideView:true隐藏ImageViewhideView:false不做任何动作
  152. privatevoidloadImage(ImageViewimageView,Stringurl,booleanhideView){
  153. if(url!=null){
  154. StringimageUrl=WeiboManager.getImageurl(activity,url);
  155. if(imageUrl!=null){
  156. imageView.setImageURI(Uri.fromFile(newFile(imageUrl)));
  157. imageView.setVisibility(View.VISIBLE);
  158. return;
  159. }
  160. }
  161. if(hideView)
  162. imageView.setVisibility(View.GONE);
  163. }
  164. @Override
  165. publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
  166. if(convertView==null){
  167. convertView=layoutInflater
  168. .inflate(R.layout.weibo_list_item,null);
  169. }
  170. ViewweiboListItem=convertView.findViewById(R.id.ll_weibo_list_item);//微博列表项
  171. ViewmoreWeiboListItem=convertView
  172. .findViewById(R.id.rl_more_weibo_list_item);//“更多”列表项
  173. ViewrefreshWeiboListItem=convertView
  174. .findViewById(R.id.rl_refresh_weibo_list_item);//"刷新"列表项
  175. refreshWeiboListItem.setVisibility(View.GONE);
  176. //当列表项不是最后一项时继续执行
  177. if(position<statuses.size()){
  178. weiboListItem.setVisibility(View.VISIBLE);
  179. moreWeiboListItem.setVisibility(View.GONE);//“更多”不显示
  180. Statusstatus=statuses.get(position);
  181. TextViewstatusText=(TextView)convertView
  182. .findViewById(R.id.tv_text);
  183. TextViewname=(TextView)convertView.findViewById(R.id.tv_name);
  184. TextViewcreateAt=(TextView)convertView
  185. .findViewById(R.id.tv_created_at);
  186. ImageViewprofileImage=(ImageView)convertView
  187. .findViewById(R.id.iv_profile_image);
  188. profileImage.setImageResource(R.drawable.portrait);//设置默认头像
  189. ImageViewpicture=(ImageView)convertView
  190. .findViewById(R.id.iv_picture);
  191. ImageViewstatusImage=(ImageView)convertView
  192. .findViewById(R.id.iv_status_image);
  193. ImageViewverified=(ImageView)convertView
  194. .findViewById(R.id.iv_verified);
  195. verified.setVisibility(View.GONE);//设置认证不可见
  196. if(status.user!=null){
  197. //设置用户认证图标,即各种颜色的“V”或其他符号
  198. Tools.userVerified(verified,status.user.verified_type);
  199. }
  200. statusImage.setImageBitmap(null);
  201. LinearLayoutinsideContent=(LinearLayout)convertView
  202. .findViewById(R.id.ll_inside_content);
  203. ImageViewretweetdetailImage=(ImageView)convertView
  204. .findViewById(R.id.iv_retweetdetail_image);
  205. retweetdetailImage.setImageBitmap(null);
  206. TextViewretweetdetailText=(TextView)convertView
  207. .findViewById(R.id.tv_retweetdetail_text);
  208. TextViewsource=(TextView)convertView
  209. .findViewById(R.id.tv_source);
  210. //装载图像
  211. if(status.user!=null){
  212. loadImage(profileImage,status.user.profile_image_url,false);
  213. }
  214. loadImage(statusImage,status.thumbnail_pic,true);
  215. statusText.setText(Tools.changeTextToFace(activity,
  216. Html.fromHtml(Tools.atBlue(status.text))));
  217. if(status.user!=null)
  218. name.setText(status.user.name);//显示用户昵称
  219. //当前微博有图像
  220. if(WeiboManager.hasPicture(status))
  221. picture.setVisibility(View.VISIBLE);
  222. else
  223. picture.setVisibility(View.INVISIBLE);
  224. createAt.setText(Tools.getTimeStr(status.getCreatedAt(),newDate()));
  225. source.setText("来自:"+status.getTextSource());//设置微博来源
  226. if(status.retweeted_status!=null//如果转发的数据不为空
  227. &&status.retweeted_status.user!=null){
  228. insideContent.setVisibility(View.VISIBLE);
  229. retweetdetailText.setText(Html.fromHtml(Tools.atBlue("@"
  230. +status.retweeted_status.user.name+":"
  231. +status.retweeted_status.text)));
  232. loadImage(retweetdetailImage,
  233. status.retweeted_status.thumbnail_pic,false);
  234. }else{
  235. insideContent.setVisibility(View.GONE);
  236. }
  237. }else{
  238. weiboListItem.setVisibility(View.GONE);
  239. moreWeiboListItem.setVisibility(View.VISIBLE);//显示“更多”
  240. ViewmoreAnim=convertView.findViewById(R.id.pb_more);
  241. if(showMoreAnimFlag){
  242. moreAnim.setVisibility(View.VISIBLE);
  243. }else{
  244. moreAnim.setVisibility(View.GONE);
  245. }
  246. }
  247. returnconvertView;
  248. }
  249. @Override
  250. publicvoiddoneProcess(ParentTasktask){
  251. notifyDataSetChanged();//通知更新列表数据
  252. }
  253. }

关于adapter我们需要关注getView这个方法,因为我们要显示的内容都在这里完成,由于每一条的微博数据比较多,所以童鞋们要注意每一项内容显示到哪个控件上。显示的数据是通过构造方法传进来的,每一条微博数据就是一个Status对象,所以我们需要定义相应的实体类,这个类我们怎么知道怎么定义,这就要知道请求API所返回的内容,

比如:https://api.weibo.com/2/statuses/home_timeline.json。我们请求这个API的时候,返回的字段就是我们需要定义的,如果不太清楚,既要好好看看一下开放平台给我们说明。

可以到这里查看:http://open.weibo.com/wiki/2/statuses/home_timeline

那里很清楚说明了,请求方式,请求参数还有返回的json数据结构。

返回字段说明

返回值字段 字段类型 字段说明
created_at string 微博创建时间
id int64 微博ID
mid int64 微博MID
idstr string 字符串型的微博ID
text string 微博信息内容
source string 微博来源
favorited boolean 是否已收藏,true:是,false:否
truncated boolean 是否被截断,true:是,false:否
in_reply_to_status_id string (暂未支持)回复ID
in_reply_to_user_id string (暂未支持)回复人UID
in_reply_to_screen_name string (暂未支持)回复人昵称
thumbnail_pic string 缩略图片地址,没有时不返回此字段
bmiddle_pic string 中等尺寸图片地址,没有时不返回此字段
original_pic string 原始图片地址,没有时不返回此字段
geo object 地理信息字段详细
user object 微博作者的用户信息字段详细
retweeted_status object 被转发的原微博信息字段,当该微博为转发微博时返回详细
reposts_count int 转发数
comments_count int 评论数
attitudes_count int 表态数
mlevel int 暂未支持
visible object 微博的可见性及指定可见分组信息。该object中type取值,0:普通微博,1:私密微博,3:指定分组微博,4:密友微博;list_id为分组的组号
pic_urls object 微博配图地址。多图时返回多图链接。无配图返回“[]”
ad object array 微博流内的推广微博ID


  1. packagecom.wwj.sina.weibo.object;
  2. importjava.io.Serializable;
  3. importjava.util.Date;
  4. importcom.wwj.sina.weibo.interfaces.WeiboObject;
  5. importcom.wwj.sina.weibo.util.Tools;
  6. importandroid.text.Html;
  7. /**
  8. *微博实体类
  9. *@authorwwj
  10. *
  11. */
  12. @SuppressWarnings("serial")
  13. publicclassStatusimplementsWeiboObject,Serializable{
  14. /**字符串型的微博ID*/
  15. publicStringidstr;
  16. /**创建时间*/
  17. publicStringcreated_at;
  18. /**微博ID*/
  19. publiclongid;
  20. /**微博信息内容*/
  21. publicStringtext;
  22. /**微博来源(html形式)*/
  23. publicStringsource;
  24. /**是否已收藏*/
  25. publicbooleanfavorited;
  26. /**是否被截断*/
  27. publicbooleantruncated;
  28. /**回复ID*/
  29. publiclongin_reply_to_status_id;
  30. /**回复人UID*/
  31. publiclongin_reply_to_user_id;
  32. /**回复人昵称*/
  33. publicStringin_reply_to_screen_name;
  34. /**微博MID*/
  35. publiclongmid;
  36. /**中等尺寸图片地址*/
  37. publicStringbmiddle_pic;
  38. /**原始图片地址*/
  39. publicStringoriginal_pic;
  40. /**缩略图片地址*/
  41. publicStringthumbnail_pic;
  42. /**转发数*/
  43. publicintreposts_count;
  44. /**评论数*/
  45. publicintcomments_count;
  46. /**转发的微博内容*/
  47. publicStatusretweeted_status;
  48. /**微博作者的用户信息字段*/
  49. publicUseruser;//不要初始化,否则可能会引起递归创建对象,导致stack溢出
  50. /**获取Date形式的创建时间*/
  51. publicDategetCreatedAt(){
  52. returnTools.strToDate(created_at);
  53. }
  54. /**文本形式的source,*/
  55. privateStringtext_source;
  56. /**获取文本形式的source*/
  57. publicStringgetTextSource(){
  58. if(text_source==null){
  59. try{
  60. //有时返回的来源是null,可能是一个bug,所以必须加上try...catch...
  61. text_source=Html.fromHtml(source).toString();
  62. }catch(Exceptione){
  63. text_source=source;
  64. }
  65. }
  66. returntext_source;
  67. }
  68. }

我们在授权第三方应用程序访问用户的数据成功后,就会异步获取用户首页微博数据,然后显示到界面上。

  1. packagecom.wwj.sina.weibo.listener;
  2. importjava.io.IOException;
  3. importjava.util.List;
  4. importandroid.app.Activity;
  5. importandroid.os.Bundle;
  6. importandroid.os.Message;
  7. importandroid.view.View;
  8. importandroid.widget.LinearLayout;
  9. importandroid.widget.Toast;
  10. importcom.weibo.net.DialogError;
  11. importcom.weibo.net.WeiboDialogListener;
  12. importcom.weibo.net.WeiboException;
  13. importcom.weibo.net.AsyncWeiboRunner.RequestListener;
  14. importcom.wwj.sina.weibo.Home;
  15. importcom.wwj.sina.weibo.R;
  16. importcom.wwj.sina.weibo.adapters.WeiboListAdapter;
  17. importcom.wwj.sina.weibo.interfaces.Const;
  18. importcom.wwj.sina.weibo.library.JSONAndObject;
  19. importcom.wwj.sina.weibo.library.StorageManager;
  20. importcom.wwj.sina.weibo.library.WeiboManager;
  21. importcom.wwj.sina.weibo.listener.impl.StatusRequestListenerImpl;
  22. importcom.wwj.sina.weibo.object.Status;
  23. importcom.wwj.sina.weibo.object.User;
  24. importcom.wwj.sina.weibo.util.LogUtils;
  25. importcom.wwj.sina.weibo.util.SettingUtil;
  26. importcom.wwj.sina.weibo.util.Tools;
  27. publicclassAuthDialogListenerimplementsWeiboDialogListener,Const{
  28. privateActivityactivity;
  29. publicAuthDialogListener(Activityactivity){
  30. super();
  31. this.activity=activity;
  32. }
  33. //认证成功后调用
  34. publicvoidonComplete(Bundlevalues){
  35. //保存access_token和expires_in
  36. Stringtoken=values.getString("access_token");
  37. Stringexpires_in=values.getString("expires_in");
  38. SettingUtil.set(activity,SettingUtil.ACCESS_TOKEN,token);
  39. SettingUtil.set(activity,SettingUtil.EXPIRES_IN,expires_in);
  40. Toast.makeText(activity,"认证成功",Toast.LENGTH_SHORT).show();
  41. finalHomehomeActivity=(Home)activity;
  42. WeiboListAdapterweiboListAdapter=null;
  43. //得到用户的唯一标识
  44. longuid=Long.parseLong(values.getString("uid"));
  45. //保存用户UID
  46. StorageManager.setValue(activity,"uid",uid);
  47. WeiboManager.getUserAsync(homeActivity,
  48. StorageManager.getValue(homeActivity,"uid",0),
  49. newRequestListener(){
  50. @Override
  51. publicvoidonIOException(IOExceptione){
  52. }
  53. @Override
  54. publicvoidonError(WeiboExceptione){
  55. }
  56. @Override
  57. publicvoidonComplete(Stringresponse){
  58. Useruser=newUser();
  59. JSONAndObject.convertSingleObject((Object)user,
  60. response);
  61. Messagemsg=newMessage();
  62. msg.obj=user;
  63. homeActivity.handler.sendMessage(msg);
  64. }
  65. });
  66. ViewhomeReloadAnim=homeActivity.findViewById(R.id.pb_home_reload);
  67. ViewhomeReload=homeActivity.findViewById(R.id.btn_home_reload);
  68. homeReloadAnim.setVisibility(View.VISIBLE);
  69. homeReload.setVisibility(View.GONE);
  70. LinearLayoutll_home_layout=(LinearLayout)homeActivity
  71. .findViewById(R.id.ll_home_layout);
  72. List<Status>statuses=WeiboManager.getHomeTimelineAsync(homeActivity,
  73. newStatusRequestListenerImpl(homeActivity,ll_home_layout,
  74. HOME));
  75. weiboListAdapter=newWeiboListAdapter(activity,statuses,Const.HOME);
  76. homeActivity.homeTimelineAdapter=weiboListAdapter;
  77. homeActivity.imageWorkQueueMonitor=Tools
  78. .getGlobalObject(homeActivity).getImageWorkQueueMonitor(
  79. homeActivity);
  80. homeActivity.taskWorkQueueMonitor=Tools.getGlobalObject(homeActivity)
  81. .getTaskWorkQueueMonitor(activity);
  82. homeActivity.imageWorkQueueMonitor.addDoneAndProcess(Const.HOME,
  83. weiboListAdapter);
  84. }
  85. publicvoidonWeiboException(WeiboExceptione){
  86. LogUtils.e("###onWeiboException");
  87. //当认证过程中捕获到WeiboException时调用
  88. Toast.makeText(activity,"Authexception:"+e.getMessage(),
  89. Toast.LENGTH_LONG).show();
  90. activity.finish();
  91. }
  92. publicvoidonError(DialogErrore){
  93. LogUtils.e("###onError");
  94. //Oauth2.0认证过程中,当认证对话框中的webView接收数据出现错误时调用此方法
  95. Toast.makeText(activity,"Autherror:"+e.getMessage(),
  96. Toast.LENGTH_LONG).show();
  97. activity.finish();
  98. }
  99. publicvoidonCancel(){
  100. LogUtils.e("###onCancel");
  101. //Oauth2.0认证过程中,如果认证窗口被关闭或认证取消时调用
  102. Toast.makeText(activity,"Authcancel",Toast.LENGTH_LONG).show();
  103. activity.finish();
  104. }
  105. }


在认证成功后,回调onComplete方法,就会获取用户个人信息,显示到标题上。下面的代码我解释一下:

statuses的数据是由WeiboManager类当中getHomeTimelineAsync返回来的,这方法传入了一个监听器,StatusRequestListenerImpl这里类实现AsyncWeiboRunner类的RequestListener接口。

  1. LinearLayoutll_home_layout=(LinearLayout)homeActivity
  2. .findViewById(R.id.ll_home_layout);
  3. List<Status>statuses=WeiboManager.getHomeTimelineAsync(homeActivity,
  4. newStatusRequestListenerImpl(homeActivity,ll_home_layout,
  5. HOME));
  6. weiboListAdapter=newWeiboListAdapter(activity,statuses,Const.HOME);
  7. homeActivity.homeTimelineAdapter=weiboListAdapter;
  8. homeActivity.imageWorkQueueMonitor=Tools
  9. .getGlobalObject(homeActivity).getImageWorkQueueMonitor(
  10. homeActivity);
  11. homeActivity.taskWorkQueueMonitor=Tools.getGlobalObject(homeActivity)
  12. .getTaskWorkQueueMonitor(activity);
  13. homeActivity.imageWorkQueueMonitor.addDoneAndProcess(Const.HOME,
  14. weiboListAdapter);


AsyncWeiboRunner这个就是实现异步请求数据的类,通过构造函数传入进来的listener,调用它的onComplete方法就可以把请求的数据得到。

  1. /*
  2. *Copyright2011Sina.
  3. *
  4. *LicensedundertheApacheLicenseandWeiboLicense,Version2.0(the"License");
  5. *youmaynotusethisfileexceptincompliancewiththeLicense.
  6. *YoumayobtainacopyoftheLicenseat
  7. *
  8. *http://www.open.weibo.com
  9. *http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
  12. *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
  13. *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
  14. *SeetheLicenseforthespecificlanguagegoverningpermissionsand
  15. *limitationsundertheLicense.
  16. */
  17. packagecom.weibo.net;
  18. importjava.io.IOException;
  19. importcom.wwj.sina.weibo.util.LogUtils;
  20. importandroid.content.Context;
  21. /**
  22. *EncapsulationmainWeiboAPIs,Include:1.getRquestToken,2.
  23. *getAccessToken,3.urlrequest.Implementsaweiboapiasaasynchronized
  24. *way.Everyobjectusedthisrunnershouldimplementinterface
  25. *RequestListener.
  26. *异步请求数据的类
  27. *@authorZhangJie([email protected])
  28. */
  29. publicclassAsyncWeiboRunner{
  30. privateWeibomWeibo;
  31. publicAsyncWeiboRunner(Weiboweibo){
  32. this.mWeibo=weibo;
  33. }
  34. publicvoidrequest(finalContextcontext,finalStringurl,
  35. finalWeiboParametersparams,finalStringhttpMethod,
  36. finalRequestListenerlistener){
  37. LogUtils.d("###AsyncWeiboRunnerrequest");
  38. newThread(){
  39. @Override
  40. publicvoidrun(){
  41. try{
  42. Stringresp=mWeibo.request(context,url,params,
  43. httpMethod,mWeibo.getAccessToken());
  44. listener.onComplete(resp);
  45. }catch(WeiboExceptione){
  46. listener.onError(e);
  47. }
  48. }
  49. }.start();
  50. }
  51. //请求接口
  52. publicstaticinterfaceRequestListener{
  53. publicvoidonComplete(Stringresponse);
  54. publicvoidonIOException(IOExceptione);
  55. publicvoidonError(WeiboExceptione);
  56. }
  57. }


所以真正显示数据的地方在StatusRequestListenerImpl里,通过回调onComplete方法得到的respone,respone就是请求api返回的json数据,我们通过JSONAndObject的convert方法,将json字符串转换为以status作为元素的List。之后就是通过handler发送消息,在界面显示数据了,具体细节你们需要好好看看代码。

  1. packagecom.wwj.sina.weibo.listener.impl;
  2. importjava.io.IOException;
  3. importjava.text.SimpleDateFormat;
  4. importjava.util.Date;
  5. importjava.util.List;
  6. importandroid.app.Activity;
  7. importandroid.os.Handler;
  8. importandroid.os.Message;
  9. importandroid.view.View;
  10. importcom.weibo.net.AsyncWeiboRunner.RequestListener;
  11. importcom.weibo.net.WeiboException;
  12. importcom.wwj.sina.weibo.Home;
  13. importcom.wwj.sina.weibo.MessageViewer;
  14. importcom.wwj.sina.weibo.R;
  15. importcom.wwj.sina.weibo.adapters.WeiboListAdapter;
  16. importcom.wwj.sina.weibo.adapters.WeiboListNoMoreAdapter;
  17. importcom.wwj.sina.weibo.interfaces.Const;
  18. importcom.wwj.sina.weibo.library.JSONAndObject;
  19. importcom.wwj.sina.weibo.library.WeiboManager;
  20. importcom.wwj.sina.weibo.object.Favorite;
  21. importcom.wwj.sina.weibo.object.Status;
  22. importcom.wwj.sina.weibo.util.LogUtils;
  23. /**
  24. *微博数据请求监听器实现
  25. *@authorwwj
  26. *
  27. */
  28. publicclassStatusRequestListenerImplimplementsRequestListener,Const{
  29. privateWeiboListAdapterweiboListAdapter;
  30. privateWeiboListNoMoreAdapterweiboListNoMoreAdapter;//隐藏“更多”
  31. privateActivityactivity;
  32. privateViewparent;
  33. privateinttype;
  34. privateHomehomeActivity;
  35. privateMessageViewermessageViewer;
  36. privateHandlerhandler=newHandler(){
  37. publicvoidhandleMessage(android.os.Messagemsg){
  38. SimpleDateFormatformat=newSimpleDateFormat("yyyy年MM月dd日HH:mm");
  39. Stringdate=format.format(newDate());
  40. switch(type){
  41. caseHOME:
  42. weiboListAdapter.putStatuses((List<Status>)msg.obj);
  43. weiboListAdapter.hideMoreAnim();
  44. weiboListAdapter.hideRefreshAnim();
  45. homeActivity=(Home)activity;
  46. if(homeActivity.weiboListView.getAdapter()==null){
  47. homeActivity.weiboListView.setAdapter(weiboListAdapter);
  48. homeActivity.imageWorkQueueMonitor.addDoneAndProcess(HOME,
  49. weiboListAdapter);
  50. }
  51. ViewhomeReloadAnim=parent.findViewById(R.id.pb_home_reload);
  52. ViewhomeReload=parent.findViewById(R.id.btn_home_reload);
  53. homeReloadAnim.setVisibility(View.GONE);
  54. homeReload.setVisibility(View.VISIBLE);
  55. homeActivity.weiboListView.onRefreshComplete(date);
  56. break;
  57. caseMESSAGE_AT:
  58. caseUSER_TIMELINE:
  59. weiboListAdapter.putStatuses((List<Status>)msg.obj);
  60. weiboListAdapter.hideMoreAnim();
  61. weiboListAdapter.hideRefreshAnim();
  62. messageViewer=(MessageViewer)activity;
  63. if(messageViewer.messageListView.getAdapter()==null){
  64. messageViewer.messageListView.setAdapter(weiboListAdapter);
  65. messageViewer.imageWorkQueueMonitor.addDoneAndProcess(type,
  66. weiboListAdapter);
  67. }
  68. ViewmessageReloadAnim=parent
  69. .findViewById(R.id.pb_message_reload);
  70. ViewmessageReload=parent
  71. .findViewById(R.id.btn_message_reload);
  72. messageReloadAnim.setVisibility(View.GONE);
  73. messageReload.setVisibility(View.VISIBLE);
  74. messageViewer.messageListView.onRefreshComplete(date);
  75. break;
  76. caseMESSAGE_FAVORITE:
  77. weiboListNoMoreAdapter.putStatuses((List<Status>)msg.obj);
  78. messageViewer=(MessageViewer)activity;
  79. if(messageViewer.messageListView.getAdapter()==null){
  80. messageViewer.messageListView
  81. .setAdapter(weiboListNoMoreAdapter);
  82. messageViewer.imageWorkQueueMonitor.addDoneAndProcess(
  83. MESSAGE_FAVORITE,weiboListNoMoreAdapter);
  84. }
  85. ViewmessageReloadAnim2=parent
  86. .findViewById(R.id.pb_message_reload);
  87. ViewmessageReload2=parent
  88. .findViewById(R.id.btn_message_reload);
  89. messageReloadAnim2.setVisibility(View.GONE);
  90. messageReload2.setVisibility(View.VISIBLE);
  91. messageViewer.messageListView.onRefreshComplete(date);
  92. break;
  93. default:
  94. break;
  95. }
  96. super.handleMessage(msg);
  97. };
  98. };
  99. publicStatusRequestListenerImpl(Activityactivity,Viewparent,inttype){
  100. this.activity=activity;
  101. this.parent=parent;
  102. this.type=type;
  103. }
  104. @Override
  105. publicvoidonComplete(Stringresponse){
  106. @SuppressWarnings("unchecked")
  107. List<Status>statuses=JSONAndObject.convert(Status.class,response,
  108. "statuses");
  109. switch(type){
  110. caseHOME:
  111. LogUtils.d("###home");
  112. homeActivity=(Home)activity;
  113. if(homeActivity.homeTimelineAdapter!=null){
  114. weiboListAdapter=homeActivity.homeTimelineAdapter;
  115. }else{
  116. weiboListAdapter=newWeiboListAdapter(homeActivity,null,
  117. type);
  118. homeActivity.homeTimelineAdapter=weiboListAdapter;
  119. }
  120. break;
  121. caseMESSAGE_AT:
  122. caseUSER_TIMELINE:
  123. LogUtils.d("###MESSAGE_AT");
  124. messageViewer=(MessageViewer)activity;
  125. if(messageViewer.messageListAdapter!=null){
  126. weiboListAdapter=messageViewer.messageListAdapter;
  127. }else{
  128. weiboListAdapter=newWeiboListAdapter(messageViewer,null,
  129. type);
  130. messageViewer.messageListAdapter=weiboListAdapter;
  131. }
  132. break;
  133. caseMESSAGE_FAVORITE:
  134. LogUtils.d("###MESSAGE_FAVORITE");
  135. messageViewer=(MessageViewer)activity;
  136. if(messageViewer.weiboListNoMoreAdapter!=null){
  137. weiboListNoMoreAdapter=messageViewer.weiboListNoMoreAdapter;
  138. }else{
  139. weiboListNoMoreAdapter=newWeiboListNoMoreAdapter(
  140. messageViewer,null,MESSAGE_FAVORITE);
  141. messageViewer.messageListAdapter=weiboListNoMoreAdapter;
  142. }
  143. List<Favorite>favorites=null;
  144. favorites=JSONAndObject.convert(Favorite.class,response,
  145. "favorites");
  146. statuses=WeiboManager.FavoriteToStatus(favorites);
  147. default:
  148. break;
  149. }
  150. Messagemsg=newMessage();
  151. msg.obj=statuses;
  152. handler.sendMessage(msg);
  153. }
  154. @Override
  155. publicvoidonIOException(IOExceptione){
  156. e.printStackTrace();
  157. }
  158. @Override
  159. publicvoidonError(WeiboExceptione){
  160. e.printStackTrace();
  161. }
  162. }


这篇博客的关键点应该不在adapter这里,如何异步更新UI才是最重要的,我这里使用的是handler来更新UI。线程的异步操作就主要通过AsyncWeiboRunner这个类实现,这部分内容就已经囊括了其他微博数据的获取实现流程,获取收藏列表和提到我的微博列表都是类似的实现,我就不多介绍了