新浪微博客户端开发之发布微博

2013年11月22日新浪微博开发系列博客

题外话:

关于新浪微博客户端的开发我基本上是摸清楚了,之所以那么久才开始接下去写这系列的博客,主要也是小巫要摸透整个微博客户端的开发流程,要了解需要用到的技术和如何实现业务流程,再加上自己平时工作忙,最近也是忙学校的事情,所以耽搁了很久,其实实习之后发现自己之前与自己之前的计划是有点出入的,我是打算在实习期间把新浪微博客户端开发完毕,并且想自主研发一款app,但现实是我想跟我想做是不一样的,我不能估计我是否能在限定的时间里完成,因为我现在一点想法都没有,我不能去冒险把它作为自己毕业设计的内容,所以我打算做比较有把握的,所以想把新浪微博客户端作为毕业设计,但最终的效果肯定是跟现在的这个不一样的,我会继续完善,完善的程度是可以通过审核并且上线。所以如果想用做新浪微博客户端的童鞋注意了,不能抄袭哦,尊重原创作品。

题外话说到这里,开始本篇博客所要介绍的内容。

经过这段时间,我已经实现的功能列表如下:

1.用户授权认证登录
2.显示新浪首页微博列表+下拉刷
新功能+更多功能
3.显示微博详细内容(转发、评论、收藏、查看个人资料)
4.发布微博+拍照和图像特效处理
5.显示微博评论列表
6.显示@我的微博列表
7.显示评论我的信息
8.显示个人资料
9.实现联想搜索应用和用户
10.显示我的收藏微博列表
11.实现获取帐号隐私设置
以上的功能列表是目前已经实现,有些功能没办法实现是因为没有权限使用新浪微博的API,一些高级权限需要审核通过之后才能使用,由于这个客户端可能跟官方的类似所以不能通过,不过普通权限的API已经可以实现一些基本的功能了,以上也只是用来普通权限API的一部分,后期继续完善的时候,我会尽量多的使用更多的API,不过实现上面的功能列表就够你忙活一阵子了,当然如果只是拿代码来用,是花不了多少时间,但想想这样有意思么,最起码也要弄懂整个客户端的开发流程和使用到的技术吧。
用户授认证登录还有显示新浪首页微博列表已经在前面一篇博客有所介绍了,但涉及到的内容有点多,看起来会比较乱,所以我尽量把关键点给大家介绍清楚,方便大家理解,只要对照项目,自己跑一遍,我想很快你们就能知道某个功能是怎么实现的。
以往博客地址

新浪微博客户端开发之授权登录+获取微博列表

http://blog.csdn.net/wwj_748/article/details/12489457

Android UI--自定义ListView(实现下拉刷新+加载更多)

http://blog.csdn.net/wwj_748/article/details/12512885
好吧,废话有点多,进入主题。
发布微博+拍照和图像特效处理
先看看效果图
授权登录+获取微博列表:
 
以上就是发布普通微博的效果图了,这里还没有涉及到图像处理,后面再介绍。
为了方便大家更加清楚,先先看看目前整个文档结构:

Acitivity都放在com.wwj.sina.weibo这个包下面

发布微博的窗口是:/xiaowu_twitter/src/com/wwj/sina/weibo/PostWeibo.java

package com.wwj.sina.weibo;import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.provider.MediaStore;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ImageSpan;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;import com.wwj.sina.weibo.adapters.FaceListAdapter;
import com.wwj.sina.weibo.interfaces.Const;
import com.wwj.sina.weibo.library.FaceMan;
import com.wwj.sina.weibo.library.StorageManager;
import com.wwj.sina.weibo.util.Tools;
import com.wwj.sina.weibo.workqueue.task.CommentWeiboTask;
import com.wwj.sina.weibo.workqueue.task.PostWeiboTask;
import com.wwj.sina.weibo.workqueue.task.RepostWeiboTask;
/*** 发布微博* @author wwj**/
public class PostWeibo extends Activity implements Const, OnClickListener,OnTouchListener, OnItemClickListener {private Button btn_back; // 返回private Button btn_send; // 发送private EditText weiboContent; // 微博内容private ImageView minPicViewer; // 微博图片private TextView postWeiboTitle; // 微博标题栏private View inputBoard; // 输入板(表情)private ImageView insertAtButton; // 插入@private ImageView insertLocationButton; // 插入位置private ImageView insertFaceButton; // 插入表情private ImageView insertPicButton; // 插入图片private ImageView insertTopicButton; // 插入主题private View isCommentView; // 评论private CheckBox isCommentCheckBox; // 同时作为评论private CheckBox postWeiboCheckBox; // 同为发送一条微博private GridView faceList; // 表情列表private Bitmap bitmap;private static String filename; // 文件名(这里是图片)private int type; // 发布微博类型private long statusId; // 状态Idprivate String title; // 标题private String text; // 发送的文本@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.post_weibo);loadView();setListener();// 表情网格视图填充数据faceList.setAdapter(new FaceListAdapter(this));bitmap = (Bitmap) getLastNonConfigurationInstance();if (bitmap != null) {minPicViewer.setVisibility(View.VISIBLE);minPicViewer.setImageBitmap(bitmap);}// 获得Intent传过来的参数statusId = getIntent().getLongExtra("status_id", 0);type = getIntent().getIntExtra("type", TYPE_POST_WEIBO);title = getIntent().getStringExtra("title");text = getIntent().getStringExtra("text");viewSetting();}private void viewSetting() {switch (type) {case TYPE_POST_WEIBO:break;case TYPE_FORWARD: // 转发微博insertPicButton.setVisibility(View.GONE);isCommentView.setVisibility(View.VISIBLE);postWeiboCheckBox.setVisibility(View.GONE);isCommentCheckBox.setVisibility(View.VISIBLE);if (title != null) {postWeiboTitle.setText(title);}if (text != null) {weiboContent.setText(Tools.changeTextToFace(this,Html.fromHtml(Tools.atBlue(text))));weiboContent.getText().insert(0, " ");weiboContent.setSelection(0, 1);InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);imm.showSoftInput(weiboContent, InputMethodManager.SHOW_FORCED);}break;case TYPE_COMMENT: // 评论微博insertPicButton.setVisibility(View.GONE);isCommentView.setVisibility(View.VISIBLE);postWeiboCheckBox.setVisibility(View.VISIBLE);isCommentCheckBox.setVisibility(View.GONE);if (title != null) {postWeiboTitle.setText(title);}break;}}private void setListener() {btn_back.setOnClickListener(this);btn_send.setOnClickListener(this);insertAtButton.setOnClickListener(this);insertLocationButton.setOnClickListener(this);insertFaceButton.setOnClickListener(this);insertPicButton.setOnClickListener(this);insertTopicButton.setOnClickListener(this);faceList.setOnItemClickListener(this);minPicViewer.setOnClickListener(this);}/** 加载视图 **/private void loadView() {btn_back = (Button) findViewById(R.id.btn_back);btn_send = (Button) findViewById(R.id.btn_send);weiboContent = (EditText) findViewById(R.id.et_weibo_content);minPicViewer = (ImageView) findViewById(R.id.iv_insert_pic_min_viewer);postWeiboTitle = (TextView) findViewById(R.id.tv_post_weibo_title);inputBoard = findViewById(R.id.fl_input_board);faceList = (GridView) findViewById(R.id.gv_face_list);insertAtButton = (ImageView) findViewById(R.id.btn_insert_at);insertLocationButton = (ImageView) findViewById(R.id.btn_insert_location);insertFaceButton = (ImageView) findViewById(R.id.btn_insert_face);insertPicButton = (ImageView) findViewById(R.id.btn_insert_pic);insertTopicButton = (ImageView) findViewById(R.id.btn_insert_topic);isCommentView = findViewById(R.id.fl_is_comment);isCommentCheckBox = (CheckBox) findViewById(R.id.cb_is_comment);postWeiboCheckBox = (CheckBox) findViewById(R.id.cb_post_weibo);}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {switch (parent.getId()) {case R.id.gv_face_list:Bitmap bitmap = BitmapFactory.decodeResource(getResources(),FaceMan.getFaceResourceId(position));ImageSpan imageSpan = new ImageSpan(bitmap);String faceText = FaceMan.getFaceText(position);SpannableString spannableString = new SpannableString(faceText);spannableString.setSpan(imageSpan, 0, faceText.length(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);weiboContent.getText().insert(weiboContent.getSelectionStart(),spannableString);break;default:break;}}@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (v.getId()) {case R.id.et_weibo_content:inputBoard.setVisibility(View.GONE);break;default:break;}return false;}@Overridepublic Object onRetainNonConfigurationInstance() {return bitmap;}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {switch (requestCode) {case CODE_REQUEST_CAPTURE_IMAGE: // 照相机switch (resultCode) {case Activity.RESULT_OK: // 确定键minPicViewer.setVisibility(View.VISIBLE); // 设置图片可见bitmap = (Bitmap) data.getExtras().get("data"); // 获取图片数据minPicViewer.setImageBitmap(bitmap); // 显示图片filename = StorageManager.saveBitmap(bitmap);break;default:break;}break;case CODE_REQUEST_PICTURE_VIEWER: // 来自查看图片的返回结果switch (resultCode) {case CODE_RESULT_REMOVE: // 删除filename = null;bitmap = null;minPicViewer.setImageBitmap(null);minPicViewer.setVisibility(View.GONE);System.out.println("hhhh");break;case CODE_RESULT_RETURN: // 返回键if (data != null) {filename = data.getStringExtra("filename"); // 得到文件名bitmap = BitmapFactory.decodeFile(filename);minPicViewer.setImageBitmap(bitmap);}break;default:break;}}super.onActivityResult(requestCode, resultCode, data);}@Overridepublic void onClick(View v) {Intent intent = null;InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);switch (v.getId()) {case R.id.btn_back: // 返回finish();break;case R.id.btn_send: // 发布send();break;case R.id.btn_insert_pic: // 插入图片intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);startActivityForResult(intent, CODE_REQUEST_CAPTURE_IMAGE);break;case R.id.btn_insert_location: // 插入位置break;case R.id.btn_insert_topic: // 插入主题String topicText = "请输入主题";weiboContent.getText().insert(weiboContent.getSelectionStart(),"#" + topicText + "#");weiboContent.setSelection(weiboContent.getSelectionStart()- topicText.length() - 1,weiboContent.getSelectionStart() - 1);imm.showSoftInput(weiboContent, InputMethodManager.SHOW_FORCED);break;case R.id.btn_insert_at: // 插入@String atText = "请输入用户名";weiboContent.getText().insert(weiboContent.getSelectionStart(),"@" + atText + " ");weiboContent.setSelection(weiboContent.getSelectionStart() - 1- atText.length(), weiboContent.getSelectionStart() - 1);imm.showSoftInput(weiboContent, InputMethodManager.SHOW_FORCED);break;case R.id.btn_insert_face: // 插入表情if (inputBoard.getVisibility() == View.GONE) {insertFaceButton.setImageResource(R.drawable.btn_insert_keyboard);inputBoard.setVisibility(View.VISIBLE);faceList.setVisibility(View.VISIBLE);} else {insertFaceButton.setImageResource(R.drawable.btn_insert_face);inputBoard.setVisibility(View.GONE);faceList.setVisibility(View.GONE);}break;case R.id.iv_insert_pic_min_viewer: // 图片浏览intent = new Intent(PostWeibo.this, PictureViewer.class);intent.putExtra("filename", filename);startActivityForResult(intent, CODE_REQUEST_PICTURE_VIEWER);break;default:break;}}// 发送private void send() {String text = weiboContent.getText().toString();switch (type) {case TYPE_POST_WEIBO: // 发送微博if (filename != null && "".equals("")) {text = "分享图片";} else if ("".equals(text)) {Toast.makeText(this, "请输入微博内容", Toast.LENGTH_LONG).show();return;}// 创建一个发布微博的任务PostWeiboTask postWeiboTask = new PostWeiboTask();postWeiboTask.text = text;postWeiboTask.file = filename;Tools.getGlobalObject(this).getWorkQueueStorage().addTask(postWeiboTask);Toast.makeText(this, "已经提交发布微博任务到工作队列", Toast.LENGTH_LONG).show();break;case TYPE_FORWARD:  // 转发微博if ("".equals(text)) {Toast.makeText(this, "请输入微博内容", Toast.LENGTH_LONG).show();return;}RepostWeiboTask repostWeiboTask = new RepostWeiboTask();repostWeiboTask.id = statusId;repostWeiboTask.text = text;if (isCommentCheckBox.isChecked()) { // 是否评论repostWeiboTask.isComment = 1;} else {repostWeiboTask.isComment = 0;}Tools.getGlobalObject(this).getWorkQueueStorage().addTask(repostWeiboTask);Toast.makeText(this, "已经提交转发微博任务到工作队列", Toast.LENGTH_LONG).show();break;case TYPE_COMMENT:if ("".equals(text)) {Toast.makeText(this, "请输入微博内容", Toast.LENGTH_LONG).show();return;}CommentWeiboTask commentWeiboTask = new CommentWeiboTask();commentWeiboTask.text = text;commentWeiboTask.weiboText = text + this.text;commentWeiboTask.id = statusId;if (postWeiboCheckBox.isChecked()) {commentWeiboTask.postWeibo = true;} else {commentWeiboTask.postWeibo = false;}Tools.getGlobalObject(this).getWorkQueueStorage().addTask(commentWeiboTask);// 返回结果setResult(TYPE_COMMENT);Toast.makeText(this, "已经提交评论微博任务到工作队列", Toast.LENGTH_LONG);break;}finish();}@Overrideprotected void onDestroy() {filename = null;super.onDestroy();}
}

来说说实现发布微博功能的关键点:

1. 任务队列(多线程的实现)

2. 任务存储

3. 任务监视

4. 任务处理

发布微博我们点击发送按钮就会调用send()方法,来看看send方法里面做了什么操作

 // 发送private void send() {String text = weiboContent.getText().toString();switch (type) {case TYPE_POST_WEIBO: // 发送微博if (filename != null && "".equals("")) {text = "分享图片";} else if ("".equals(text)) {Toast.makeText(this, "请输入微博内容", Toast.LENGTH_LONG).show();return;}// 创建一个发布微博的任务PostWeiboTask postWeiboTask = new PostWeiboTask();postWeiboTask.text = text;postWeiboTask.file = filename;Tools.getGlobalObject(this).getWorkQueueStorage().addTask(postWeiboTask);Toast.makeText(this, "已经提交发布微博任务到工作队列", Toast.LENGTH_LONG).show();break;case TYPE_FORWARD:    // 转发微博if ("".equals(text)) {Toast.makeText(this, "请输入微博内容", Toast.LENGTH_LONG).show();return;}RepostWeiboTask repostWeiboTask = new RepostWeiboTask();repostWeiboTask.id = statusId;repostWeiboTask.text = text;if (isCommentCheckBox.isChecked()) { // 是否评论repostWeiboTask.isComment = 1;} else {repostWeiboTask.isComment = 0;}Tools.getGlobalObject(this).getWorkQueueStorage().addTask(repostWeiboTask);Toast.makeText(this, "已经提交转发微博任务到工作队列", Toast.LENGTH_LONG).show();break;case TYPE_COMMENT:if ("".equals(text)) {Toast.makeText(this, "请输入微博内容", Toast.LENGTH_LONG).show();return;}CommentWeiboTask commentWeiboTask = new CommentWeiboTask();commentWeiboTask.text = text;commentWeiboTask.weiboText = text + this.text;commentWeiboTask.id = statusId;if (postWeiboCheckBox.isChecked()) {commentWeiboTask.postWeibo = true;} else {commentWeiboTask.postWeibo = false;}Tools.getGlobalObject(this).getWorkQueueStorage().addTask(commentWeiboTask);// 返回结果setResult(TYPE_COMMENT);Toast.makeText(this, "已经提交评论微博任务到工作队列", Toast.LENGTH_LONG);break;}finish();}

这里只看发送微博就行了,至于转发微博还有评论都是提交到任务队列里去的,都是类似的实现过程,所以我介绍完发布微博这个流程,关于转发和评论的实现我就不多介绍,只会在需要注意的地方介绍一下。

我们可以看到,会先创建一个任务,然后把任务添加到任务队列里面

PostWeiboTask这个类,里面的内容如下:

package com.wwj.sina.weibo.workqueue.task;/*** 发布微博任务* @author wwj**/
public class PostWeiboTask extends ParentTask {public String text;public String file;
}

它继承ParentTask这个类

package com.wwj.sina.weibo.workqueue.task;import com.wwj.sina.weibo.workqueue.DoneAndProcess;public class ParentTask {public DoneAndProcess doneAndProcess;
}

而ParentTask有DoneAndProcess这个接口属性

package com.wwj.sina.weibo.workqueue;import com.wwj.sina.weibo.workqueue.task.ParentTask;
/*** 完成任务后的接口* @author wwj**/
public interface DoneAndProcess {void doneProcess(ParentTask task);
}

这个接口定义了一个doneProcess这个方法,里面传入一个ParentTask对象,用于完成任务后的收尾工作,这里是用来刷新数据。

与之对应的执行任务的接口DoingAndProcess

package com.wwj.sina.weibo.workqueue;import java.util.List;/*** 处理任务的接口* @author wwj**/
public interface DoingAndProcess {void doingProcess(List list) throws Exception;
}

这个接口有一个方法是doingProcess,传入List为参数,意味着它要执行List里面的任务,实现这个接口的类就是用要实现各种任务的,实现这个接口的类叫TaskMan。

package com.wwj.sina.weibo.workqueue.task;import java.util.List;import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.widget.Toast;import com.wwj.sina.weibo.net.PullFile;
import com.wwj.sina.weibo.workqueue.DoingAndProcess;
import com.wwj.sina.weibo.workqueue.task.process.CommentWeiboProcess;
import com.wwj.sina.weibo.workqueue.task.process.FavoriteWeiboProcess;
import com.wwj.sina.weibo.workqueue.task.process.PostWeiboProcess;
import com.wwj.sina.weibo.workqueue.task.process.RepostWeiboProcess;/*** 处理任务的中枢* * @author wwj* */
public class TaskMan implements DoingAndProcess {private Activity activity;private PostWeiboProcess postWeiboProcess;private RepostWeiboProcess repostWeiboProcess;private CommentWeiboProcess commentWeiboProcess;private FavoriteWeiboProcess favoriteWeiboProcess;private Handler msgHandler = new Handler() {public void handleMessage(android.os.Message msg) {String str = String.valueOf(msg.obj);Toast.makeText(activity, str, Toast.LENGTH_LONG).show();super.handleMessage(msg);};};public TaskMan(Activity activity) {super();this.activity = activity;// 创建各种任务处理类对象postWeiboProcess = new PostWeiboProcess(activity);repostWeiboProcess = new RepostWeiboProcess(activity);commentWeiboProcess = new CommentWeiboProcess(activity);favoriteWeiboProcess = new FavoriteWeiboProcess(activity);}@Overridepublic void doingProcess(List list) throws Exception {// 开始处理各种任务for (Object task : list) {// 处理发布微博任务if (task instanceof PostWeiboTask) {try {postWeiboProcess.process((PostWeiboTask) task);Message msg = new Message();msg.obj = "成功发布微博";msgHandler.sendMessage(msg);} catch (Exception e) {exceptionProcess(task);throw e;}// 处理下载文件任务} else if (task instanceof PullFileTask) {PullFileTask pullFileTask = (PullFileTask) task;PullFile pullFile = new PullFile();pullFile.doingProcess(pullFileTask.fileUrl);// 处理转发微博任务} else if (task instanceof RepostWeiboTask) {try {repostWeiboProcess.process((RepostWeiboTask) task);Message msg = new Message();msg.obj = "成功转发微博";msgHandler.sendMessage(msg);} catch (Exception e) {exceptionProcess(task);throw e;}// 处理评论微博任务} else if (task instanceof CommentWeiboTask) {try {commentWeiboProcess.process((CommentWeiboTask) task);Message msg = new Message();msg.obj = "成功评论微博";msgHandler.sendMessage(msg);} catch (Exception e) {exceptionProcess(task);throw e;}// 处理收藏微博任务} else if (task instanceof FavoriteWeiboTask) {try {favoriteWeiboProcess.process((FavoriteWeiboTask) task);} catch (Exception e) {exceptionProcess(task);throw e;}}}}// 执行任务类失败时调用该方法private void exceptionProcess(Object task) {Message msg = new Message();// 任务处理if (task instanceof PostWeiboTask) {msg.obj = "微博发布失败";} else if (task instanceof RepostWeiboTask) {msg.obj = "转发微博失败";} else if (task instanceof CommentWeiboTask) {msg.obj = "评论微博失败";} else if (task instanceof FavoriteWeiboTask) {msg.obj = "收藏微博失败";}msgHandler.sendMessage(msg);}}

这个类很重要哈,我们可以看到任务队列里面的任务都在这里完成了,具体实现任务处理的类,这里只介绍PostWeiboProcess。

package com.wwj.sina.weibo.workqueue.task.process;import com.wwj.sina.weibo.library.WeiboManager;
import com.wwj.sina.weibo.util.Tools;
import com.wwj.sina.weibo.workqueue.task.PostWeiboTask;import android.app.Activity;
/*** 发博微博任务处理类* @author wwj**/
public class PostWeiboProcess {private Activity activity;public PostWeiboProcess(Activity activity) {super();this.activity = activity;}// 提交微博public void process(PostWeiboTask task) throws Exception {// 发布微博WeiboManager.update(activity, Tools.getWeibo(activity), task.text, task.file);}}

这个就是发布微博的处理类,它有一个process方法,把发布微博的任务对象传入,这里的task就是在send()方面里面传入的,然后通过WeiboManager方法调用update的方法实现发布微博。

关于任务队列这一块是实现新浪微博最核心的,稍微有点复杂,下面我帮大家整理一下思路:

任务存储类:/xiaowu_twitter/src/com/wwj/sina/weibo/workqueue/WorkQueueStorage.java

这个类呢就是用来存储任务的,获取当前需要执行的任务,也用来移除执行完的任务列表,安装先进先出的方式实现任务按顺序执行,所以每次获取的任务就是放在最前面的,因为List的排列是顺序的。

package com.wwj.sina.weibo.workqueue;import java.util.ArrayList;
import java.util.List;/*** 任务存储* * @author wwj* */
public class WorkQueueStorage {//  存储文件下载任务的Listprivate List<String> webFileDoingList = new ArrayList<String>();// 存储通用任务的List, 所有任务都必须是ParentTask的子类private List taskList = new ArrayList();// 获取文件下载任务(要下载的URL)public List<String> getDoingWebFileUrls() {// 进行同步synchronized (webFileDoingList) {if (webFileDoingList.size() > 0) {List<String> resultList = new ArrayList<String>();resultList.addAll(webFileDoingList);return resultList;} else {return null;}}}// 删除文件下载队列中的任务public void removeDoingWebFileUrl(List<String> list) {synchronized (webFileDoingList) {if (list != null)webFileDoingList.removeAll(list);}}// 想文件下载队列添加任务(一个Url)public void addDoingWebFileUrl(String url) {synchronized (webFileDoingList) {webFileDoingList.add(url);}}// 目前必须只得到到一个任务,如果一下得到多个任务,需要修改WorkQueueMonitor类的代码// 获取一个通用任务public List getDoingTasks() {synchronized (taskList) {List result = new ArrayList();if (taskList.size() > 0) {result.add(taskList.get(0));return result;} else {return null;}}}// 删除通用任务public void removeTask(List tasks) {synchronized (taskList) {if (taskList.size() > 0) {taskList.removeAll(tasks);}}}// 添加通用任务public void addTask(Object task) {synchronized (taskList) {taskList.add(task);}}
}

我们通过调用addTask方法,把任务添加到任务列表当中,这个方法是线程同步的。

任务监视类:/xiaowu_twitter/src/com/wwj/sina/weibo/workqueue/WorkQueueMonitor.java

package com.wwj.sina.weibo.workqueue;import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import android.app.Activity;
import android.os.Handler;
import android.os.Message;import com.wwj.sina.weibo.interfaces.Const;
import com.wwj.sina.weibo.util.LogUtils;
import com.wwj.sina.weibo.workqueue.task.ParentTask;/*** 任务监视* * @author Lining 说明:除了任务存储外,还需要通过线程不断扫描保存的任务的List,一旦发现任务,立刻处理。*         这个工作交给WorkQueueMonitor类来完成*/
public class WorkQueueMonitor implements Runnable, Const {private WorkQueueStorage storage; // 任务存储private Map<Integer, DoneAndProcess> doneAndProcessMap = new HashMap<Integer, DoneAndProcess>();private DoingAndProcess doingAndProcess; // 处理任务接口对象private Activity activity;private boolean stopFlag = false; // 停止标识private Thread thread; // 线程引用private int monitorType = MONITOR_TYPE_IMAGE; // 监视类型,默认为图片// 任务完成后,处理剩余的工作,主要是执行doneAndProcess方法private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {ParentTask parentTask = (ParentTask) msg.obj;// 如果任务本身有doneAndProcess方法,则执行此方法if (parentTask != null && parentTask.doneAndProcess != null) {parentTask.doneAndProcess.doneProcess(parentTask);} else { // 否则由构造方法传入的doneAndProcessCollection<DoneAndProcess> doneAndProcesses = doneAndProcessMap.values();for (DoneAndProcess doneAndProcess : doneAndProcesses) {doneAndProcess.doneProcess(parentTask);}}};};/*** 构造函数* * @param activity*            窗口* @param storage*            任务存储对象* @param doingAndProcess*            正在处理的任务接口对象* @param monitorType*            监视类型*/public WorkQueueMonitor(Activity activity, WorkQueueStorage storage,DoingAndProcess doingAndProcess, int monitorType) {super();this.activity = activity;this.storage = storage;this.doingAndProcess = doingAndProcess;this.monitorType = monitorType;}// 开启线程public void start() {if (thread == null) {thread = new Thread(this);thread.start(); // 启动线程}}// 停止线程public void stop() {stopFlag = true;}// 扫描文件下载任务队列private void imageScan() {LogUtils.i("+++ imageScan");// 获取文件下载任务List<String> webFileDoingList = storage.getDoingWebFileUrls();while (webFileDoingList != null) {try {// 处理文件下载任务doingAndProcess.doingProcess(webFileDoingList);handler.sendEmptyMessage(0);} catch (Exception e) {e.printStackTrace();} finally {// 删除已处理完的任务storage.removeDoingWebFileUrl(webFileDoingList);}webFileDoingList = storage.getDoingWebFileUrls();}}// 扫描通用任务private void taskScan() {List taskList = storage.getDoingTasks();while (taskList != null) {try {doingAndProcess.doingProcess(taskList);Message msg = new Message();if (taskList.size() > 0) {msg.obj = taskList.get(0);}handler.sendMessage(msg);} catch (Exception e) {e.printStackTrace();} finally {storage.removeTask(taskList);}taskList = storage.getDoingTasks();}}@Overridepublic void run() {while (!stopFlag) {if (monitorType == MONITOR_TYPE_IMAGE) {imageScan();} else if (monitorType == MONITOR_TYPE_TASK) {taskScan();}try {// 每200毫秒扫描一次任务队列Thread.sleep(200);} catch (Exception e) {e.printStackTrace();}}}public void addDoneAndProcess(int type, DoneAndProcess doneAndProcess) {if (doneAndProcess != null) {doneAndProcessMap.put(type, doneAndProcess);}}}

任务队列如何实现?就是通过线程不断扫描任务列表,只要任务列表有任务就马上执行,关于任务会分两种,一种是图片下载任务,另一种是普通任务(发布微博、收藏微博、转发微博等)。当调用WorkQueueMonitor这个类的start方法就启动线程,然后执行run方法,根据不同任务类型执行任务。具体调用start方法的地方是在GlobalObject这个类里面。

/xiaowu_twitter/src/com/wwj/sina/weibo/GlobalObject.java

package com.wwj.sina.weibo;import android.app.Activity;
import android.app.Application;import com.weibo.net.Weibo;
import com.wwj.sina.weibo.interfaces.Const;
import com.wwj.sina.weibo.listener.AuthDialogListener;
import com.wwj.sina.weibo.net.PullFile;
import com.wwj.sina.weibo.object.Consumer;
import com.wwj.sina.weibo.workqueue.WorkQueueMonitor;
import com.wwj.sina.weibo.workqueue.WorkQueueStorage;
import com.wwj.sina.weibo.workqueue.task.TaskMan;/*** 全局对象Application级别* * @author Administrator* */
public class GlobalObject extends Application implements Const {// 调试开关public static final boolean DEBUG = true;private Weibo weibo;// 任务存储private WorkQueueStorage workQueueStorage;// 图像下载监视器private WorkQueueMonitor imageWorkQueueMonitor;// 通用任务监视器private WorkQueueMonitor taskWorkQueueMonitor;/*** 获得微博对象* * @param activity* @return*/public Weibo getWeibo(Activity activity) {// 如果微博对象为null或者会话无效if (weibo == null || !weibo.isSessionValid()) {weibo = Weibo.getInstance(); // 获取Weibo对象weibo.setupConsumerConfig(Consumer.consumerKey,Consumer.consumerSecret);weibo.setRedirectUrl(Consumer.redirectUrl);// 授权认证weibo.authorize(activity, new AuthDialogListener(activity));}return weibo;}public Weibo getWeibo() {return weibo;}/*** 获取图像工作队列监视器* @param activity* @return*/public WorkQueueMonitor getImageWorkQueueMonitor(Activity activity) {if (imageWorkQueueMonitor == null) {// Pullfile用于下载文件,实现了DoingAndProcess接口imageWorkQueueMonitor = new WorkQueueMonitor(activity,getWorkQueueStorage(), new PullFile(), MONITOR_TYPE_IMAGE);// 开启线程imageWorkQueueMonitor.start();}return imageWorkQueueMonitor;}/*** 获取通用任务监视器* @param activity* @return*/public WorkQueueMonitor getTaskWorkQueueMonitor(Activity activity) {if (taskWorkQueueMonitor == null) {// TaskMan用于处理通用任务taskWorkQueueMonitor = new WorkQueueMonitor(activity,getWorkQueueStorage(), new TaskMan(activity),MONITOR_TYPE_TASK);// 开启线程taskWorkQueueMonitor.start();}return taskWorkQueueMonitor;}public WorkQueueMonitor getImageWorkQueueMonitor() {return imageWorkQueueMonitor;}public WorkQueueMonitor getTaskWorkQueueMonitor() {return taskWorkQueueMonitor;}public WorkQueueStorage getWorkQueueStorage() {if (workQueueStorage == null) {workQueueStorage = new WorkQueueStorage();}return workQueueStorage;}public void closeWorkQueue() {if (imageWorkQueueMonitor != null) {imageWorkQueueMonitor.stop();imageWorkQueueMonitor = null;}if (taskWorkQueueMonitor != null) {taskWorkQueueMonitor.stop();taskWorkQueueMonitor = null;}}}

通过调用getTaskWorkQueueMonitor()方法就启动了监视器线程,每过200毫秒扫描一下通用任务列表,这里调用

WorkQueueMonitor中的taskScan方法来实现循环扫描将WorkQueueStorage存储的需要执行的任务通过调用doingProcess执行,实现DoingAndProcess接口的类有TaskMan还有PullFileTask,传入任务队列之就会遍历List来分别执行相应的任务,比如发布微博,就调用PostWeiboProcess的process方法。

我不知道我在这里把流程说清楚了没有,我想这个需要自己去跟踪一下代码会比较清楚,如果不太明白的童鞋可以认真看几遍代码,就可以把整个调用的流程搞清楚的。

之前的博客就已经介绍过WeiboManager这个方法的,但是不完整的,这个类也非常重要,因为在这个类里面你就可以知道如何调用新浪微博API的了,这一块还涉及到线程异步的知识点,是通过AsyncWeiboRunner这个类实现的,我在测试的时候,发现原来非异步的操作已经不行了,因为在Android4.0的时候会抛异常,提示是在主线程不能进行网络操作,我也发表相关的博客,可以到以下地址查看:

http://blog.csdn.net/wwj_748/article/details/14003851

所以在开发的时候要注意这一点,获取不了数据可能就是网络操作出错了,当然有很多原因也会造成,这就需要你们自己去查找原因了。

WeiManager中发布微博的方法:

public static String update(Activity activity, Weibo weibo, String text,String file) throws WeiboException {WeiboParameters bundle = new WeiboParameters();bundle.add("source", Weibo.getAppKey());bundle.add("status", text);String url = Weibo.SERVER + "statuses/update.json";if (file != null) {bundle.add("pic", file);url = Weibo.SERVER + "statuses/upload.json";}String rlt = "";rlt = weibo.request(activity, url, bundle, Utility.HTTPMETHOD_POST,weibo.getAccessToken());return rlt;}

以上就是关于发布微博业务实现流程,可能有人觉得怎么那么麻烦,直接调用不就行了么?当然你只想实现发布微博一个功能的话,直接调用update方法就行了,但在完整的项目里面,涉及到很多不同的任务,我们需要保证好的用户体验还要考虑程序的性能,所以需要使用特殊的解决方案,任务队列就是实现各种微博任务的解决方案。

我还要做特别的说明,整个微博项目代码量是很足的,只要涉及到这部分代码,我就会贴出来,所以会有点乱,有点烦,如果网友有哪部分不太明白的话,可以给我留言,我会在新的文章当中进行说明。

新浪微博客户端开发之发布微博相关推荐

  1. 新浪微博客户端开发--显示单条微博

    新浪微博客户端开发--显示单条微博 2013年11月23日 新浪微博客户端开发记录 前面两篇博客介绍了如何调用新浪微博API发布微博,任务队列的实现流程,自定义微博adapter的实现,异步更新UI的 ...

  2. 新浪微博客户端开发之授权登录+获取微博列表

    新浪微博客户端开发之授权登录+获取微博列表 闲篇: 最近实在是乱得不行,至于怎么乱我也不知该怎么说,那么久没发博客就证明了这点,一般如果小巫有做详尽的计划,并把时间投入到上面的话,我是可以用最短的时间 ...

  3. java 微博sdk_Java新浪微博客户端开发第一步

    Java新浪微博客户端开发***步 一.获得开发应用所需的"通行证"App Key和App Secret 首先必须要有新浪的账号.再打开http://open.weibo.com/ ...

  4. 微博java客户端开发教程_Java新浪微博客户端开发第四步

    这一步是对之前进行较大的改动.增加的类也比较多.包结构如下: 0.Main:主函数入口 1.MainDialog:主界面 2.WeiboPanel:StatusPanel及CommentPanel的父 ...

  5. java 微博客户端,Java新浪微博客户端开发第二步

    上一篇:Java新浪微博客户端开发***步中有下图,这个access_token就是接下来要用到的. 关于access_token的有效时间: 更多关于access_token与Oauth2,请参看: ...

  6. 新浪微博客户端开发开篇

    新浪微博客户端开发开篇 2013年7月28日新浪微博客户端启动啦 项目启动原因 其实想开发新浪微博客户端已经是很早之前的一件事情了,之前是因为开发<简.美音乐播放器>所以就没有启动它,开发 ...

  7. Java新浪微博客户端开发第二步

    上一篇:Java新浪微博客户端开发第一步中有下图,这个access_token就是接下来要用到的. 关于access_token的有效时间: 授权级别 测试 普通 中级 高级 合作 授权有效期 1天 ...

  8. Java新浪微博客户端开发第四步

    这一步是对之前进行较大的改动.增加的类也比较多.包结构如下: 0.Main:主函数入口 1.MainDialog:主界面 2.WeiboPanel:StatusPanel及CommentPanel的父 ...

  9. Java新浪微博客户端开发第六步(完结开源)

    这次所达到的: 1.修复之前几个严重的Bug 1).查看别的用户的微博时,出现当前登录用户的微博 2).查看粉丝时,出现重复加载的情况. 3).查看微博评论.转发时,出现只有第一条点击的微博可以查看. ...

  10. 2011年沈大海讲师Android的新浪微博客户端开发教程

    增加了GPS和 Google map显示功能 优化的整体架构 实现了话题显示 实现了在微博应用中嵌入游戏项目(NDK开发的) 完全使用Oauth方式实现用户认证 基于Android的新浪微博系统开发0 ...

最新文章

  1. Android高级开发-布局渲染流程与优化
  2. 201671010444 夏向明 词频统计软件项目报告
  3. java部署容器_Linux容器——Docker(二)之 JavaWeb部署
  4. 百度语音识别最新资讯
  5. 使用一个虚拟环境,但是运用其他环境中的库!【pycharm】
  6. SnapKit 是怎样炼成的 | 掘金技术征文
  7. VSS2005使支持通过Internet访问
  8. chrome frame节点 取_Chrome Frame插件解决IE浏览器兼容问题
  9. 客户需求分析8个维度_客户需求不知如何分析总结?一篇文章让你少走弯路!...
  10. python 描述性分析_python数据分析:美国巴尔的摩16年公务员工资数据集描述性分析...
  11. eclipse 中用svn共享项目
  12. win7系统安装网银助手时提示您尚未正确安装错误的两种解决方法图文教程
  13. vue 图片加载完成事件
  14. USB转RS485代替PC/PPI通讯电缆
  15. H5及H5页面是什么意思?如何制作H5页面?
  16. Windows7 UAC 实验
  17. 计算机蓝屏代码0xc0000020,Win10系统运行程序提示“损坏的映像 错误0xc0000020”如何解决?...
  18. 【算法笔记】极客时间 算法面试通关40讲 笔记  覃超
  19. 《程序员十二时辰》,居然是这样的!内容过于真实 ...
  20. 供给云SAAS平台企微助手再升级

热门文章

  1. 析构函数什么时候析构
  2. Java——(九)IO流
  3. 【听】天才在左,疯子在右,天才与疯子一线之间
  4. 加拿大前十大学计算机硕士学费,2018年加拿大各大学硕士学费一览表!
  5. Day3:MVP+ButterKnife+Dagger2的使用
  6. 我要偷偷的学Python,然后惊呆所有人(第九天)
  7. 有趣的数据结构——Linux内核中的链表(Black Aureole)
  8. Facebook三方登陆流程
  9. Java Web实训项目:西蒙购物网1
  10. 花都平安保险应该找谁?