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

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


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

题外话:

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

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


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

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


用户授认证登录还有显示新浪首页微博列表已经在前面一篇博客有所介绍了,但涉及到的内容有点多,看起来会比较乱,所以我尽量把关键点给大家介绍清楚,方便大家理解,只要对照项目,自己跑一遍,我想很快你们就能知道某个功能是怎么实现的。
以往博客地址

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

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


好吧,废话有点多,进入主题。


发布微博+拍照和图像特效处理

先看看效果图

授权登录+获取微博列表:
 




以上就是发布普通微博的效果图了,这里还没有涉及到图像处理,后面再介绍。

为了方便大家更加清楚,先先看看目前整个文档结构:




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; // 状态Id
	private String title; // 标题
	private String text; // 发送的文本

	@Override
	protected 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);

	}

	@Override
	public 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;
		}
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		switch (v.getId()) {
		case R.id.et_weibo_content:
			inputBoard.setVisibility(View.GONE);
			break;
		default:
			break;
		}
		return false;
	}

	@Override
	public Object onRetainNonConfigurationInstance() {
		return bitmap;
	}

	@Override
	protected 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);

	}

	@Override
	public 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();
	}

	@Override
	protected 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);
	}

	@Override
	public 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 {
	//  存储文件下载任务的List
	private 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 { // 否则由构造方法传入的doneAndProcess
				Collection<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();
		}
	}

	@Override
	public 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方法就行了,但在完整的项目里面,涉及到很多不同的任务,我们需要保证好的用户体验还要考虑程序的性能,所以需要使用特殊的解决方案,任务队列就是实现各种微博任务的解决方案。


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




发布了678 篇原创文章 · 获赞 2776 · 访问量 577万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: Age of Ai 设计师: meimeiellie

分享到微信朋友圈

×

扫一扫,手机浏览