Android即时通讯--仿QQ即时聊天:(五)聊天模块

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代表接收到的消息
	 * 
	 */
	@Override
	public int getItemViewType(int position) {// 这个方法是给getView用得
		QQMessage msg = getItem(position);
		// 消息来自谁,如果消息来自我自己,说明是我发送的
		if (msg.from == app.getMyAccount()) {
			// 我自己的消息,发送
			return 0;
		} else {
			return 1;
		}
	}

	/**
	 * 两种布局
	 */
	@Override
	public int getViewTypeCount() {

		return 2;
	}

	class ViewHolder {
		TextView time;
		TextView content;
		ImageView head;
	}

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

					}

				}
			});

		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_chart);
		ViewUtils.inject(this);// 相当于findViewByID
		app = (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);
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		app.getMyConn().removeOnMessageListener(listener);
	}
}
至此,基于Socket的Android即时通讯软件就介绍完了,功能很丑陋,原理基本能说得通,自己留一份备忘,同时也希望能帮到别人。源码的话,稍后整理发出来,整个项目运行起来的效果如下。有待完善的地方还有很多,望不吝赐教,与君共勉,共同进步!!!



  • 15
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
即时通讯IM系统(H5+安卓+IOS)客户端 支持红包转账 朋友圈 附视频教程_大小434M 即时通讯IM系统(H5+安卓+IOS)客户端 支持红包转账 朋友圈 群聊和群聊红包 收藏功能 语音相册 视频通话 附视频教程 项目是开发一款社交APP,具体的参考QQ、微信上的功能,与QQ、微信不同的地方在于此项目有一栏游戏专区列表,在这个列表里列出了各个热门游戏简介及入口,用户通过这个入口进入游戏,对于用户来说,首先是可以用作生活或者工作社交,其次是可以用作游戏里面的社交关系。 项目背景: 前端: 项目首先是一个APP,其次是能在其他平台上能够上线,基于公司情况,决定用 H5 开发Hybrid APP ,优点在于跨平台,一套代码多端运行,能有效节省开发周期,维护、升级、更新的工作量。且Hybrid APP 开发模式技术已经趋于成熟,性能、原生接口都有不错的体验,天猫、淘宝、京东等很多主流app大都采用这种开发模式,基于H5的Hybrid APP已经是行业趋势。 后端: 基于公司情况,大都擅长PHP,整个后端技术:PHP全系。考虑到社交类APP用户在线率、高并发、数据量庞大。 数据库方面: 要用到多个数据库联合,mysql 用作写,mongodb 用作读,实现读写分离,数据库合理设计,数据库水平切分。 缓存、集群、分布式、CDN基于情况上。 项目技术栈: 前端: 用Dcloud 的 uni-app全系,基于vue.js和微信小程序开发模式。 目前支持APP(android、ios)、H5、微信小程序、支付宝小程序5端。 在特定场景可以用weex进行原生渲染。 APP用的是Dcloud 公司的H5+进行原生接口调用。 后端: php 7.2.x thinkphp 5.1作HTTP服务(Nginx)。 getWanWork作socket服务(socket 数据交互方式是二进制数据格式)。 redis缓存,特定模块用sqllite缓存模块数据。 mysql、mongodb 数据库。 JWT进行用户验证。 使用 http 进行发送文件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值