在开发中,有时会出现这样的开发场景,需要在一个持续变化的场景里不停的更新或者发送请求,比如说:在一个聊天界面回执消息,当然一般情况下来说第三方的imSDK会提供方法帮助我们处理这样的事,例如融云,在点对点的聊天中它们的做法就是会把每个聊天的最后一条消息回执回去,再此消息之前的所有消息都是按已读处理。这样它们用最简单的方法解决了这个问题,但是这种解决方式并不完全满足我们的需求,因为我们并不能实时的监控每条消息的状态,如果想要监控每条消息的状态的话融云并没有提供相关的方法,这时就需要我们自己来处理了。一开始我设想的很简单就是在adapter里调用融云的回执方法,按我的想法当adapter,每展示一条数据可见的数据就发起一次回执,但是在实际操作中我发现事情并不是我想的那样,因为adapter的加载实在太快了导致在同一时间所有的数据都回去发回执,这样造成了融云回执的接口报错,导致回执失败,为了解决这样的问题我想的了使用队列,先进先出,逐步的去请求。代码如下:
1.我使用一个队列来装载数据
/*
*
*由链表结构组成的有界阻塞队列,可以在设置队列最大长度,如果不设置默认是int的最大值 Integer.MAX_VALUE。基于列表的阻塞队列,按照先进先出的策略对数据进行排序,内部也维持了一个缓冲的链表队列方法有,put,take,pull,offer
*
***/
BlockingQueue<MessageEntity> queue = new LinkedBlockingQueue<MessageEntity>();
在adapter的onBindView时把数据加入队列
publick voide onBindView(ViewHolder holder, int position)
{
//确定该消息是否回执过,没有加人队列
if(tbub.isReceipt == MessageEntity.ReceiptStatus.NOT_RECEIPT)
{
ReceiptTask receiptTask = new ReceiptTask.Builder().entity(tbub).errorCount(0).build();
executeSend(receiptTask);
}
}
//加人队列
private void executeSend(ReceiptTask task) {
try {
if (task != null && task.mEntity != null) {
LogUtils.d("添加内容");
queue.put(task);
}
//标记是否需要发送,默认false
if (!isSending) {
LogUtils.d("取出内容" + isSending);
ReceiptTask take = queue.poll();
if (take != null) {
send(take);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//延时发送,成功和失败后都在此调用添加方法发送
private void send(ReceiptTask task) {
LogUtils.d("发送内容");
isSending = true;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
RongYunManager.sendSingleChatReceiptMessage(task.mEntity, new RongYunManager.ReadReceiptMessageCallback() {
@Override
public void onSuccess() {
//成功就不在添加继续下次的活动,更新当前状态
isSending = false;
executeSend(null);
}
@Override
public void onError() {
//失败就再次加人队列等待下次执行
isSending = false;
//错误次数大于4时就不再发了
if (task.errorCount < 4) {
task.errorCount++;
executeSend(task);
}
}
});
}
}, 300);
}
自此代码完成,这是一个极其简单的队列使用,下面附上LinkedBlockingQueue队列的一些方法
-
put 添加的方法,添加数据到队列 ,如果添加时队列已满这时会阻塞线程等到事件消费后可以添加在进行,未满就开启线程执行方法
-
offer 与put基本相同,不同的是offer方法不会阻塞线程,当队列已满会直接返回false,同还可以设置等待时间,当时间到了还没有执行就放会false
-
take 出队的方法,当队列为空时会阻塞线程,直到有新的事件来,如果队列不为空就会获取首个元素,并在队列里移除首个元素
-
poll 出队的方法,与take相比只是移除了阻塞线程的功能,其他一致该方法还可以设置等待时间