新浪微博客户端开发之adapter

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.ImageView;

import android.widget.LinearLayout;

import android.widget.TextView;

import com.wwj.sina.weibo.R;

import com.wwj.sina.weibo.interfaces.Const;

import com.wwj.sina.weibo.library.StorageManager;

import com.wwj.sina.weibo.library.WeiboManager;

import com.wwj.sina.weibo.object.Status;

import com.wwj.sina.weibo.util.Tools;

import com.wwj.sina.weibo.workqueue.DoneAndProcess;

import com.wwj.sina.weibo.workqueue.task.ParentTask;

/**

  • 微博列表适配器 主要用来显示首页、提示我的、收藏微博列表

  • @author wwj

*/

public class WeiboListAdapter extends BaseAdapter implements Const,

DoneAndProcess {

protected Activity activity;

protected int type;

protected LayoutInflater layoutInflater;

protected List statuses;

public WeiboListAdapter(Activity activity) {

this.activity = activity;

}

/**

  • 需要传入一个已经封装微博数据的List对象 type表示

  • @param activity

  • @param statuses

  • @param type

  •        表示处理的微博数据类型,在Const中定义相关常量
    

*/

public WeiboListAdapter(Activity activity, List statuses, int type) {

this.activity = activity;

this.type = type;

layoutInflater = (LayoutInflater) activity

.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

this.statuses = new ArrayList();

if (statuses != null)

this.statuses.addAll(statuses);

try {

// 保存微博数据

StorageManager.saveList(statuses, PATH_STORAGE, type);

} catch (Exception e) {

e.printStackTrace();

}

}

@Override

public int getCount() {

// 获取微博数,加1为了最后一项显示"更多"

return statuses.size() + 1;

}

@Override

public Object getItem(int position) {

return null;

}

@Override

public long getItemId(int position) {

return 0;

}

// 获取制定位置的Status对象

public Status getStatus(int position) {

if (statuses.size() > 0) {

return statuses.get(position);

} else {

return null;

}

}

// 获取已经显示的微博的最小ID

public long getMinId() {

if (statuses.size() > 0)

return statuses.get(statuses.size() - 1).id;

else

return Long.MAX_VALUE;

}

// 获取已经显示的微博最大ID

public long getMaxId() {

if (statuses.size() > 0)

return statuses.get(0).id;

else

return 0;

}

// 添加新的微博

// 在刷新、显示更多微博时会根据不同的情况决定如何添加微博

public void putStatuses(List statuses) {

if (statuses == null || this.statuses == null)

return;

if (statuses.size() == 0)

return;

if (this.statuses.size() == 0) {

this.statuses.addAll(statuses);

} else if (statuses

.get(0)

.getCreatedAt()

.before(this.statuses.get(this.statuses.size() - 1)

.getCreatedAt())) {

this.statuses.addAll(statuses);

// 添加的statuses比原来的新,并且数量小于等于默认返回数量,直接将statuses添加到前面

} else if (statuses.get(statuses.size() - 1).getCreatedAt()

.after(this.statuses.get(0).getCreatedAt())

&& statuses.size() <= DEFAULT_STATUS_COUNT) {

this.statuses.addAll(0, statuses);

} else {

this.statuses.clear();

this.statuses.addAll(statuses);

}

try {

// 保存微博信息

StorageManager.saveList(this.statuses, PATH_STORAGE, type);

} catch (Exception e) {

e.printStackTrace();

}

// 并且刷新ListView

this.notifyDataSetChanged();

}

// 控制View行为的

private boolean showMoreAnimFlag = false;

protected boolean showRefreshAnimFlag = false;

public void showMoreAnim() {

showMoreAnimFlag = true;

notifyDataSetChanged();

}

public void hideMoreAnim() {

showMoreAnimFlag = false;

notifyDataSetChanged();

}

public void showRefreshAnim() {

showMoreAnimFlag = true;

notifyDataSetChanged();

}

public void hideRefreshAnim() {

showRefreshAnimFlag = false;

notifyDataSetChanged();

}

// 通过url装载要显示的图像,如果图像文件不存在,回通过hideView标志决定是否隐藏ImageView组件

// hideView: true 隐藏ImageView hideView:false 不做任何动作

private void loadImage(ImageView imageView, String url, boolean hideView) {

if (url != null) {

String imageUrl = WeiboManager.getImageurl(activity, url);

if (imageUrl != null) {

imageView.setImageURI(Uri.fromFile(new File(imageUrl)));

imageView.setVisibility(View.VISIBLE);

return;

}

}

if (hideView)

imageView.setVisibility(View.GONE);

}

@Override

public View getView(int position, View convertView, ViewGroup parent) {

if (convertView == null) {

convertView = layoutInflater

.inflate(R.layout.weibo_list_item, null);

}

View weiboListItem = convertView.findViewById(R.id.ll_weibo_list_item); // 微博列表项

View moreWeiboListItem = convertView

.findViewById(R.id.rl_more_weibo_list_item); // “更多”列表项

View refreshWeiboListItem = convertView

.findViewById(R.id.rl_refresh_weibo_list_item); // "刷新"列表项

refreshWeiboListItem.setVisibility(View.GONE);

// 当列表项不是最后一项时继续执行

if (position < statuses.size()) {

weiboListItem.setVisibility(View.VISIBLE);

moreWeiboListItem.setVisibility(View.GONE); // “更多”不显示

Status status = statuses.get(position);

TextView statusText = (TextView) convertView

.findViewById(R.id.tv_text);

TextView name = (TextView) convertView.findViewById(R.id.tv_name);

TextView createAt = (TextView) convertView

.findViewById(R.id.tv_created_at);

ImageView profileImage = (ImageView) convertView

.findViewById(R.id.iv_profile_image);

profileImage.setImageResource(R.drawable.portrait); // 设置默认头像

ImageView picture = (ImageView) convertView

.findViewById(R.id.iv_picture);

ImageView statusImage = (ImageView) convertView

.findViewById(R.id.iv_status_image);

ImageView verified = (ImageView) convertView

.findViewById(R.id.iv_verified);

verified.setVisibility(View.GONE); // 设置认证不可见

if (status.user != null) {

// 设置用户认证图标,即各种颜色的“V”或其他符号

Tools.userVerified(verified, status.user.verified_type);

}

statusImage.setImageBitmap(null);

LinearLayout insideContent = (LinearLayout) convertView

.findViewById(R.id.ll_inside_content);

ImageView retweetdetailImage = (ImageView) convertView

.findViewById(R.id.iv_retweetdetail_image);

retweetdetailImage.setImageBitmap(null);

TextView retweetdetailText = (TextView) convertView

.findViewById(R.id.tv_retweetdetail_text);

TextView source = (TextView) convertView

.findViewById(R.id.tv_source);

// 装载图像

if (status.user != null) {

loadImage(profileImage, status.user.profile_image_url, false);

}

loadImage(statusImage, status.thumbnail_pic, true);

statusText.setText(Tools.changeTextToFace(activity,

Html.fromHtml(Tools.atBlue(status.text))));

if (status.user != null)

name.setText(status.user.name); // 显示用户昵称

// 当前微博有图像

if (WeiboManager.hasPicture(status))

picture.setVisibility(View.VISIBLE);

else

picture.setVisibility(View.INVISIBLE);

createAt.setText(Tools.getTimeStr(status.getCreatedAt(), new Date()));

source.setText("来自: " + status.getTextSource()); // 设置微博来源

if (status.retweeted_status != null // 如果转发的数据不为空

&& status.retweeted_status.user != null) {

insideContent.setVisibility(View.VISIBLE);

retweetdetailText.setText(Html.fromHtml(Tools.atBlue(“@”

  • status.retweeted_status.user.name + “:”

  • status.retweeted_status.text)));

loadImage(retweetdetailImage,

status.retweeted_status.thumbnail_pic, false);

} else {

insideContent.setVisibility(View.GONE);

}

} else {

weiboListItem.setVisibility(View.GONE);

moreWeiboListItem.setVisibility(View.VISIBLE); // 显示“更多”

View moreAnim = convertView.findViewById(R.id.pb_more);

if (showMoreAnimFlag) {

moreAnim.setVisibility(View.VISIBLE);

} else {

moreAnim.setVisibility(View.GONE);

}

}

return convertView;

}

@Override

public void doneProcess(ParentTask task) {

notifyDataSetChanged(); // 通知更新列表数据

}

}

关于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 |

package com.wwj.sina.weibo.object;

import java.io.Serializable;

import java.util.Date;

import com.wwj.sina.weibo.interfaces.WeiboObject;

import com.wwj.sina.weibo.util.Tools;

import android.text.Html;

/**

  • 微博实体类

  • @author wwj

*/

@SuppressWarnings(“serial”)

public class Status implements WeiboObject, Serializable {

/** 字符串型的微博ID */

public String idstr;

/** 创建时间 */

public String created_at;

/** 微博ID */

public long id;

/** 微博信息内容 */

public String text;

/** 微博来源(html形式) */

public String source;

/** 是否已收藏 */

public boolean favorited;

/** 是否被截断 */

public boolean truncated;

/** 回复ID */

public long in_reply_to_status_id;

/** 回复人UID */

public long in_reply_to_user_id;

/** 回复人昵称 */

public String in_reply_to_screen_name;

/** 微博MID */

public long mid;

/** 中等尺寸图片地址 */

public String bmiddle_pic;

/** 原始图片地址 */

public String original_pic;

/** 缩略图片地址 */

public String thumbnail_pic;

/** 转发数 */

public int reposts_count;

/** 评论数 */

public int comments_count;

/** 转发的微博内容 */

public Status retweeted_status;

/** 微博作者的用户信息字段 */

public User user; // 不要初始化,否则可能会引起递归创建对象,导致stack溢出

/** 获取Date形式的创建时间 */

public Date getCreatedAt() {

return Tools.strToDate(created_at);

}

/** 文本形式的source, */

private String text_source;

/** 获取文本形式的source */

public String getTextSource() {

if (text_source == null) {

try {

// 有时返回的来源是null,可能是一个bug,所以必须加上try…catch…

text_source = Html.fromHtml(source).toString();

} catch (Exception e) {

text_source = source;

}

}

return text_source;

}

}

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

package com.wwj.sina.weibo.listener;

import java.io.IOException;

import java.util.List;

import android.app.Activity;

import android.os.Bundle;

import android.os.Message;

import android.view.View;

import android.widget.LinearLayout;

import android.widget.Toast;

import com.weibo.net.DialogError;

import com.weibo.net.WeiboDialogListener;

import com.weibo.net.WeiboException;

import com.weibo.net.AsyncWeiboRunner.RequestListener;

import com.wwj.sina.weibo.Home;

import com.wwj.sina.weibo.R;

import com.wwj.sina.weibo.adapters.WeiboListAdapter;

import com.wwj.sina.weibo.interfaces.Const;

import com.wwj.sina.weibo.library.JSONAndObject;

import com.wwj.sina.weibo.library.StorageManager;

import com.wwj.sina.weibo.library.WeiboManager;

import com.wwj.sina.weibo.listener.impl.StatusRequestListenerImpl;

import com.wwj.sina.weibo.object.Status;

import com.wwj.sina.weibo.object.User;

import com.wwj.sina.weibo.util.LogUtils;

import com.wwj.sina.weibo.util.SettingUtil;

import com.wwj.sina.weibo.util.Tools;

public class AuthDialogListener implements WeiboDialogListener, Const {

private Activity activity;

public AuthDialogListener(Activity activity) {

super();

this.activity = activity;

}

// 认证成功后调用

public void onComplete(Bundle values) {

// 保存access_token 和 expires_in

String token = values.getString(“access_token”);

String expires_in = values.getString(“expires_in”);

SettingUtil.set(activity, SettingUtil.ACCESS_TOKEN, token);

SettingUtil.set(activity, SettingUtil.EXPIRES_IN, expires_in);

Toast.makeText(activity, “认证成功”, Toast.LENGTH_SHORT).show();

final Home homeActivity = (Home) activity;

WeiboListAdapter weiboListAdapter = null;

// 得到用户的唯一标识

long uid = Long.parseLong(values.getString(“uid”));

// 保存用户UID

StorageManager.setValue(activity, “uid”, uid);

WeiboManager.getUserAsync(homeActivity,

StorageManager.getValue(homeActivity, “uid”, 0),

new RequestListener() {

@Override

public void onIOException(IOException e) {

}

@Override

public void onError(WeiboException e) {

}

@Override

public void onComplete(String response) {

User user = new User();

JSONAndObject.convertSingleObject((Object) user,

response);

Message msg = new Message();

msg.obj = user;

homeActivity.handler.sendMessage(msg);

}

});

View homeReloadAnim = homeActivity.findViewById(R.id.pb_home_reload);

View homeReload = homeActivity.findViewById(R.id.btn_home_reload);

homeReloadAnim.setVisibility(View.VISIBLE);

homeReload.setVisibility(View.GONE);

LinearLayout ll_home_layout = (LinearLayout) homeActivity

.findViewById(R.id.ll_home_layout);

List statuses = WeiboManager.getHomeTimelineAsync(homeActivity,

new StatusRequestListenerImpl(homeActivity, ll_home_layout,

HOME));

weiboListAdapter = new WeiboListAdapter(activity, statuses, Const.HOME);

homeActivity.homeTimelineAdapter = weiboListAdapter;

homeActivity.imageWorkQueueMonitor = Tools

.getGlobalObject(homeActivity).getImageWorkQueueMonitor(

homeActivity);

homeActivity.taskWorkQueueMonitor = Tools.getGlobalObject(homeActivity)

.getTaskWorkQueueMonitor(activity);

homeActivity.imageWorkQueueMonitor.addDoneAndProcess(Const.HOME,

weiboListAdapter);

}

public void onWeiboException(WeiboException e) {

LogUtils.e(“### onWeiboException”);

// 当认证过程中捕获到WeiboException时调用

Toast.makeText(activity, “Auth exception:” + e.getMessage(),

Toast.LENGTH_LONG).show();

activity.finish();

}

public void onError(DialogError e) {

LogUtils.e(“### onError”);

// Oauth2.0认证过程中,当认证对话框中的webView接收数据出现错误时调用此方法

Toast.makeText(activity, “Auth error:” + e.getMessage(),

Toast.LENGTH_LONG).show();

activity.finish();

}

public void onCancel() {

LogUtils.e(“### onCancel”);

// Oauth2.0认证过程中,如果认证窗口被关闭或认证取消时调用

Toast.makeText(activity, “Auth cancel”, Toast.LENGTH_LONG).show();

activity.finish();

}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

结语

  • 现在随着短视频,抖音,快手的流行NDK模块开发也显得越发重要,需要这块人才的企业也越来越多,随之学习这块的人也变多了,音视频的开发,往往是比较难的,而这个比较难的技术就是NDK里面的技术。
  • 音视频/高清大图片/人工智能/直播/抖音等等这年与用户最紧密,与我们生活最相关的技术一直都在寻找最终的技术落地平台,以前是windows系统,而现在则是移动系统了,移动系统中又是以Android占比绝大部分为前提,所以AndroidNDK技术已经是我们必备技能了。
  • 要学习好NDK,其中的关于C/C++,jni,Linux基础都是需要学习的,除此之外,音视频的编解码技术,流媒体协议,ffmpeg这些都是音视频开发必备技能,而且
  • OpenCV/OpenGl/这些又是图像处理必备知识,下面这些我都是当年自己搜集的资料和做的一些图,因为当年我就感觉视频这块会是一个大的趋势。所以提前做了一些准备。现在拿出来分享给大家。

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

lAgF4GLR-1711992159768)]

[外链图片转存中…(img-TfmtKYBl-1711992159769)]

[外链图片转存中…(img-BhULqP1j-1711992159769)]

[外链图片转存中…(img-NXsphCJD-1711992159770)]

[外链图片转存中…(img-2mN30rY7-1711992159770)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

结语

  • 现在随着短视频,抖音,快手的流行NDK模块开发也显得越发重要,需要这块人才的企业也越来越多,随之学习这块的人也变多了,音视频的开发,往往是比较难的,而这个比较难的技术就是NDK里面的技术。
  • 音视频/高清大图片/人工智能/直播/抖音等等这年与用户最紧密,与我们生活最相关的技术一直都在寻找最终的技术落地平台,以前是windows系统,而现在则是移动系统了,移动系统中又是以Android占比绝大部分为前提,所以AndroidNDK技术已经是我们必备技能了。
  • 要学习好NDK,其中的关于C/C++,jni,Linux基础都是需要学习的,除此之外,音视频的编解码技术,流媒体协议,ffmpeg这些都是音视频开发必备技能,而且
  • OpenCV/OpenGl/这些又是图像处理必备知识,下面这些我都是当年自己搜集的资料和做的一些图,因为当年我就感觉视频这块会是一个大的趋势。所以提前做了一些准备。现在拿出来分享给大家。

[外链图片转存中…(img-QXHk9gC6-1711992159770)]

[外链图片转存中…(img-jY7tI22V-1711992159770)]

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值