Android即时通讯--仿QQ即时聊天:(五)聊天模块
来源:互联网 发布:sql语句group by的用法 编辑:程序博客网 时间:2024/05/16 19:24
1、复杂ListView的展示
聊天模块其实就是一个复杂的ListView,在数据适配器中,从application中获取到当前登录的用户,与聊天消息中的from参数进行比较,如果两者相同则说明是自己发送的消息,那么ListView中就显示发送消息的布局,否则显示接收消息的布局。适配器的代码如下:
/** * 聊天消息的适配器 * * @author ZHY * */public class ChartMessageAdapter extends ArrayAdapter<QQMessage> {ImApp app;public ChartMessageAdapter(Context context, List<QQMessage> objects) {super(context, 0, objects);Activity activity = (Activity) context;app = (ImApp) activity.getApplication();}/** * 根据集合中的position位置,返回不同的值,代表不同的布局 0代表自己发送的消息 1代表接收到的消息 * */@Overridepublic int getItemViewType(int position) {// 这个方法是给getView用得QQMessage msg = getItem(position);// 消息来自谁,如果消息来自我自己,说明是我发送的if (msg.from == app.getMyAccount()) {// 我自己的消息,发送return 0;} else {return 1;}}/** * 两种布局 */@Overridepublic int getViewTypeCount() {return 2;}class ViewHolder {TextView time;TextView content;ImageView head;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {int type = getItemViewType(position);if (0 == type) {// 发送的布局ViewHolder holder;if (convertView == null) {convertView = View.inflate(getContext(),R.layout.item_chat_send, null);holder = new ViewHolder();holder.time = (TextView) convertView.findViewById(R.id.time);holder.content = (TextView) convertView.findViewById(R.id.content);holder.head = (ImageView) convertView.findViewById(R.id.head);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}// 设置值QQMessage msg = getItem(position);holder.time.setText(msg.sendTime);holder.head.setImageResource(msg.fromAvatar);holder.content.setText(msg.content);return convertView;} else {// 接收的布局ViewHolder holder;if (convertView == null) {convertView = View.inflate(getContext(),R.layout.item_chat_receive, null);holder = new ViewHolder();holder.time = (TextView) convertView.findViewById(R.id.time);holder.content = (TextView) convertView.findViewById(R.id.content);holder.head = (ImageView) convertView.findViewById(R.id.head);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}// 设置值QQMessage msg = getItem(position);holder.head.setImageResource(msg.fromAvatar);holder.time.setText(msg.sendTime);holder.content.setText(msg.content);return convertView;}}}
2、消息处理
在聊天页面中添加接收消息的监听,如果接收到的消息是聊天消息,那么就将接收到的消息添加到messages消息集合中,然后通知适配器数据发生了变化,进而刷新界面。当用户点击发送按钮的时候,封装消息,将消息发送个给服务器。聊天界面的代码如下:
/** * 聊天界面 * * @author ZHY * */public class ChartActivity extends Activity {@ViewInject(R.id.title)private TextView title;@ViewInject(R.id.listview)private ListView listView;@ViewInject(R.id.input)private EditText input;private ImApp app;private ChartMessageAdapter adapter;// 这是点击的用户,也就是你要发消息给谁private String toNick;// 要发送给谁private long toAccount;// y要发送的账号private long fromAccount;// 我的账号,我要跟谁睡聊天private String inputStr;// 聊天内容// 聊天消息的集合private List<QQMessage> messages = new ArrayList<QQMessage>();// 点击发送按钮的时候,获得输入框中的内容,将内容封装到messages集合中,聊调消息是一个QQMessageJava对象,一定包含四个字段@OnClick(R.id.send)public void send(View view) {// Toast.makeText(getBaseContext(), "ddadasf", 0).show();inputStr = input.getText().toString().trim();// 清空输入框input.setText("");final QQMessage msg = new QQMessage();if ("".equals(inputStr)) {Toast.makeText(getApplicationContext(), "不能为空", 0).show();return;}msg.type = QQMessageType.MSG_TYPE_CHAT_P2P;msg.from = fromAccount;msg.to = toAccount;msg.content = inputStr;msg.fromAvatar = R.drawable.ic_launcher;messages.add(msg);// 数据集合有了,创建适配器// 刷新消息if (adapter != null) {adapter.notifyDataSetChanged();}// 展示到最新发送的消息处if (messages.size() > 0) {listView.setSelection(messages.size() - 1);}// 发送消息到服务器--子线程ThreadUtils.runInSubThread(new Runnable() {public void run() {try {app.getMyConn().sendMessage(msg);} catch (IOException e) {e.printStackTrace();}}});}/** * 接收消息,使用监听器 */private OnMessageListener listener = new OnMessageListener() {public void onReveive(final QQMessage msg) {// 注意onReveive是子线程,更新界面一定要在主线程中ThreadUtils.runInUiThread(new Runnable() {public void run() {// 服务器返回回来的消息System.out.println(msg.content);if (QQMessageType.MSG_TYPE_CHAT_P2P.equals(msg.type)) {messages.add(msg);// 把消息加到消息集合中,这是最新的消息// 刷新消息if (adapter != null) {adapter.notifyDataSetChanged();}// 展示到最新发送的消息出if (messages.size() > 0) {listView.setSelection(messages.size() - 1);}}}});}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_chart);ViewUtils.inject(this);// 相当于findViewByIDapp = (ImApp) getApplication();// 开启监听app.getMyConn().addOnMessageListener(listener);// 聊天的界面是复杂的listView。发送消息的条目是item_chat_send.xml布局,接收到的消息现实的条目是item_chat_receive.xml布局/** * 聊天的消息 content "约不?" type chatp2p from 老王 to 大头 */// 获得从上一个界面获取的账号与昵称Intent intent = getIntent();toNick = intent.getStringExtra("nick");toAccount = intent.getLongExtra("account", 0);title.setText("与" + toNick + "聊天中");fromAccount = app.getMyAccount();// 我的账户adapter = new ChartMessageAdapter(this, messages);listView.setAdapter(adapter);}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();app.getMyConn().removeOnMessageListener(listener);}}至此,基于Socket的Android即时通讯软件就介绍完了,功能很丑陋,原理基本能说得通,自己留一份备忘,同时也希望能帮到别人。源码的话,稍后整理发出来,整个项目运行起来的效果如下。有待完善的地方还有很多,望不吝赐教,与君共勉,共同进步!!!
点我下载源码
6 0
- Android即时通讯--仿QQ即时聊天:(五)聊天模块
- Android即时通讯--仿QQ即时聊天:(一)初识Socket
- Android即时通讯--仿QQ即时聊天:(二)闪屏页及登录页面的实现
- Android即时通讯--仿QQ即时聊天:(三)核心代码抽取与登录逻辑
- Android即时通讯--仿QQ即时聊天:(四)好友列表的处理
- winform中socket实现即时通讯(仿qq聊天)
- 即时聊天web即时通讯
- 即时聊天,websocket,即时通讯
- 网络编程(五)--仿QQ聊天程序
- vue+express+mongodb+websocket 仿QQ即时聊天项目
- 【Android即时通讯】Android 高仿微信的即时聊天DEMO
- 仿qq聊天程序设计
- 仿QQ聊天程序
- 仿qq聊天界面
- 仿QQ聊天程序
- 0901Android基础仿QQ聊天界面(下)
- Android之高仿手机QQ聊天
- Android之高仿QQ聊天
- 大型网站架构系列:20本技术书籍推荐
- 2016Java工程师面试经验总结
- OpenGL之坐标转换(好文-清晰版)
- spring data jap的openEntityManagerInViewFilter和hibernate的openSessionInViewFilter
- 从今天开始坚持写博客
- Android即时通讯--仿QQ即时聊天:(五)聊天模块
- Java在linux下调用C/C++生成的so文件
- Swift 笔记(五)
- 译:在ASP.NET MVC5中如何使用Apache log4net 类库来记录日志
- 学习Kotlin笔记记录。--------类
- 大型网站架构系列:分布式消息队列(一)
- 1087. All Roads Lead to Rome (30)
- Android Fragment 生命周期图
- VMware Workstation 网络设置解释三种