实现过程全纪录——自己写一个“微信朋友圈”(包括移动端与PC端)
一.朋友圈的基本单元——动态
首先定义一个自定义控件用来显示每条动态。
二.运行效果
三.核心解读
PushedMessage 有个PushIndex属性,表示发送消息的index,从0开始递增。每个人Push的index都是从0开始,ResponseMoments 的 MessageList 是个字典,Key表示 index。
//
// 摘要:
// 拉取我的朋友们发的消息。当收到服务器回复,将触发ResponseMomentsReceived事件。
//
// 参数:
// startPullIndex:
// 从哪个index的消息开始拉取(不包含该index对应的那条)。如果startPullIndex小于0,表示拉取最新的N条。
//
// latest:
// latest为true,表示拉取更新的(大于startPullIndex);为false表示拉取之前的(小于startPullIndex)。
void Pull(long startPullIndex, bool latest);
//
// 摘要:
// 拉取目标用户所发的消息。当收到服务器回复,将触发ResponseMomentsReceived事件。
//
// 参数:
// ownerID:
// 所要拉取的目标用户的ID
//
// startPushIndex:
// 从哪个index的消息开始拉取(不包含该index对应的那条)。如果startPushIndex小于0,表示拉取最新的N条。
//
// latest:
// latest为true,表示拉取更新的(大于startPullIndex);为false表示拉取之前的(小于startPullIndex)。
void Pull(string ownerID, long startPushIndex, bool latest);
当调用这个方法时,表示获取我的朋友们的动态,我朋友们的动态会排序,index就是用这个key表示的。
latest 参数 表示是下拉,还是上拉。
四.DynamicsLoader解读
DynamicsLoader中最主要的是Load方法。
public void Load(Dictionary<long, PushedMessage> currentMessageList, FlowLayoutPanel flowLayoutPanel, IMomentsClient client)
{
this.preLastIndex = this.lastIndex;
foreach (var item in currentMessageList)
{
if (this.firstIndex < )
{
this.firstIndex = item.Key - currentMessageList.Count + ;
}
if (item.Key < this.firstIndex)
{
this.firstIndex = item.Key;
}
if (item.Key > this.lastIndex)
{
this.lastIndex = item.Key;
}
if (!this.messageList.ContainsKey(item.Key))
{
this.messageList.Add(item.Key, item.Value);
}
}
this.freeIndex = this.lastIndex - ; if ((this.lastIndex - this.preLastIndex) > )
{
this.firstIndex = this.lastIndex - currentMessageList.Count + ;
this.preLastIndex = this.firstIndex;
this.freeIndex = this.preLastIndex;
this.messageList.Clear();
this.messageList = currentMessageList;
}
this.listIndex = new List<long>((IEnumerable<long>)this.messageList.Keys);
this.listIndex.Sort();
flowLayoutPanel.Controls.Clear();
foreach (var item in this.listIndex)
{
DynamicsControl crl = new DynamicsControl();
crl.Initialize(this.messageList[item].OwnerID, Encoding.UTF8.GetString(this.messageList[item].Content), this.messageList[item].PushTime);
flowLayoutPanel.Controls.Add(crl);
flowLayoutPanel.Controls.SetChildIndex(crl, );
}
this.listIndex.Clear();
this.listIndex = null;
if (this.isUp)
{
if (flowLayoutPanel.Controls.Count != )
{
flowLayoutPanel.ScrollControlIntoView(flowLayoutPanel.Controls[]);
}
}
else
{
if (flowLayoutPanel.Controls.Count != )
{
flowLayoutPanel.ScrollControlIntoView(flowLayoutPanel.Controls[flowLayoutPanel.Controls.Count - ]);
}
}
if (currentMessageList.Count == )
{
return;
}
if ((this.lastIndex - this.preLastIndex) < )
{
return;
}
do
{
client.Pull(this.freeIndex, false);
this.freeIndex -= ;
}
while (this.freeIndex > this.preLastIndex);
}
正如前面所言,每一条动态都有一个index,那么我每次获取动态的时候,就需要保留一个最小的索引,用于下拉的时候使用;保留一个最大的索引,用于上拉的时候使用。当最新的动态比本地的动态多出20条以上时,则分为两种情况:1.两次可以加载完的就加载两次 ,2两次无法加载完的,就只加载最新的20条,并将本地旧动态全部删除。
五.移动端如何通信
一.消息编解码总体策略
NPush默认使用紧凑的序列化器,其遵循的策略如下:
字符串一律使用UTF-8编码。如果是基础数据类型,则直接记录其字节。
如果是bool,则用一个字节表示,0表示false,1表示true。
如果是string,先记录其长度(int,-1表示为null,0表示string.Empty),再记录UTF8编码的字节。
如果是byte[],先记录其长度(int,-1表示为null),再记录其内容。
如果是Image ,先记录其长度(int,-1表示为null),再记录是否为Gif(一个byte),再记录序列化内容。
如果是Color ,长度固定为3个字节,一次记录R/G/B的值。
如果是List<>,先记录元素数(int,-1表示为null),再依次记录每个元素的内容。
如果是Dictionary<,>,先记录元素对的个数(int,-1表示为null),再依次记录每个元素的Key,Value。
如果是自定义的class和struct,则先记录其序列化的长度(int,-1表示为null),再记录其序列化后的内容
二.消息头
消息头固定长度为8。
以登陆请求消息为例:LoginContract,C->S,MessageType为0
三.消息
DeviceType取值: 0 - DotNet ,1 - Android ,2 - iOS
六.序列化原理
在分布式通信系统中,网络传递的是二进制流,而内存中是我们基于对象模型构建的各种各样的对象,当我们需要将一个对象通过网络传递给另一个节点时,首先需要将其序列化为字节流,然后通过网络发送给目标节点,目标节点接收后,再反序列化为对象实例。
为了将业务对象转换为二进制流,大家通常有两种方案可以选择:使用.NET自带的二进制序列化器,或,先将业务对象转换为字符串(比如xml),再将结果用类似UTF8进行编码得到字节流。 然而这两种方案都有缺陷。
1..NET自带的二进制序列化器
缺点:强侵入性,序列化结果臃肿,其size巨大,效率低下,加密困难。
2.通过string进行中转
缺点:需要自己打造协议对象与字符串之间的相互转换、序列化之后的结果的Size取决于我们协议对象与字符串之间相互转换时所采用的规则,同样也取决于我们的耐心程度 、同.NET自带的二进制序列化器,对象属性值的读取/设置、对象的创建等通常也是基于反射的,所以,效率同样存在问题。
基于上述,我选择采用自己的序列化方式,性能较.NET自带的二进制序列化器提高了7~8倍。
七.源码下载
(说明:压缩包中有SQL脚本,我使用的是Mysql数据库。客户端登陆账号为test01~test99,以及默认的testQQ。相应的好友关系可以查看服务端的TestFriendProvider类。 )
——————————————————————————————————————
推荐阅读 :那些年搞不懂的高深术语——依赖倒置•控制反转•依赖注入•面向接口编程
实现过程全纪录——自己写一个“微信朋友圈”(包括移动端与PC端)的更多相关文章
- Android 高仿微信朋友圈动态, 支持双击手势放大并滑动查看图片。
转载请注明出处:http://blog.csdn.net/sk719887916/article/details/40348873 作者skay: 最近参与了开发一款旅行APP,其中包含实时聊天和动态 ...
- ionic 实现微信朋友圈分享的完整开发流程
最近开始要着手负责开发ionic的项目了,一直很好奇想实现一个微信朋友圈分享的功能,所以我就网上找了找文章来练手实现,果不其然,找到了几篇,但是发现它们的流程都不太详细,清楚,直接,还有不少坑. 今天 ...
- iOS版微信朋友圈数据库的简要分析
本文版权归cxun所有,如有转载请注明出处与本文链接,谢谢!原文地址:http://www.cnblogs.com/cxun/p/4550523.html 之前写了一些关于微信聊天记录的博文之后,不少 ...
- 微信朋友圈如何同时分享(图片+文字) Android版
以下是:微信朋友圈SDK 分享图片的代码,但只能分享图片,不能分享文字,如何才能图片和文字同时分享?求各位大神指教! public class MainActivity extends Activit ...
- 如何利用Python网络爬虫抓取微信朋友圈的动态(上)
今天小编给大家分享一下如何利用Python网络爬虫抓取微信朋友圈的动态信息,实际上如果单独的去爬取朋友圈的话,难度会非常大,因为微信没有提供向网易云音乐这样的API接口,所以很容易找不到门.不过不要慌 ...
- 实训六(Cocos2dx游戏分享到微信朋友圈----AppID的获取)
考虑把游戏分享到微信朋友圈,前面的博文已经写到,shareSDK是一个很好的选择,但是学习了几天时间,遇到了很多问题,与其在一棵树上吊死,还不如退一步海阔天空,先暂时放一放,于是我考虑了一下既然是分享 ...
- Android 仿微信朋友圈发动态功能(相册图片多选)
代码分享 代码名称: 仿微信朋友圈发动态功能(相册图片多选) 代码描述: 仿微信朋友圈发动态功能(相册图片多选) 代码托管地址: http://www.apkbus.com/android-15276 ...
- python爬虫24 | 搞事情了,用 Appium 爬取你的微信朋友圈。
昨天小帅b看到一些事情不顺眼 有人偷换概念 忍不住就写了一篇反讽 996 的 看不下去了,我支持996,年轻人就该996! 没想到有些人看不懂 这就算了 还来骂我 早些时候关注我的小伙伴应该知道我第一 ...
- (转载) listview实现微信朋友圈嵌套
listview实现微信朋友圈嵌套 标签: androidlistview 2016-01-06 00:05 572人阅读 评论(0) 收藏 举报 分类: android(8) 版权声明:本文为博 ...
随机推荐
- extJS4.2.0 tabPanel学习(三)
了解添加tab的函数 这里设置为自动添加,菜单是从后台获取的数据,前台进行双击的时候,添加tab页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...
- Android Studio:Gradle DSL method not found: 'runProguard()'
Android Studio发布了新的1.0版,更新之后却发现原来在0.8下面正常的项目编译失败了,从报错上来看是卡在gradle上面. Gradle DSL method not found: 'r ...
- myeclipse设置以及快捷键
http://blog.csdn.net/anxin323/article/details/40214467 如何查看jar包里的源码和doc文档? 1. jar文件右键properties--jav ...
- Cocos2dx 学习笔记整理----在项目中使用图片(一)
cocos2dx有多种使用图片的方法,先来个最简单的:用CCSprite直接使用图片. 首先,进入到之前建立的项目,把你将要使用的图片放入到目录下的Resources文件夹里面.项目中以相对路径使用资 ...
- Openlayers修改矢量要素
将以下代码放到demo下examples中即可运行 <!DOCTYPE html><html> <head> <meta http-equiv="C ...
- JSON-lib框架,转换JSON、XML不再困难
Json-lib可以将Java对象转成json格式的字符串,也可以将Java对象转换成xml格式的文档,同样可以将json字符串转换成Java对象或是将xml字符串转换成Java对象. 一. 准备工作 ...
- MYSQL一次性能优化实战经历[转]
每次经历数据库性能调优,都是对性能优化的再次认识.对自己知识不足的有力验证,只有不断总结.学习才能少走弯路. 一.性能问题描述 应用端反应系统查询缓慢,长时间出不来结果.SQLServer数据库服务器 ...
- C#-WebForm-AJAX阿贾克斯(一)基本格式
AJAX 即" Asynchronous Javascript And XML "(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术. AJAX = 异 ...
- Phone APP设计规范/iPad APP设计规范/Android APP设计规范/网页设计规范
原文链接:http://www.ui001.com/chicun/ ①iPhone的设计尺寸 iPhone界面尺寸: 设备 分辨率 状态栏高度 导航栏高度 标签栏(工具栏)高度 iPhone6 plu ...
- js设置文本框只能输入数字
JS判断只能是数字和小数点 1.文本框只能输入数字代码(小数点也不能输入) <input onkeyup="this.value=this.value.replace(/\D/g,'' ...