今天有看了一下客户端,感觉是我用过的最好的客户端之一了,真的要赞一个优点:
1.简洁 无论是容量还是操作 不像现在某些公司追求大追求平台化 追求各种特效
2.功能全面,该有的都有了
那么现在就分析一下开源中国客户端吧。
其实 资讯类 app结构还是比较简单的 自己也做过一些 但是看了这个客户端 还是有些新知识学到的,整体
来说这个app的结构比较清晰 但是MainActivity负责的功能很多一定程度上会给菜鸟以困难 ,感觉很像 ActivityThread的那个消息处理架构, 看了作者应该看过很多源码?呵呵,乱猜的
现在以 获取新闻为例分析这个客户端
首先是从网络获取数据 并通知UI
核心代码
private void loadLvNewsData(final int catalog, final int pageIndex,
final Handler handler, final int action) {
mHeadProgress.setVisibility(ProgressBar.VISIBLE);
new Thread() {
public void run() {
Message msg = new Message();
boolean isRefresh = false;
if (action == UIHelper.LISTVIEW_ACTION_REFRESH
|| action == UIHelper.LISTVIEW_ACTION_SCROLL)
isRefresh = true;
try {
NewsList list = appContext.getNewsList(catalog, pageIndex,
isRefresh);
msg.what = list.getPageSize();
msg.obj = list;
} catch (AppException e) {
e.printStackTrace();
msg.what = -1;
msg.obj = e;
}
msg.arg1 = action;
msg.arg2 = UIHelper.LISTVIEW_DATATYPE_NEWS;
if (curNewsCatalog == catalog)
handler.sendMessage(msg);
}
}.start();
}
private void loadLvNewsData(final int catalog, final int pageIndex,
final Handler handler, final int action) {
mHeadProgress.setVisibility(ProgressBar.VISIBLE);
new Thread() {
public void run() {
Message msg = new Message();
boolean isRefresh = false;
if (action == UIHelper.LISTVIEW_ACTION_REFRESH
|| action == UIHelper.LISTVIEW_ACTION_SCROLL)
isRefresh = true;
try {
NewsList list = appContext.getNewsList(catalog, pageIndex,
isRefresh);
msg.what = list.getPageSize();
msg.obj = list;
} catch (AppException e) {
e.printStackTrace();
msg.what = -1;
msg.obj = e;
}
msg.arg1 = action;
msg.arg2 = UIHelper.LISTVIEW_DATATYPE_NEWS;
if (curNewsCatalog == catalog)
handler.sendMessage(msg);
}
}.start();
}
1 在onCreate函数中会使用initFrameListView 所有的listview
2.调用loadLvNewsData 初始化所有的handler 光控制各个listview的handler就有6个
3.使用getLvHandler获取 news对于list的handler
4.使用loadLvNewsData 函数加载新闻数据
那么就分析一下加载的新闻数据吧:注意这里有些UI操作就省略了:
5.这里获取网络数据并没有在Activity中进行,(如果真的在这里进行就。。)而是在这个app的application 对象中进行的,这也导致了application 特别巨大,为什么不放在一个特别的类中呢?这个就不是很清楚了
6.AppContext的getNewsList函数会使用ApiClient请求网络数据去了
7.ApiClient根据传来的参数使用_MakeURL构造了请求URL
8.更加上面的网址请求服务器并获取返回的输入流
9.解析返回的输入流 使用的XmlPullParser解析的
10.现在有回到Main中了 既然数据都拿到了 那该发送消息通知UI更新了于是
handler.sendMessage(msg);
到此 获取数据 并通知UI阶段就完成了
第二阶段当然是更新UI了
核心代码
private Handler getLvHandler(final PullToRefreshListView lv,
final BaseAdapter adapter, final TextView more,
final ProgressBar progress, final int pageSize) {
return new Handler() {
public void handleMessage(Message msg) {
if (msg.what >= 0) {
// listview数据处理
Notice notice = handleLvData(msg.what, msg.obj, msg.arg2,
msg.arg1);
if (msg.what < pageSize) {
lv.setTag(UIHelper.LISTVIEW_DATA_FULL);
adapter.notifyDataSetChanged();
more.setText(R.string.load_full);
} else if (msg.what == pageSize) {
lv.setTag(UIHelper.LISTVIEW_DATA_MORE);
adapter.notifyDataSetChanged();
more.setText(R.string.load_more);
// 特殊处理-热门动弹不能翻页
if (lv == lvTweet) {
TweetList tlist = (TweetList) msg.obj;
if (lvTweetData.size() == tlist.getTweetCount()) {
lv.setTag(UIHelper.LISTVIEW_DATA_FULL);
more.setText(R.string.load_full);
}
}
}
// 发送通知广播
if (notice != null) {
UIHelper.sendBroadCast(lv.getContext(), notice);
}
// 是否清除通知信息
if (isClearNotice) {
ClearNotice(curClearNoticeType);
isClearNotice = false;// 重置
curClearNoticeType = 0;
}
} else if (msg.what == -1) {
// 有异常--显示加载出错 & 弹出错误消息
lv.setTag(UIHelper.LISTVIEW_DATA_MORE);
more.setText(R.string.load_error);
((AppException) msg.obj).makeToast(Main.this);
}
if (adapter.getCount() == 0) {
lv.setTag(UIHelper.LISTVIEW_DATA_EMPTY);
more.setText(R.string.load_empty);
}
progress.setVisibility(ProgressBar.GONE);
mHeadProgress.setVisibility(ProgressBar.GONE);
if (msg.arg1 == UIHelper.LISTVIEW_ACTION_REFRESH) {
lv.onRefreshComplete(getString(R.string.pull_to_refresh_update)
+ new Date().toLocaleString());
lv.setSelection(0);
} else if (msg.arg1 == UIHelper.LISTVIEW_ACTION_CHANGE_CATALOG) {
lv.onRefreshComplete();
lv.setSelection(0);
}
}
};
}
private Handler getLvHandler(final PullToRefreshListView lv,
final BaseAdapter adapter, final TextView more,
final ProgressBar progress, final int pageSize) {
return new Handler() {
public void handleMessage(Message msg) {
if (msg.what >= 0) {
// listview数据处理
Notice notice = handleLvData(msg.what, msg.obj, msg.arg2,
msg.arg1);
if (msg.what < pageSize) {
lv.setTag(UIHelper.LISTVIEW_DATA_FULL);
adapter.notifyDataSetChanged();
more.setText(R.string.load_full);
} else if (msg.what == pageSize) {
lv.setTag(UIHelper.LISTVIEW_DATA_MORE);
adapter.notifyDataSetChanged();
more.setText(R.string.load_more);
// 特殊处理-热门动弹不能翻页
if (lv == lvTweet) {
TweetList tlist = (TweetList) msg.obj;
if (lvTweetData.size() == tlist.getTweetCount()) {
lv.setTag(UIHelper.LISTVIEW_DATA_FULL);
more.setText(R.string.load_full);
}
}
}
// 发送通知广播
if (notice != null) {
UIHelper.sendBroadCast(lv.getContext(), notice);
}
// 是否清除通知信息
if (isClearNotice) {
ClearNotice(curClearNoticeType);
isClearNotice = false;// 重置
curClearNoticeType = 0;
}
} else if (msg.what == -1) {
// 有异常--显示加载出错 & 弹出错误消息
lv.setTag(UIHelper.LISTVIEW_DATA_MORE);
more.setText(R.string.load_error);
((AppException) msg.obj).makeToast(Main.this);
}
if (adapter.getCount() == 0) {
lv.setTag(UIHelper.LISTVIEW_DATA_EMPTY);
more.setText(R.string.load_empty);
}
progress.setVisibility(ProgressBar.GONE);
mHeadProgress.setVisibility(ProgressBar.GONE);
if (msg.arg1 == UIHelper.LISTVIEW_ACTION_REFRESH) {
lv.onRefreshComplete(getString(R.string.pull_to_refresh_update)
+ new Date().toLocaleString());
lv.setSelection(0);
} else if (msg.arg1 == UIHelper.LISTVIEW_ACTION_CHANGE_CATALOG) {
lv.onRefreshComplete();
lv.setSelection(0);
}
}
};
}
11 handleMessage这个函数是在 构造getLvHandler方法中实现的 根据android的handler机制,如果消息队列中有消息的时候 就会执行这个方法 由于上面的handler.sendMessage(msg);的handler是news对应的handler,刚才发送的消息就会给new对应的handler处理了
12 13 handleLvData 这个函数 是 在list添加 从网络获取的list
14 ok终于notifyDataSetChanged 这样new对于的listview就显示数据了