这一篇在 Android仿人人客户端(v5.7.1)——个人主页(二) 的基础上,继续和大家聊一聊剩下部分的实现思路,以及对已完成部分做的一些调整。 有关 好友个人主页的在前两篇已和大家聊过了,这篇重点是和大家聊下有关当前登录用户的个人主页的实现。
一、代码结构的调整
我去人人官方开放平台查看API时,发现有提供新版本的API,相关内容地址:http://wiki.dev.renren.com/wiki/API_new。仔细阅读其简介中有如下描述:随着API2.0的逐渐完善,原来的API1.0服务将不再维护,预计在年底(2013)前关闭,建议开发者开发应用时采用新版API,对已有的应用做好迁移。看到这段话,说明数据提供接口有变更。既然有变更,我们想用别人提供的服务就得拥抱变化。再次回过头看我们之前写的代码,觉得是时候重构一下了。
1、定义一组数据提供接口,代码如下:
package com.everyone.android.user.manager; import java.util.List; import android.os.Handler; import com.everyone.android.api.AuthTokenManager; import com.everyone.android.api.NetworkBaseActivity; import com.everyone.android.callback.ResultCallback; import com.everyone.android.net.AsyncBaseRequest; import com.everyone.android.net.DefaultThreadPool; import com.everyone.android.utils.LogUtil; /** * 功能描述:用户个人主页数据管理类 * @author android_ls */ public abstract class PersonalHomepageManager { /** * LOG打印标签 */ protected static final String TAG = PersonalHomepageManager.class.getSimpleName(); /** * 当前activity所持有的所有网络请求 */ protected List<AsyncBaseRequest> mAsyncRequests; /** * 当前activity所持有的Handler */ protected Handler mHandler; /** * 当前activity所持有的线程池对象 */ protected DefaultThreadPool mDefaultThreadPool; protected AuthTokenManager mAuthTokenManager; /** * 用户信息唯一标识 */ protected int uid; /** * 当前登录用户身份的唯一标识 */ protected String accessToken; public PersonalHomepageManager(NetworkBaseActivity activity) { this.mHandler = activity.getHandler(); this.mAuthTokenManager = activity.getAuthTokenManager(); this.mAsyncRequests = activity.getAsyncRequests(); this.mDefaultThreadPool = activity.getDefaultThreadPool(); this.accessToken = mAuthTokenManager.getAccessToken(); LogUtil.i(TAG, "accessToken = " + accessToken); } /** * 设置用户的唯一标识。 * 该方法必须在{@link #getProfileInfo()}和{@link #getUserImage()}之前调用 * @param uid 用户Id */ public void setUid(int uid) { this.uid = uid; } /** * 获取用户个人主页的信息 */ public abstract void getProfileInfo(ResultCallback resultCallback); /** * 获取用户的图像 */ public abstract void getUserImage(ResultCallback resultCallback); /** * 获取用户最近来访列表 */ public abstract void getVisitors(int page, int pageSize, ResultCallback resultCallback); }
2、编写基于人人API1.0版本,个人主页请求服务器端数据的实现。
package com.everyone.android.user.manager; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import com.everyone.android.api.NetworkBaseActivity; import com.everyone.android.callback.ParseCallback; import com.everyone.android.callback.ResultCallback; import com.everyone.android.entity.UserBasicInfo; import com.everyone.android.entity.UserDetailInfo; import com.everyone.android.net.AsyncBaseRequest; import com.everyone.android.net.AsyncHttpsPost; import com.everyone.android.utils.Constant; import com.everyone.android.utils.LogUtil; /** * 功能描述:基于人人API1.0版本,个人主页请求服务器端数据的实现类 * @author android_ls */ public class PersonalHomepageManagerV1 extends PersonalHomepageManager { public PersonalHomepageManagerV1(NetworkBaseActivity activity) { super(activity); } @Override public void getProfileInfo(ResultCallback resultCallback) { Map<String, String> parameter = new HashMap<String, String>(); parameter.put("v", "1.0"); // API的版本号,固定值为1.0 parameter.put("access_token", accessToken); // OAuth2.0验证授权后获得的token。 parameter.put("format", "JSON"); // 返回值的格式。请指定为JSON或者XML parameter.put("call_id", "1.0"); // 请求队列号 parameter.put("method", "users.getProfileInfo"); parameter.put("uid", uid + ""); // 个人主页用户的Id parameter.put("fields", "base_info,status,friends_count,status_count," + "visitors_count,blogs_count,albums_count,guestbook_count"); // 需要获取的信息的字段列表,各个字段用逗号隔开。 AsyncHttpsPost asyncHttpsPost = new AsyncHttpsPost(Constant.API_SERVER_URL, parameter, new ParseCallback() { @Override public UserDetailInfo parse(String json) throws JSONException { LogUtil.i(TAG, "getProfileInfo() json = " + json); /* { "uid":221659942, "status":{"content":"我才知道草莓翻转,是这个意思(偷笑) 转自谭静:明天最后一门考试,结束后,就真的迎来暑假啦~~哇卡卡卡~~~下学期也终于木有课了~~~(twg)(大笑)(ys)(流口水)","time":"2013-07-02 14:37:01"}, "star":1, "network_name":"西北大学", "headurl":"http://hdn.xnimg.cn/photos/hdn421/20130614/1350/tiny_cm9Q_ec73000461fa113e.jpg", "name":"谭静", "base_info":{"birth":{"birth_month":3,"birth_day":21,"birth_year":"1987"},"hometown":{"province":"河北","city":"唐山市"},"gender":0} }*/ UserDetailInfo userDetail = new UserDetailInfo(); final JSONObject jsonObject = new JSONObject(json); String name = jsonObject.optString("name"); userDetail.setName(name); int star = jsonObject.optInt("star"); userDetail.setStar(star); JSONObject jsonStatus = jsonObject.optJSONObject("status"); String status = jsonStatus.optString("content"); userDetail.setStatus(status); /* String headurl = jsonObject.optString("headurl"); LogUtil.i(TAG, "headurl = " + headurl);*/ int uid = jsonObject.optInt("uid"); userDetail.setUid(uid); String network_name = jsonObject.optString("network_name"); userDetail.setNetwork_name(network_name); JSONObject jsonBaseInfo = jsonObject.optJSONObject("base_info"); if (jsonBaseInfo != null) { userDetail.setBase_info(jsonBaseInfo.toString()); } int status_count = jsonObject.optInt("status_count"); int albums_count = jsonObject.optInt("albums_count"); int guestbook_count = jsonObject.optInt("guestbook_count"); int blogs_count = jsonObject.optInt("blogs_count"); int friends_count = jsonObject.optInt("friends_count"); userDetail.setStatus_count(status_count); userDetail.setAlbums_count(albums_count); userDetail.setGuestbook_count(guestbook_count); userDetail.setBlogs_count(blogs_count); userDetail.setFriends_count(friends_count); return userDetail; } }, resultCallback); mDefaultThreadPool.execute(asyncHttpsPost); mAsyncRequests.add(asyncHttpsPost); } @Override public void getUserImage(ResultCallback resultCallback) { // 获取用户信息所需的参数 Map<String, String> parameter = new HashMap<String, String>(); parameter.put("v", "1.0"); // API的版本号,固定值为1.0 parameter.put("access_token", accessToken); // OAuth2.0验证授权后获得的token。 parameter.put("format", "JSON"); // 返回值的格式。请指定为JSON或者XML,推荐使用JSON,缺省值为XML parameter.put("call_id", "1.0"); // 请求队列号 parameter.put("method", "users.getInfo"); // 你要访问那个接口,我们肯定调用用获取用户的信息的接口咯,该接口支持批量获取。 parameter.put("uids", uid + ""); // 个人主页用户的Id parameter.put("fields", "zidou,vip,mainurl"); // 返回的字段列表,可以指定返回那些字段,用逗号分隔。 AsyncBaseRequest asyncHttpsPost = new AsyncHttpsPost(Constant.API_SERVER_URL, parameter, new ParseCallback() { @Override public String[] parse(String json) throws JSONException { LogUtil.i(TAG, "getUserImage() json = " + json); // 正常情况下返回的JSON字符串 /*[ { "uid":221659942, "vip":1, "mainurl":"http://hdn.xnimg.cn/photos/hdn221/20130614/1350/h_main_hIfE_e8e9000001ad113e.jpg", "zidou":0 } ]*/ // 异常情况下返回的JSON字符串 /* [ { "uid":600038849, "tinyurl":"http://hdn.xnimg.cn/photos/hdn221/20110212/1700/h_tiny_2ZyG_4a320001f9f62f75.jpg", "vip":1, "sex":1, "name":"折翼の天使", "star":1, "headurl":"http://hdn.xnimg.cn/photos/hdn221/20110212/1700/h_head_jMyd_4a320001f9f62f75.jpg", "zidou":0 } ]*/ JSONArray jsonArray = new JSONArray(json); JSONObject jsonObject = jsonArray.getJSONObject(0); // 是否为vip用户,值1表示是;值0表示不是 final int zidou = jsonObject.optInt("zidou"); LogUtil.i(TAG, "zidou = " + zidou); // 是否为vip用户等级,前提是zidou节点必须为1 final int vip = jsonObject.optInt("vip"); LogUtil.i(TAG, "vip = " + vip); String mainurl = jsonObject.optString("mainurl"); LogUtil.i(TAG, "headurl = " + mainurl); return new String[] { zidou + "", vip + "", mainurl }; } }, resultCallback); mDefaultThreadPool.execute(asyncHttpsPost); mAsyncRequests.add(asyncHttpsPost); } @Override public void getVisitors(int page, int pageSize, ResultCallback resultCallback) { // 获取用户信息所需的参数 Map<String, String> parameter = new HashMap<String, String>(); parameter.put("v", "1.0"); // API的版本号,固定值为1.0 parameter.put("access_token", accessToken); // OAuth2.0验证授权后获得的token。 parameter.put("format", "JSON"); // 返回值的格式。请指定为JSON或者XML,推荐使用JSON,缺省值为XML parameter.put("call_id", "1.0"); // 请求队列号 parameter.put("method", "users.getVisitors"); parameter.put("page", page + ""); // 支持分页,指定页号,页号从1开始,默认值为1 parameter.put("count", pageSize + ""); // 支持分页,指定每页记录数,缺省值为6 AsyncBaseRequest asyncHttpsPost = new AsyncHttpsPost(Constant.API_SERVER_URL, parameter, new ParseCallback() { @Override public LinkedList<UserBasicInfo> parse(String json) throws JSONException { LogUtil.i(TAG, "json = " + json); /* { "visitors": [ {"uid":224036999,"time":"2013-06-28 16:21:38","name":"任少平","headurl":"http://hdn.xnimg.cn/photos/hdn421/20130525/1750/tiny_Soml_ec1300039669113e.jpg"}, {"uid":244003316,"time":"2013-05-28 10:16:04","name":"李妍","headurl":"http://hdn.xnimg.cn/photos/hdn121/20130528/1010/tiny_rGtl_ec530003b2b0113e.jpg"}, {"uid":223577985,"time":"2013-05-09 19:56:48","name":"靳峰","headurl":"http://hdn.xnimg.cn/photos/hdn121/20111111/1800/tiny_Rawe_5958m019117.jpg"}, {"uid":224035532,"time":"2013-05-04 22:45:14","name":"张韦","headurl":"http://hdn.xnimg.cn/photos/hdn421/20120218/2230/h_tiny_abJK_7a8f00067f722f75.jpg"}, {"uid":234353545,"time":"2013-05-01 23:40:58","name":"刘志伟","headurl":"http://hdn.xnimg.cn/photos/hdn121/20110328/1120/tiny_DWhy_83312g019116.jpg"}, {"uid":221273145,"time":"2013-04-29 05:47:50","name":"蔡多","headurl":"http://hdn.xnimg.cn/photos/hdn321/20100426/1915/h_tiny_z5ER_66f0000013cf2f74.jpg"} ] }*/ JSONObject jsonObject = new JSONObject(json); JSONArray jsonVisitors = jsonObject.getJSONArray("visitors"); LinkedList<UserBasicInfo> mUserBasicInfos = new LinkedList<UserBasicInfo>(); for (int i = 0; i < jsonVisitors.length(); i++) { JSONObject jsonUser = jsonVisitors.getJSONObject(i); UserBasicInfo userBasicInfo = new UserBasicInfo(); userBasicInfo.setUid(jsonUser.optInt("uid")); userBasicInfo.setName(jsonUser.optString("name")); userBasicInfo.setHeadurl(jsonUser.optString("headurl")); userBasicInfo.setTime(jsonUser.optString("time")); mUserBasicInfos.add(userBasicInfo); } return mUserBasicInfos; } }, resultCallback); mDefaultThreadPool.execute(asyncHttpsPost); mAsyncRequests.add(asyncHttpsPost); } }
PersonalHomepageManager mHomepageManager = new PersonalHomepageManagerV1(this); mHomepageManager.setUid(uid);用户个人主页信息的处理代码如下:
/** * 用户个人主页信息的处理 */ public void getProfileInfo() { mHomepageManager.getProfileInfo(new ResultCallback() { @Override public void onSuccess(final Object obj) { mHandler.post(new Runnable() { @Override public void run() { if (!(obj instanceof UserDetailInfo)) { // 返回的数据类型有问题 return; } UserDetailInfo userDetail = (UserDetailInfo) obj; // 用户个人主页的信息 String name = userDetail.getName(); LogUtil.i(TAG, "name = " + name); int star = userDetail.getStar(); LogUtil.i(TAG, "star = " + star); String status = userDetail.getStatus(); LogUtil.i(TAG, "status = " + status); tvName.setText(name); // tvName.setText("android_ls"); tvStatusContent.setText(status); if (star == 1) { ivStar.setVisibility(View.VISIBLE); } int friends_count = userDetail.getFriends_count(); LogUtil.i(TAG, "friends_count = " + friends_count); tvFriendsCount.setText(friends_count + "个好友"); int uid = userDetail.getUid(); LogUtil.i(TAG, "uid = " + uid); tvRenrenId.setText("人人ID:" + uid); String network_name = userDetail.getNetwork_name(); if (TextUtils.isEmpty(network_name)) { network_name = ""; } LogUtil.i(TAG, "network_name = " + network_name); tvNetwork.setText("网络:" + network_name); try { String base_info = userDetail.getBase_info(); if (TextUtils.isEmpty(base_info)) { tvGender.setText("性别:"); tvBirth.setText("生日:"); tvHometown.setText("家乡:"); return; } JSONObject jsonBaseInfo = new JSONObject(base_info); JSONObject jsonBirth = jsonBaseInfo.optJSONObject("birth"); JSONObject jsonHometown = jsonBaseInfo.optJSONObject("hometown"); int gender = jsonBaseInfo.optInt("gender"); LogUtil.i(TAG, "gender = " + gender); String birth_month = jsonBirth.optString("birth_month"); if (TextUtils.isEmpty(birth_month)) { birth_month = ""; } LogUtil.i(TAG, "birth_month = " + birth_month); String birth_day = jsonBirth.optString("birth_day"); if (TextUtils.isEmpty(birth_day)) { birth_day = ""; } LogUtil.i(TAG, "birth_day = " + birth_day); String birth_year = jsonBirth.optString("birth_year"); if (TextUtils.isEmpty(birth_year)) { birth_year = ""; } LogUtil.i(TAG, "birth_year = " + birth_year); String province = jsonHometown.optString("province"); if (TextUtils.isEmpty(province)) { province = ""; } LogUtil.i(TAG, "province = " + province); String city = jsonHometown.optString("city"); if (TextUtils.isEmpty(city)) { city = ""; } LogUtil.i(TAG, "city = " + city); String sexString = "男"; if (gender == 0) { sexString = "女"; } tvGender.setText("性别:" + sexString); tvBirth.setText("生日:" + birth_year + "年" + birth_month + "月" + birth_day + "日"); tvHometown.setText("家乡:" + province + " " + city); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } @Override public void onFail(int errorCode) { LogUtil.i(TAG, "freshNewsList errorCode = " + errorCode); } }); }4、当人人官方不再提供对API1.0版本的支持,我们只需要做如下修改:
package com.everyone.android.user.manager; import com.everyone.android.api.NetworkBaseActivity; import com.everyone.android.callback.ResultCallback; /** * 功能描述:基于人人API2.0版本,个人主页请求服务器端数据的实现类 * @author android_ls */ public class PersonalHomepageManagerV2 extends PersonalHomepageManager { public PersonalHomepageManagerV2(NetworkBaseActivity activity) { super(activity); // TODO Auto-generated constructor stub } @Override public void getProfileInfo(ResultCallback resultCallback) { // TODO Auto-generated method stub } @Override public void getUserImage(ResultCallback resultCallback) { // TODO Auto-generated method stub } @Override public void getVisitors(int page, int pageSize, ResultCallback resultCallback) { // TODO Auto-generated method stub } }b.在UI类中修改实例化数据提供类的对象,代码如下:
PersonalHomepageManager mHomepageManager = new PersonalHomepageManagerV2(this);其它的不需要改动,服务器端提供数据的方式发生了改变,我们只需要修改客户端请求数据的方式及解析返回的新格式的数据。
2、点击当前登录用户(android_ls)的图像,修改之前的事件处理代码如下:
ivUserIcon.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent(mActivity,PersonalHomepageActivity.class); intent.putExtra("actor_id", user.getUid()); intent.putExtra("flage", 1); // 这里的标识值随便写了,呵呵 mActivity.startActivity(intent); } });
3、在个人主页界面( PersonalHomepageActivity )的类文件中,添加处理代码如下:
@Override protected void initialized() { Intent intent = this.getIntent(); uid = intent.getIntExtra("actor_id", -1); LogUtil.i(TAG, "uid = " + uid); flage = intent.getIntExtra("flage", -1); LogUtil.i(TAG, "flage = " + flage); // ...... }
4、根据标识flage的值做相应的数据初始化处理。
if(flage == 1){ // 当前登录用户的个人主页 ivIconUpdate.setVisibility(View.VISIBLE); mTexts = this.getResources().getStringArray(R.array.personal_homepage_filter_list); mIcons = new int[]{ R.drawable.v5_0_1_profile_popupwindow_type_visitor_background, R.drawable.v5_0_1_profile_popupwindow_type_minifeed_background, R.drawable.v5_0_1_profile_popupwindow_type_info_background, R.drawable.v5_0_1_profile_popupwindow_type_album_background, R.drawable.v5_0_1_profile_popupwindow_type_status_background, R.drawable.v5_0_1_profile_popupwindow_type_blog_background, R.drawable.v5_0_1_profile_popupwindow_type_share_background }; freshNewsTypes = new String[]{ Constant.PERSONAL_HOMEPAGE_TYPE_LATELY, Constant.FRESH_NEWS_TYPE_ALL, Constant.PERSONAL_HOMEPAGE_TYPE_DATA, Constant.FRESH_NEWS_TYPE_PHOTO, Constant.FRESH_NEWS_TYPE_STATUS, Constant.FRESH_NEWS_TYPE_BLOG, Constant.FRESH_NEWS_TYPE_SHARE }; // 获取当前登录用户的最近来访数据 pageCount = 20; mPHVisitorsAdapter = new PHVisitorsAdapter(this, mUserBasicInfos); mListView.setAdapter(mPHVisitorsAdapter); // 获取最近来访用户的数据 getVisitors(); mTopRightMenus = this.getResources().getStringArray(R.array.personal_homepage_top_right_menu); } else { // 好友的个人主页 mTexts = this.getResources().getStringArray(R.array.friend_homepage_filter_list); mIcons = new int[]{ R.drawable.v5_0_1_profile_popupwindow_type_minifeed_background, R.drawable.v5_0_1_profile_popupwindow_type_info_background, R.drawable.v5_0_1_profile_popupwindow_type_album_background, R.drawable.v5_0_1_profile_popupwindow_type_status_background, R.drawable.v5_0_1_profile_popupwindow_type_blog_background, R.drawable.v5_0_1_profile_popupwindow_type_share_background }; freshNewsTypes = new String[]{Constant.FRESH_NEWS_TYPE_ALL, Constant.PERSONAL_HOMEPAGE_TYPE_DATA, Constant.FRESH_NEWS_TYPE_PHOTO, Constant.FRESH_NEWS_TYPE_STATUS, Constant.FRESH_NEWS_TYPE_BLOG, Constant.FRESH_NEWS_TYPE_SHARE }; mFreshNewsAdapter = new FreshNewsAdapter(this, mFreshNewsList); mListView.setAdapter(mFreshNewsAdapter); // 加载新鲜事数据 getFreshNews(); mTopRightMenus = this.getResources().getStringArray(R.array.friend_homepage_top_right_menu); }
5、获取最近来访用户的数据,网络请求代码如下:
public void getVisitors(int page, int pageSize, ResultCallback resultCallback) { // 获取用户信息所需的参数 Map<String, String> parameter = new HashMap<String, String>(); parameter.put("v", "1.0"); // API的版本号,固定值为1.0 parameter.put("access_token", accessToken); // OAuth2.0验证授权后获得的token。 parameter.put("format", "JSON"); // 返回值的格式。请指定为JSON或者XML,推荐使用JSON,缺省值为XML parameter.put("call_id", "1.0"); // 请求队列号 parameter.put("method", "users.getVisitors"); parameter.put("page", page + ""); // 支持分页,指定页号,页号从1开始,默认值为1 parameter.put("count", pageSize + ""); // 支持分页,指定每页记录数,缺省值为6 AsyncBaseRequest asyncHttpsPost = new AsyncHttpsPost(Constant.API_SERVER_URL, parameter, new ParseCallback() { @Override public LinkedList<UserBasicInfo> parse(String json) throws JSONException { LogUtil.i(TAG, "json = " + json); JSONObject jsonObject = new JSONObject(json); JSONArray jsonVisitors = jsonObject.getJSONArray("visitors"); LinkedList<UserBasicInfo> mUserBasicInfos = new LinkedList<UserBasicInfo>(); for (int i = 0; i < jsonVisitors.length(); i++) { JSONObject jsonUser = jsonVisitors.getJSONObject(i); UserBasicInfo userBasicInfo = new UserBasicInfo(); userBasicInfo.setUid(jsonUser.optInt("uid")); userBasicInfo.setName(jsonUser.optString("name")); userBasicInfo.setHeadurl(jsonUser.optString("headurl")); userBasicInfo.setTime(jsonUser.optString("time")); mUserBasicInfos.add(userBasicInfo); } return mUserBasicInfos; } }, resultCallback); mDefaultThreadPool.execute(asyncHttpsPost); mAsyncRequests.add(asyncHttpsPost); }
6、服务器端请求返回的JSON字符串如下:
{ "visitors": [ {"uid":224036999,"time":"2013-06-28 16:21:38","name":"任少平","headurl":"http://hdn.xnimg.cn/photos/hdn421/20130525/1750/tiny_Soml_ec1300039669113e.jpg"}, {"uid":244003316,"time":"2013-05-28 10:16:04","name":"李妍","headurl":"http://hdn.xnimg.cn/photos/hdn121/20130528/1010/tiny_rGtl_ec530003b2b0113e.jpg"}, {"uid":223577985,"time":"2013-05-09 19:56:48","name":"靳峰","headurl":"http://hdn.xnimg.cn/photos/hdn121/20111111/1800/tiny_Rawe_5958m019117.jpg"}, {"uid":224035532,"time":"2013-05-04 22:45:14","name":"张韦","headurl":"http://hdn.xnimg.cn/photos/hdn421/20120218/2230/h_tiny_abJK_7a8f00067f722f75.jpg"}, {"uid":234353545,"time":"2013-05-01 23:40:58","name":"刘志伟","headurl":"http://hdn.xnimg.cn/photos/hdn121/20110328/1120/tiny_DWhy_83312g019116.jpg"}, {"uid":221273145,"time":"2013-04-29 05:47:50","name":"蔡多","headurl":"http://hdn.xnimg.cn/photos/hdn321/20100426/1915/h_tiny_z5ER_66f0000013cf2f74.jpg"} ] }
7、获取到解析完的数据后,UI做的处理代码如下:
/** * 获取用户最近来访列表 */ public void getVisitors() { mHomepageManager.getVisitors(page, pageCount, new ResultCallback() { @Override public void onSuccess(final Object obj) { mHandler.post(new Runnable() { @Override public void run() { if (obj instanceof LinkedList) { LinkedList<UserBasicInfo> mUsers = (LinkedList<UserBasicInfo>) obj; if (mUsers.size() > 0) { // 下拉刷新的数据去重复处理 if (page == 1 && mUserBasicInfos.size() > 0) { for (UserBasicInfo userInfo : mUsers) { boolean flage = false; for (UserBasicInfo user : mUserBasicInfos) { if (userInfo.getUid() == user.getUid()) { flage = true; } } if (flage == false) { mUserBasicInfos.addFirst(userInfo); } } } else { mUserBasicInfos.addAll(mUsers); } mListView.setPullLoadEnable(true); } else { mListView.setPullLoadEnable(false); } mListView.stopLoadMore(); if (page == 1) { mPHVisitorsAdapter.notifyDataSetInvalidated(); } else { mPHVisitorsAdapter.notifyDataSetChanged(); } } } }); } @Override public void onFail(int errorCode) { // TODO Auto-generated method stub } }); }
8、最近来访用户列表数据适配器类(PHVisitorsAdapter),代码如下:
package com.everyone.android.ui.user; import java.util.LinkedList; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import com.everyone.android.R; import com.everyone.android.api.NetworkBaseActivity; import com.everyone.android.bitmap.ImageLoader; import com.everyone.android.entity.ImageInfo; import com.everyone.android.entity.UserBasicInfo; import com.everyone.android.utils.DateUtil; import com.everyone.android.utils.DensityUtil; import com.everyone.android.utils.LogUtil; /** * 功能描述:当前登录用户的个人主页,最近来访用户列表数据适配器 * 注:完整的类名应该是PersonalHomepageVisitorsAdapter,我觉得有些长就简写为PHVisitorsAdapter * @author android_ls */ public class PHVisitorsAdapter extends BaseAdapter { private NetworkBaseActivity mActivity; private LinkedList<UserBasicInfo> mUserBasicInfos; private LayoutInflater mInflater; private ImageLoader mImageLoader; public PHVisitorsAdapter(NetworkBaseActivity activity, LinkedList<UserBasicInfo> userBasicInfo) { this.mActivity = activity; this.mUserBasicInfos = userBasicInfo; this.mInflater = LayoutInflater.from(mActivity); this.mImageLoader = new ImageLoader(mActivity); } public int getCount() { return mUserBasicInfos.size(); } public Object getItem(int position) { return mUserBasicInfos.get(position); } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { convertView = mInflater.inflate(R.layout.personal_homepage_visitors_item, null); holder = new ViewHolder(); holder.imageView = (ImageView) convertView.findViewById(R.id.iv_icon); holder.textView1 = (TextView) convertView.findViewById(R.id.tv_name); holder.button = (Button) convertView.findViewById(R.id.btn_action); holder.textView2 = (TextView) convertView.findViewById(R.id.tv_time); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } UserBasicInfo userBasicInfo = mUserBasicInfos.get(position); // 加载图像 String headurl = userBasicInfo.getHeadurl(); LogUtil.i("", "headurl = " + headurl); if (!TextUtils.isEmpty(headurl)) { int widthPx = DensityUtil.dip2px(mActivity, 43); ImageInfo imgInfo = new ImageInfo(holder.imageView, headurl, widthPx, widthPx); mImageLoader.displayImage(imgInfo); } holder.textView1.setText(userBasicInfo.getName()); holder.textView2.setText(DateUtil.getMachTime(userBasicInfo.getTime())); holder.button.setText("聊 天"); holder.button.setOnClickListener(new OnClickListener() { public void onClick(View v) { } }); return convertView; } static class ViewHolder { public ImageView imageView; public TextView textView1; public Button button; public TextView textView2; } }
9、最近来访用户列表Item的布局文件(personal_homepage_visitors_item.xml),其配置内容如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#FFFFFF" android:padding="10dip" > <ImageView android:id="@+id/iv_icon" android:layout_width="43dip" android:layout_height="43dip" android:scaleType="centerCrop" android:src="@drawable/v5_0_1_widget_default_head" /> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dip" android:layout_toRightOf="@+id/iv_icon" android:textColor="#ff005092" android:textSize="16sp" /> <Button android:id="@+id/btn_action" android:layout_width="80dip" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:background="@drawable/v5_0_1_guide_button_black_background" android:gravity="center" android:text="聊 天" android:textColor="#ff005092" android:textSize="14sp" /> <TextView android:id="@+id/tv_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/tv_name" android:layout_below="@+id/tv_name" android:layout_marginTop="5dip" android:textColor="#ff888888" android:textSize="12sp" /> </RelativeLayout>
10、最近来访用户列表,运行后的效果图如下:
11、最近来访与顶部下拉菜单列表中其它选项的切换处理。
先看下个人主页界面的布局文件(personal_homepage.xml)如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#FFFFFF" android:orientation="vertical" > <com.everyone.android.widget.TopMenuNavbar android:id="@+id/rl_top_menu_navbar" style="@style/top_navbar" /> <com.everyone.android.widget.XListView android:id="@+id/listview" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#00000000" android:cacheColorHint="#00000000" android:divider="@drawable/v5_0_1_newsfeed_divider" android:listSelector="@null" android:fastScrollEnabled="true" /> </LinearLayout>
大家仔细查看后,觉得与前面文章中贴出的布局文件中的配置一样,没有什么更改。个人主页header部分基本上是不变的,而列表区域,好友的个人主页分为:用户基本信息和与新鲜事有关的数据的展示,也就是说列表的Item的布局文件是一样的。当前登录用户的个人主页分为:用户基本信息、与新鲜事有关的数据和最近来访用户列表的展示,最近来访用户列表的Item与新鲜事列表的Item肯定是不一样,这里牵扯到的是一个ListView组件,两个adapter的来回切换的问题。
a. 初始化数据时的处理,代码如下:
if (flage == 1) { mPHVisitorsAdapter = new PHVisitorsAdapter(this, mUserBasicInfos); mListView.setAdapter(mPHVisitorsAdapter); // 获取最近来访用户的数据 getVisitors(); }else{ mFreshNewsAdapter = new FreshNewsAdapter(this, mFreshNewsList); mListView.setAdapter(mFreshNewsAdapter); // 加载新鲜事数据 getFreshNews(); }
b. 在顶部下拉菜单Item的单击事件处理器中的处理。
mListView.setPullLoadEnable(false); mListView.setPullRefreshEnable(false); if (mFreshNewsAdapter != null) { mFreshNewsList.clear(); mFreshNewsAdapter.notifyDataSetChanged(); } if (mPHVisitorsAdapter != null) { mUserBasicInfos.clear(); mPHVisitorsAdapter.notifyDataSetChanged(); } // 最近来访,当前登录的用户,只能能查看自己的最近来访好友 if (Constant.PERSONAL_HOMEPAGE_TYPE_LATELY.equals(fresh_news_type)) { // 获取当前登录用户的最近来访数据 if (mPHVisitorsAdapter != null) { mListView.setAdapter(mPHVisitorsAdapter); } page = 1; pageCount = 20; getVisitors(); } else if (Constant.PERSONAL_HOMEPAGE_TYPE_DATA.equals(fresh_news_type)) { // 资料 tvType.setText("好友信息"); mListView.addHeaderView(mBasicInfoView); } else { if (mFreshNewsAdapter == null) { mFreshNewsAdapter = new FreshNewsAdapter(PersonalHomepageActivity.this, mFreshNewsList); } mListView.setAdapter(mFreshNewsAdapter); mListView.removeHeaderView(mBasicInfoView); page = 1; pageCount = 30; getFreshNews(); }
c. 运行程序,看看来回切换的效果图如下:
最近来访,运行后的效果图如下:
新鲜事,运行后的效果图如下:
资料,运行后的效果图如下:
状态,运行后的效果图如下:
相册,运行后的效果图如下:
其它的就不一一贴图了,大家看到基本上与好友的个人主页界面效果是一样的。
三、修改(当前登录用户)用户图像处理。
1、根据标识,判断是否要显示修改图像组件。
if (flage == 1) { // 当前登录用户的个人主页 ivIconUpdate.setVisibility(View.VISIBLE); }
2、在 public void onClick(View v) {}中添加事件处理
case R.id.iv_icon_update: // 更改用户图像 photoDialog(); break;
3、调用系统相机或者从相册中选取照片,代码处理如下:
/** * 修改用户图像的Dialog */ private void photoDialog() { AlertDialog.Builder builder = new Builder(PersonalHomepageActivity.this); builder.setTitle("修改图像"); builder.setItems(new String[] { "拍照", "从相册中选取" }, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Intent intent = null; switch (which) { case 0: String rootDir = Constant.getRootDir(mContext); File dir = new File(rootDir + File.separator + Constant.IMAGE_CAMERA_UPLOAD_PATH); if (!dir.exists()) { dir.mkdirs(); } mUploadPhotoPath = rootDir + "/" + Constant.IMAGE_CAMERA_UPLOAD_PATH + "/" + UUID.randomUUID().toString(); File file = new File(mUploadPhotoPath); intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); startActivityForResult(intent, Constant.REQUEST_CAMERA_CODE); break; case 1: Intent getImage = new Intent(Intent.ACTION_GET_CONTENT); getImage.addCategory(Intent.CATEGORY_OPENABLE); getImage.setType("image/*"); startActivityForResult(getImage, Constant.REQUEST_GALLERY_CODE); break; } } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); builder.create().show(); }
4、 调用系统相机拍完照片或者从相册中选取照片后的处理
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (Constant.REQUEST_CAMERA_CODE == requestCode) { if (resultCode == Activity.RESULT_OK) { File file = new File(mUploadPhotoPath); if (file.exists()) { show("拍摄的照片已存好"); cropPhoto(Uri.fromFile(file)); } } else { show("取消了拍照"); } } else if (Constant.REQUEST_GALLERY_CODE == requestCode) { if (resultCode == Activity.RESULT_OK) { Uri uri = data.getData(); show("照片已选取"); cropPhoto(uri); } else { show("取消了选取照片"); } } else if (Constant.REQUEST_CROP_PHOTO_CODE == requestCode) { if (resultCode == Activity.RESULT_OK) { savePhoto(data); } else { show("取消了剪裁照片"); } } }
5、剪裁照片的处理代码如下:
/** * 调用系统裁剪照片应用 * @param uri Uri */ private void cropPhoto(Uri uri) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("outputX", 200); intent.putExtra("outputY", 200); intent.putExtra("scale", true); intent.putExtra("noFaceDetection", true); intent.putExtra("return-data", true); startActivityForResult(intent, Constant.REQUEST_CROP_PHOTO_CODE); }
6、更换用户图像,并将新的用户图像保存到服务器端。
/** * 改换用户图像并将修改保存到服务器端 * @param data Intent */ private void savePhoto(Intent intent) { Bundle extras = intent.getExtras(); if (extras != null) { Bitmap bitmap = extras.getParcelable("data"); if (bitmap != null) { show("裁剪照片成功"); ivIconView.setImageBitmap(bitmap); // 将剪裁后的图片转换成byte数组,上传到服务器端即可 /* ByteArrayOutputStream outStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream); byte[] data = outStream.toByteArray();*/ } } else { show("获取裁剪照片出错"); } }
注:人人开放平台没有提供相关接口,故这里只是在UI层做了实现。
7、运行后的效果图:
修改用户图像前的截图:
点击修改用户图像图标, 调用系统照相机
选取拍照项,效果图如下:
拍照完毕,剪裁图片效果图如下:
修改完图像后,截图如下:
从相册选取图片后的流程与拍照完毕的处理流程一直,这里就不贴效果图了。这一篇文章里,图片已经很多了,再贴以后这篇文章就打不开了。呵呵
四、个人主页UI类,完整代码如下:
package com.everyone.android.ui.user; import java.io.File; import java.text.SimpleDateFormat; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.UUID; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.net.Uri; import android.os.Bundle; import android.os.Looper; import android.provider.MediaStore; import android.text.TextUtils; import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.FrameLayout.LayoutParams; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.PopupWindow; import android.widget.RelativeLayout; import android.widget.TextView; import com.everyone.android.R; import com.everyone.android.api.NetworkBaseActivity; import com.everyone.android.bitmap.ImageLoader; import com.everyone.android.callback.ParseCallback; import com.everyone.android.callback.ResultCallback; import com.everyone.android.entity.FreshNews; import com.everyone.android.entity.ImageInfo; import com.everyone.android.entity.UserBasicInfo; import com.everyone.android.entity.UserDetailInfo; import com.everyone.android.net.AsyncHttpsPost; import com.everyone.android.ui.freshnews.FreshNewsAdapter; import com.everyone.android.ui.freshnews.FreshNewsPopupAdapter; import com.everyone.android.user.manager.PersonalHomepageManager; import com.everyone.android.user.manager.PersonalHomepageManagerV1; import com.everyone.android.utils.Constant; import com.everyone.android.utils.LogUtil; import com.everyone.android.widget.TopMenuNavbar; import com.everyone.android.widget.XListView; import com.everyone.android.widget.XListView.IXListViewListener; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; /** * 功能描述:个人主页(当前登录用户的个人主页或者好友的个人主页) * @author android_ls */ public class PersonalHomepageActivity extends NetworkBaseActivity implements IXListViewListener, OnClickListener { /** * LOG打印标签 */ private static final String TAG = PersonalHomepageActivity.class.getSimpleName(); private TopMenuNavbar topMenuNavbar; private XListView mListView; private FreshNewsAdapter mFreshNewsAdapter; /** * 新鲜事信息集合 */ private LinkedList<FreshNews> mFreshNewsList = new LinkedList<FreshNews>(); /** * 用户信息唯一标识 */ private int uid; /** * 用户标识,若值为1,表示是当登录账号对应的用户 */ private int flage; /** * 每一页记录数,默认值为30,最大50 */ private int pageCount = 30; /** * 当前获取第几页,默认值为1 */ private int page = 1; private LayoutInflater mInflater; // 用户图像 private ImageView ivIconView; // 用户名 private TextView tvName; // 表示该用户是否为星级用户 1表示该用户是星级用户,0表示否 private ImageView ivStar; // 用户状态信息 private TextView tvStatusContent; // 是否为VIP用户 private Button btnVip; /** * 更改用户图像 */ private ImageView ivIconUpdate; /** * 显示当前过滤的信息所属的类型 */ private TextView tvType; /** * 指定信息类型的总数 */ private TextView tvTypeCount; /** * 新鲜事类型,默认为当前所支持的全部类型 */ private String fresh_news_type = Constant.FRESH_NEWS_TYPE_ALL; private PopupWindow mPopupWindow; /** * 顶部下拉列表 */ private ListView mPopupListView; /** * 顶部下拉列表数据适配器 */ private FreshNewsPopupAdapter mPopupAdapter; /** * 顶部下拉列表的操作提示文本数组 */ private String[] mTexts; /** * 新鲜事类型数组 */ private String[] freshNewsTypes; /** * 顶部下拉列表的操作指示图标Id数组 */ private int[] mIcons; private LinearLayout mBasicInfoView; private TextView tvRenrenId; private TextView tvGender; private TextView tvBirth; private TextView tvHometown; private TextView tvNetwork; private RelativeLayout rlFriends; private TextView tvFriendsCount; /** * 个人主页管理类 */ private PersonalHomepageManager mHomepageManager; private SimpleDateFormat mDateFormat; /** * 最近访问的用户集合 */ private LinkedList<UserBasicInfo> mUserBasicInfos = new LinkedList<UserBasicInfo>(); /** * 最近来访的好友列表数据适配器(数据填充) */ private PHVisitorsAdapter mPHVisitorsAdapter; /** * 记录顶部下拉列表,当前选中项的位置下标 */ private int mPosition; /** * 顶部右侧下拉菜单文本数组 */ private String[] mTopRightMenus; /** * 顶部右侧Menu键关联的下拉菜单 */ private PopupWindow menuPopupWindow; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 初始化顶部下拉菜单组件 setupPopupWindow(); setupTopMenu(); } @Override protected int getLayoutId() { return R.layout.personal_homepage; } /** * 初始化顶部下拉菜单组件 */ private void setupPopupWindow() { View view = mInflater.inflate(R.layout.fresh_news_popupwindow, null); mPopupWindow = new PopupWindow(view, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, true); mPopupWindow.setBackgroundDrawable(new BitmapDrawable()); mPopupWindow.setAnimationStyle(R.style.fresh_news_popup_animation); mPopupListView = (ListView) view.findViewById(R.id.popup_listview); mPopupAdapter = new FreshNewsPopupAdapter(this, mIcons, mTexts); mPopupListView.setAdapter(mPopupAdapter); // 设置默认选中下拉列表中的第一项 fresh_news_type = freshNewsTypes[0]; mPopupAdapter.setPosition(0); mPopupAdapter.notifyDataSetChanged(); topMenuNavbar.tvTitle.setText(mTexts[0]); tvType.setText(mTexts[0]); // 设置顶部下拉菜单的Item事件处理 mPopupListView.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { mPopupWindow.dismiss(); // 当前选择的项与之前的一样,则不做处理。 if (mPopupAdapter.getPosition() == position) { return; } mPosition = position; // 新鲜事过滤事件处理 fresh_news_type = freshNewsTypes[position]; LogUtil.i(TAG, "onItemClick position = " + position); LogUtil.i(TAG, "onItemClick fresh_news_type = " + fresh_news_type); mPopupAdapter.setPosition(position); mPopupAdapter.notifyDataSetChanged(); topMenuNavbar.tvTitle.setText(mTexts[position]); tvType.setText(mTexts[position]); mListView.setPullLoadEnable(false); mListView.setPullRefreshEnable(false); if (mFreshNewsAdapter != null) { mFreshNewsList.clear(); mFreshNewsAdapter.notifyDataSetChanged(); } if (mPHVisitorsAdapter != null) { mUserBasicInfos.clear(); mPHVisitorsAdapter.notifyDataSetChanged(); } // 最近来访,当前登录的用户,只能能查看自己的最近来访好友 if (Constant.PERSONAL_HOMEPAGE_TYPE_LATELY.equals(fresh_news_type)) { // 获取当前登录用户的最近来访数据 if (mPHVisitorsAdapter != null) { mListView.setAdapter(mPHVisitorsAdapter); } page = 1; pageCount = 20; getVisitors(); } else if (Constant.PERSONAL_HOMEPAGE_TYPE_DATA.equals(fresh_news_type)) { // 资料 tvType.setText("好友信息"); mListView.addHeaderView(mBasicInfoView); } else { if (mFreshNewsAdapter == null) { mFreshNewsAdapter = new FreshNewsAdapter(PersonalHomepageActivity.this, mFreshNewsList); } mListView.setAdapter(mFreshNewsAdapter); mListView.removeHeaderView(mBasicInfoView); page = 1; pageCount = 30; getFreshNews(); } } }); } @Override protected void setupViews() { topMenuNavbar = (TopMenuNavbar) this.findViewById(R.id.rl_top_menu_navbar); topMenuNavbar.tvRightOperationName.setVisibility(View.GONE); topMenuNavbar.ivRightLine.setVisibility(View.GONE); // 将顶部左侧的menu图标换成back图标 LinearLayout llBackMenu = topMenuNavbar.llShowMenu; ImageView ivBack = (ImageView) llBackMenu.findViewById(R.id.iv_back); ivBack.setImageResource(R.drawable.v5_0_1_flipper_head_back); // 将顶部右侧的刷新按钮换成下拉菜单图标 LinearLayout llDownOperation = topMenuNavbar.mLlRefresh; ImageView ivOperation = (ImageView) llDownOperation.findViewById(R.id.iv_refresh); ivOperation.setImageResource(R.drawable.v5_0_1_flipper_head_menu); llBackMenu.setOnClickListener(this); llDownOperation.setOnClickListener(this); topMenuNavbar.mLlDownList.setOnClickListener(this); mListView = (XListView) this.findViewById(R.id.listview); mListView.setPullLoadEnable(false); mListView.setPullRefreshEnable(false); mListView.setXListViewListener(this); // HeadView组件 mInflater = LayoutInflater.from(this.getContext()); LinearLayout mHeadView = (LinearLayout) mInflater.inflate(R.layout.personal_homepage_head, null); mListView.addHeaderView(mHeadView); tvName = (TextView) mHeadView.findViewById(R.id.tv_name); ivIconView = (ImageView) mHeadView.findViewById(R.id.iv_icon); ivStar = (ImageView) mHeadView.findViewById(R.id.iv_star); tvStatusContent = (TextView) mHeadView.findViewById(R.id.tv_status_content); btnVip = (Button) mHeadView.findViewById(R.id.btn_vip); tvType = (TextView) mHeadView.findViewById(R.id.tv_type); tvTypeCount = (TextView) mHeadView.findViewById(R.id.tv_type_count); ivIconUpdate = (ImageView) mHeadView.findViewById(R.id.iv_icon_update); ivIconUpdate.setOnClickListener(this); // 用户基本信息组件 mBasicInfoView = (LinearLayout) mInflater.inflate(R.layout.personal_homepage_user_basic, null); tvRenrenId = (TextView) mBasicInfoView.findViewById(R.id.tv_renren_id); tvGender = (TextView) mBasicInfoView.findViewById(R.id.tv_gender); tvBirth = (TextView) mBasicInfoView.findViewById(R.id.tv_birth); tvHometown = (TextView) mBasicInfoView.findViewById(R.id.tv_hometown); tvNetwork = (TextView) mBasicInfoView.findViewById(R.id.tv_network); // 好友的数量 rlFriends = (RelativeLayout) mBasicInfoView.findViewById(R.id.rl_friends); tvFriendsCount = (TextView) mBasicInfoView.findViewById(R.id.tv_friends_count); rlFriends.setOnClickListener(this); } @Override protected void initialized() { Intent intent = this.getIntent(); uid = intent.getIntExtra("actor_id", -1); LogUtil.i(TAG, "uid = " + uid); flage = intent.getIntExtra("flage", -1); LogUtil.i(TAG, "flage = " + flage); mDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); mHomepageManager = new PersonalHomepageManagerV1(this); mHomepageManager.setUid(uid); getProfileInfo(); getUserImage(); if (flage == 1) { // 当前登录用户的个人主页 ivIconUpdate.setVisibility(View.VISIBLE); mTexts = this.getResources().getStringArray(R.array.personal_homepage_filter_list); mIcons = new int[] { R.drawable.v5_0_1_profile_popupwindow_type_visitor_background, R.drawable.v5_0_1_profile_popupwindow_type_minifeed_background, R.drawable.v5_0_1_profile_popupwindow_type_info_background, R.drawable.v5_0_1_profile_popupwindow_type_album_background, R.drawable.v5_0_1_profile_popupwindow_type_status_background, R.drawable.v5_0_1_profile_popupwindow_type_blog_background, R.drawable.v5_0_1_profile_popupwindow_type_share_background }; freshNewsTypes = new String[] { Constant.PERSONAL_HOMEPAGE_TYPE_LATELY, Constant.FRESH_NEWS_TYPE_ALL, Constant.PERSONAL_HOMEPAGE_TYPE_DATA, Constant.FRESH_NEWS_TYPE_PHOTO, Constant.FRESH_NEWS_TYPE_STATUS, Constant.FRESH_NEWS_TYPE_BLOG, Constant.FRESH_NEWS_TYPE_SHARE }; // 获取当前登录用户的最近来访数据 pageCount = 20; mPHVisitorsAdapter = new PHVisitorsAdapter(this, mUserBasicInfos); mListView.setAdapter(mPHVisitorsAdapter); // 获取最近来访用户的数据 getVisitors(); mTopRightMenus = this.getResources().getStringArray(R.array.personal_homepage_top_right_menu); } else { // 好友的个人主页 mTexts = this.getResources().getStringArray(R.array.friend_homepage_filter_list); mIcons = new int[] { R.drawable.v5_0_1_profile_popupwindow_type_minifeed_background, R.drawable.v5_0_1_profile_popupwindow_type_info_background, R.drawable.v5_0_1_profile_popupwindow_type_album_background, R.drawable.v5_0_1_profile_popupwindow_type_status_background, R.drawable.v5_0_1_profile_popupwindow_type_blog_background, R.drawable.v5_0_1_profile_popupwindow_type_share_background }; freshNewsTypes = new String[] { Constant.FRESH_NEWS_TYPE_ALL, Constant.PERSONAL_HOMEPAGE_TYPE_DATA, Constant.FRESH_NEWS_TYPE_PHOTO, Constant.FRESH_NEWS_TYPE_STATUS, Constant.FRESH_NEWS_TYPE_BLOG, Constant.FRESH_NEWS_TYPE_SHARE }; mFreshNewsAdapter = new FreshNewsAdapter(this, mFreshNewsList); mListView.setAdapter(mFreshNewsAdapter); // 加载新鲜事数据 getFreshNews(); mTopRightMenus = this.getResources().getStringArray(R.array.friend_homepage_top_right_menu); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.ll_back: onBackPressed(); break; case R.id.ll_down_list: if (mPopupWindow != null) { mPopupWindow.showAsDropDown(topMenuNavbar); } break; case R.id.rl_friends: // 切换到好友列表界面 break; case R.id.iv_icon_update: // 更改用户图像 photoDialog(); break; case R.id.ll_refresh: // 顶部右侧的下拉菜单 if (menuPopupWindow != null) { menuPopupWindow.showAsDropDown(topMenuNavbar.mLlRefresh); } break; default: break; } } /** * 设置顶部右侧的菜单按钮 */ public void setupTopMenu() { ArrayAdapter<String> menuAdapter = new ArrayAdapter<String>(this, R.layout.personal_homepage_popupwindow_item, R.id.tv_name, mTopRightMenus); LinearLayout layout = (LinearLayout) mInflater.inflate(R.layout.personal_homepage_popupwindow, null); ListView listView = (ListView) layout.findViewById(R.id.lv_top_right_menu); listView.setAdapter(menuAdapter); DisplayMetrics metric = new DisplayMetrics(); this.getWindowManager().getDefaultDisplay().getMetrics(metric); int width = metric.widthPixels; menuPopupWindow = new PopupWindow(layout, (width / 2 - 10), LayoutParams.WRAP_CONTENT, true); menuPopupWindow.setBackgroundDrawable(new BitmapDrawable()); menuPopupWindow.setAnimationStyle(R.style.fresh_news_popup_animation); } /** * 存放拍照上传的照片路径 */ public String mUploadPhotoPath; /** * 修改用户图像的Dialog */ private void photoDialog() { AlertDialog.Builder builder = new Builder(PersonalHomepageActivity.this); builder.setTitle("修改图像"); builder.setItems(new String[] { "拍照", "从相册中选取" }, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Intent intent = null; switch (which) { case 0: String rootDir = Constant.getRootDir(mContext); File dir = new File(rootDir + File.separator + Constant.IMAGE_CAMERA_UPLOAD_PATH); if (!dir.exists()) { dir.mkdirs(); } mUploadPhotoPath = rootDir + "/" + Constant.IMAGE_CAMERA_UPLOAD_PATH + "/" + UUID.randomUUID().toString(); File file = new File(mUploadPhotoPath); intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); startActivityForResult(intent, Constant.REQUEST_CAMERA_CODE); break; case 1: Intent getImage = new Intent(Intent.ACTION_GET_CONTENT); getImage.addCategory(Intent.CATEGORY_OPENABLE); getImage.setType("image/*"); startActivityForResult(getImage, Constant.REQUEST_GALLERY_CODE); break; } } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); builder.create().show(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (Constant.REQUEST_CAMERA_CODE == requestCode) { if (resultCode == Activity.RESULT_OK) { File file = new File(mUploadPhotoPath); if (file.exists()) { show("拍摄的照片已存好"); cropPhoto(Uri.fromFile(file)); } } else { show("取消了拍照"); } } else if (Constant.REQUEST_GALLERY_CODE == requestCode) { if (resultCode == Activity.RESULT_OK) { Uri uri = data.getData(); show("照片已选取"); cropPhoto(uri); } else { show("取消了选取照片"); } } else if (Constant.REQUEST_CROP_PHOTO_CODE == requestCode) { if (resultCode == Activity.RESULT_OK) { savePhoto(data); } else { show("取消了剪裁照片"); } } } /** * 调用系统裁剪照片应用 * @param uri Uri */ private void cropPhoto(Uri uri) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("outputX", 200); intent.putExtra("outputY", 200); intent.putExtra("scale", true); intent.putExtra("noFaceDetection", true); intent.putExtra("return-data", true); startActivityForResult(intent, Constant.REQUEST_CROP_PHOTO_CODE); } /** * 改换用户图像并将修改保存到服务器端 * @param data Intent */ private void savePhoto(Intent intent) { Bundle extras = intent.getExtras(); if (extras != null) { Bitmap bitmap = extras.getParcelable("data"); if (bitmap != null) { show("裁剪照片成功"); ivIconView.setImageBitmap(bitmap); // 将剪裁后的图片转换成byte数组,上传到服务器端即可 /* ByteArrayOutputStream outStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream); byte[] data = outStream.toByteArray();*/ } } else { show("获取裁剪照片出错"); } } // 下拉刷新 @Override public void onRefresh() { page = 1; getFreshNews(); // 最近来访的用户列表,只支持加载更多 /* if(mPosition == 0 && flage == 1){ getVisitors(); } else { getFreshNews(); }*/ } // 加载更多 @Override public void onLoadMore() { page++; if (mPosition == 0 && flage == 1) { getVisitors(); } else { getFreshNews(); } } /** * 获取用户最近来访列表 */ public void getVisitors() { mHomepageManager.getVisitors(page, pageCount, new ResultCallback() { @Override public void onSuccess(final Object obj) { mHandler.post(new Runnable() { @Override public void run() { if (obj instanceof LinkedList) { LinkedList<UserBasicInfo> mUsers = (LinkedList<UserBasicInfo>) obj; if (mUsers.size() > 0) { // 下拉刷新的数据去重复处理 if (page == 1 && mUserBasicInfos.size() > 0) { for (UserBasicInfo userInfo : mUsers) { boolean flage = false; for (UserBasicInfo user : mUserBasicInfos) { if (userInfo.getUid() == user.getUid()) { flage = true; } } if (flage == false) { mUserBasicInfos.addFirst(userInfo); } } } else { mUserBasicInfos.addAll(mUsers); } mListView.setPullLoadEnable(true); } else { mListView.setPullLoadEnable(false); } mListView.stopLoadMore(); if (page == 1) { mPHVisitorsAdapter.notifyDataSetInvalidated(); } else { mPHVisitorsAdapter.notifyDataSetChanged(); } } } }); } @Override public void onFail(int errorCode) { // TODO Auto-generated method stub } }); } /** * 用户个人主页信息的处理 */ public void getProfileInfo() { mHomepageManager.getProfileInfo(new ResultCallback() { @Override public void onSuccess(final Object obj) { mHandler.post(new Runnable() { @Override public void run() { if (!(obj instanceof UserDetailInfo)) { // 返回的数据类型有问题 return; } UserDetailInfo userDetail = (UserDetailInfo) obj; // 用户个人主页的信息 String name = userDetail.getName(); LogUtil.i(TAG, "name = " + name); int star = userDetail.getStar(); LogUtil.i(TAG, "star = " + star); String status = userDetail.getStatus(); LogUtil.i(TAG, "status = " + status); tvName.setText(name); // tvName.setText("android_ls"); tvStatusContent.setText(status); if (star == 1) { ivStar.setVisibility(View.VISIBLE); } int friends_count = userDetail.getFriends_count(); LogUtil.i(TAG, "friends_count = " + friends_count); tvFriendsCount.setText(friends_count + "个好友"); int uid = userDetail.getUid(); LogUtil.i(TAG, "uid = " + uid); tvRenrenId.setText("人人ID:" + uid); String network_name = userDetail.getNetwork_name(); if (TextUtils.isEmpty(network_name)) { network_name = ""; } LogUtil.i(TAG, "network_name = " + network_name); tvNetwork.setText("网络:" + network_name); try { String base_info = userDetail.getBase_info(); if (TextUtils.isEmpty(base_info)) { tvGender.setText("性别:"); tvBirth.setText("生日:"); tvHometown.setText("家乡:"); return; } JSONObject jsonBaseInfo = new JSONObject(base_info); JSONObject jsonBirth = jsonBaseInfo.optJSONObject("birth"); JSONObject jsonHometown = jsonBaseInfo.optJSONObject("hometown"); int gender = jsonBaseInfo.optInt("gender"); LogUtil.i(TAG, "gender = " + gender); String birth_month = jsonBirth.optString("birth_month"); if (TextUtils.isEmpty(birth_month)) { birth_month = ""; } LogUtil.i(TAG, "birth_month = " + birth_month); String birth_day = jsonBirth.optString("birth_day"); if (TextUtils.isEmpty(birth_day)) { birth_day = ""; } LogUtil.i(TAG, "birth_day = " + birth_day); String birth_year = jsonBirth.optString("birth_year"); if (TextUtils.isEmpty(birth_year)) { birth_year = ""; } LogUtil.i(TAG, "birth_year = " + birth_year); String province = jsonHometown.optString("province"); if (TextUtils.isEmpty(province)) { province = ""; } LogUtil.i(TAG, "province = " + province); String city = jsonHometown.optString("city"); if (TextUtils.isEmpty(city)) { city = ""; } LogUtil.i(TAG, "city = " + city); String sexString = "男"; if (gender == 0) { sexString = "女"; } tvGender.setText("性别:" + sexString); tvBirth.setText("生日:" + birth_year + "年" + birth_month + "月" + birth_day + "日"); tvHometown.setText("家乡:" + province + " " + city); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } @Override public void onFail(int errorCode) { LogUtil.i(TAG, "freshNewsList errorCode = " + errorCode); } }); } /** * 获取用户的图像 */ public void getUserImage() { mHomepageManager.getUserImage(new ResultCallback() { @Override public void onSuccess(final Object obj) { mHandler.post(new Runnable() { @Override public void run() { String[] result = (String[]) obj; // 是否为vip用户,值1表示是;值0表示不是 final int zidou = Integer.parseInt(result[0]); LogUtil.i(TAG, "zidou = " + zidou); // 是否为vip用户等级,前提是zidou节点必须为1 final int vip = Integer.parseInt(result[1]); LogUtil.i(TAG, "vip = " + vip); if (zidou == 1) { btnVip.setVisibility(View.VISIBLE); btnVip.setText("VIP" + vip); } String imageUrl = result[2]; LogUtil.i(TAG, "imageUrl = " + imageUrl); if (TextUtils.isEmpty(imageUrl)) { LogUtil.i(TAG, "用户图像对应的URL为null"); return; } ImageInfo imgInfo = new ImageInfo(ivIconView, imageUrl); new ImageLoader(PersonalHomepageActivity.this).displayImage(imgInfo); } }); } @Override public void onFail(int errorCode) { // TODO Auto-generated method stub } }); } /** * 向服务器端请求新鲜事的数据 */ public void getFreshNews() { String accessToken = mAuthTokenManager.getAccessToken(); LogUtil.e(TAG, "accessToken = " + accessToken); Map<String, String> parameter = new HashMap<String, String>(); parameter.put("v", "1.0"); // API的版本号,固定值为1.0 parameter.put("access_token", accessToken); // OAuth2.0验证授权后获得的token。 parameter.put("format", "JSON"); // 返回值的格式。请指定为JSON或者XML parameter.put("call_id", "1.0"); // 请求队列号 parameter.put("method", "feed.get"); parameter.put("type", fresh_news_type); // 新鲜事的类别,多个类型以逗号分隔,type列表 parameter.put("uid", uid + ""); // 支持传入当前用户的一个好友ID,表示获取此好友的新鲜事,如果不传,默认为获取当前用户的新鲜事 parameter.put("page", page + ""); // 支持分页,指定页号,页号从1开始,默认值为1 parameter.put("count", pageCount + ""); // 支持分页,每一页记录数,默认值为30,最大50 AsyncHttpsPost asyncHttpsPost = new AsyncHttpsPost(Constant.API_SERVER_URL, parameter, new ParseCallback() { @Override public LinkedList<FreshNews> parse(String json) throws JSONException { LogUtil.i(TAG, "getFreshNews() json = " + json); if ("[]".equals(json)) { Looper.prepare(); show("没有数据可加载!"); Looper.loop(); return null; } // 判断返回值不是JSONArray类型的,可能是出错了 if (!json.substring(0, 1).equals("[")) { JSONObject jsonObject = new JSONObject(json); int error_code = jsonObject.optInt("error_code"); if (error_code == 200) { Looper.prepare(); show("抱歉,该用户未对第三方应用,授予访问她的个人主页的权限。"); Looper.loop(); return null; } } /*{"request_args": [ {"value":"600038849","key":"uid"}, {"value":"1.0","key":"v"}, {"value":"30","key":"count"}, {"value":"1","key":"page"}, {"value":"feed.get","key":"method"}, {"value":"JSON","key":"format"}, {"value":"10,11,20,21,22,23,30,31,32,33,34,35,36","key":"type"}, {"value":"1.0","key":"call_id"}, {"value":"195789|6.13c88bc61edd3f85b7e9cc658cc2f504.2592000.1375952400-461345584","key":"access_token"} ], "error_code":200, "error_msg":"没有权限进行操作" }*/ Gson gson = new Gson(); java.lang.reflect.Type type = new TypeToken<LinkedList<FreshNews>>() { }.getType(); LinkedList<FreshNews> freshNewsList = gson.fromJson(json, type); LogUtil.e(TAG, "freshNewsList = " + freshNewsList.size()); return freshNewsList; } }, new ResultCallback() { @Override public void onSuccess(final Object obj) { mHandler.post(new Runnable() { @Override public void run() { if (obj != null && obj instanceof LinkedList) { @SuppressWarnings("unchecked") LinkedList<FreshNews> freshNewsList = (LinkedList<FreshNews>) obj; if (freshNewsList.size() > 0) { // 下拉刷新的数据去重复处理 if (page == 1 && mFreshNewsList.size() > 0) { for (FreshNews freshNews : freshNewsList) { boolean flage = false; for (FreshNews fresh : mFreshNewsList) { if (freshNews.getPost_id() == fresh.getPost_id()) { flage = true; } } if (flage == false) { mFreshNewsList.addFirst(freshNews); } } } else { mFreshNewsList.addAll(freshNewsList); } mListView.setPullLoadEnable(true); mListView.setPullRefreshEnable(true); } } else { mListView.setPullLoadEnable(false); } mListView.stopRefresh(); mListView.stopLoadMore(); mListView.setRefreshTime(mDateFormat.format(System.currentTimeMillis())); if (page == 1) { mFreshNewsAdapter.notifyDataSetInvalidated(); } else { mFreshNewsAdapter.notifyDataSetChanged(); } } }); } @Override public void onFail(int errorCode) { LogUtil.i(TAG, "freshNewsList errorCode = " + errorCode); } }); mDefaultThreadPool.execute(asyncHttpsPost); mAsyncRequests.add(asyncHttpsPost); } }
常量类源码如下:
package com.everyone.android.utils; import android.content.Context; /** * 功能描述:常量类 * @author android_ls */ public class Constant { /** * 人人登录和授权的地址 */ public static final String AUTHORIZE_URL = "https://graph.renren.com/oauth/authorize"; /** * 默认重定向URL */ public static final String DEFAULT_REDIRECT_URI = "http://graph.renren.com/oauth/login_success.html"; /** * 用accessToken交换sessionKey的URL */ public static final String SESSION_KEY_URL = "http://graph.renren.com/renren_api/session_key"; /** * 人人服务器URL(API Server URL) */ public static final String API_SERVER_URL = "https://api.renren.com/restserver.do"; /** * 第三方应用所拥有的权限 */ public static final String[] HAVE_PERMISSIONS = { "publish_feed", "create_album", "photo_upload", "read_user_album", "status_update", "read_user_blog", "read_user_checkin", "read_user_feed", "read_user_guestbook", "read_user_invitation", "read_user_like_history", "read_user_message", "read_user_notification", "read_user_photo", "read_user_status", "read_user_comment", "read_user_share", "read_user_request", "publish_blog", "publish_checkin", "publish_feed", "publish_share", "write_guestbook", "send_invitation", "send_request", "send_message", "send_notification", "photo_upload", "create_album", "publish_comment", "operate_like", "admin_page" }; /** * API_KEY */ public static final String API_KEY = "661ea1ba2d6b49859be197d77fe361f1"; /** * Secret Key */ public static final String SECRET_KEY = "a088d31cd5d341819bfc75ac0208b5e1"; /** * 应用ID */ public static final String APP_ID = "195789"; /** * 网络请求异常标识码 */ public static final int NETWORK_REQUEST_IOEXCEPTION_CODE = 1; /** * 网络请求返回NULL */ public static final int NETWORK_REQUEST_RETUN_NULL = 2; /** * 网络请求返回结果JSON解析异常(返回的字符串与我们商定的不一致时,会导致解析出错) */ public static final int NETWORK_REQUEST_RESULT_PARSE_ERROR = 3; /** * 网络请求未知异常(在我们预料之外的) */ public static final int NETWORK_REQUEST_UNKNOWN_EXCEPTION = 4; /** * JSON异常(普通字符串转换成JSON字符串时,格式出错会抛此异常) */ public static final int NETWORK_REQUEST_RESULT_CONVERT_ERROR = 5; /** * 发表的新鲜事,默认请求所有类型的新鲜事 */ public static final String FRESH_NEWS_TYPE_ALL = "10,11,20,21,22,23,30,31,32,33,34,35,36"; /** * 照片(相册) */ public static final String FRESH_NEWS_TYPE_PHOTO = "30,31"; /** * 状态 */ public static final String FRESH_NEWS_TYPE_STATUS = "10,11"; /** * 日志 */ public static final String FRESH_NEWS_TYPE_BLOG = "20,22"; /** * 分享的新鲜事 */ public static final String FRESH_NEWS_TYPE_SHARE = "21,23,32,33,36"; /** * 最近来访 */ public static final String PERSONAL_HOMEPAGE_TYPE_LATELY = "1"; /** * 资料 */ public static final String PERSONAL_HOMEPAGE_TYPE_DATA = "2"; /** * 好友内容 */ public static final String FRESH_NEWS_TYPE_FRIEND = null; // "40"; /** * 特别关注 */ public static final String FRESH_NEWS_TYPE_FOCUS = null; /** * 位置 */ public static final String FRESH_NEWS_TYPE_PLACE = null; /** * 本地与我们应用程序相关文件存放的根目录 */ public static final String ROOT_DIR_PATH = "CopyEveryone"; /** * 下载文件存放的目录 */ public static final String IMAGE_DOWNLOAD_CACHE_PATH = ROOT_DIR_PATH + "/Download/cache"; /** * 默认的磁盘缓存大小(20MB) */ public static final int DEFAULT_DISK_CACHE_SIZE = 1024 * 1024 * 20; /** * 拍照上传,照片在本地的存储目录 */ public static final String IMAGE_CAMERA_UPLOAD_PATH = ROOT_DIR_PATH + "/Camera/upload"; /** * 获取SDCard卡或者手机内存的根路径(优先获取SDCard卡的根路径) * @param context Context * @return SDCard卡或者手机内存的根路径 */ public static String getRootDir(Context context){ String rootDir = null; if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) { rootDir = android.os.Environment.getExternalStorageDirectory().getAbsolutePath(); } else { rootDir = context.getCacheDir().getAbsolutePath(); } return rootDir; } /** * 打开拍照界面的请求码 */ public static final int REQUEST_CAMERA_CODE = 1; /** * 打开相册界面的请求码 */ public static final int REQUEST_GALLERY_CODE = 2; /** * 调用系统的剪裁照片的请求码 */ public static final int REQUEST_CROP_PHOTO_CODE = 3; }
对服务器端返回的字符串形式的日期,进行加工处理工具类源码如下:
package com.everyone.android.utils; /** * 功能描述:日期处理工具类 * @author android_ls */ public final class DateUtil { /** * 对服务器端返回的字符串格式的日期值进行加工处理 * @param updateTime * @return 进行加工处理后的时间值 */ public static final String getMachTime(String updateTime) { String result = ""; if (updateTime != null && !"".equals(updateTime)) { result = updateTime; result = result.substring(result.indexOf("-") + 1, result.lastIndexOf(":")); result = result.replace("-", "月"); result = result.replace(" ", "日 "); int index = result.indexOf("0"); if (index == 0) { result = result.substring(index + 1); } } return result; } }