[置顶] Android即时通讯--仿QQ即时聊天:(四)好友列表的处理

好友列表的布局非常简单,就是一个ListView控件而已。首先根据服务器返回的联系人数据封装Java对象。服务器返回来的json串如下:

<span style="font-size:18px;">{
    "buddyList": [
        {
            "account": 101,
            "avatar": 0,
            "nick": "aa"
        },
        {
            "account": 101,
            "avatar": 0,
            "nick": "aa"
        }
    ]
}</span>

由以上json串分析可知,服务器返回来的是一个集合,集合中的参数是buddyList,集合中有两个联系人,每个联系人中的参数分别是account、avatar、nick,根据这三个参数封装联系人对象,如下,一个ContactInfo代表一个联系人。

/**
 * 好友列表的信息,listView条目的信息,包括头像,昵称,个性签名
 * 
 * @author ZHY
 * 
 */
public class ContactInfo {
	// "account": 101,
	// "avatar": 0,
	// "nick": "aa"
	public long account;
	public int avatar;
	public String nick;

}
服务器返回的联系人列表是一个封装这ContactInfo对象的List集合,代码如下

/**
 * 好友列表的信息,listView条目的信息,包括头像,昵称,个性签名
 * 
 * @author ZHY
 * 
 */
public class ContactInfoList {
	// "account": 101,
	// "avatar": 0,
	// "nick": "aa"
	public List<ContactInfo> buddyList = new ArrayList<ContactInfo>();

}

在联系人列表的页面,首先获取在登录页面中保存到application中的联系人的json串,然后将json串序列化为联系人的Java对象ContactInfoList,这个对象的buddyList字段表示的其实就是联系人列表。数据处理好之后,处理ListView的数据适配器,代码如下

/**
 * 联系人列表的适配器
 * 
 * @author ZHY
 * 
 */
public class ContactInfoAdapter extends ArrayAdapter<ContactInfo> {

	/**
	 * 传入上下文与集合
	 * 
	 * @param context
	 * @param objects
	 */
	public ContactInfoAdapter(Context context, List<ContactInfo> objects) {
		super(context, 0, objects);
	}

	class ViewHolder {
		ImageView icon;
		TextView title;
		TextView desc;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ContactInfo info = getItem(position);// 从集合中取得数据
		// listView的优化
		ViewHolder holder;
		if (convertView == null) {
			convertView = View.inflate(getContext(),
					R.layout.view_item_contact, null);
			holder = new ViewHolder();
			holder.icon = (ImageView) convertView.findViewById(R.id.icon);
			holder.title = (TextView) convertView.findViewById(R.id.title);
			holder.desc = (TextView) convertView.findViewById(R.id.desc);
			convertView.setTag(holder);

		} else {
			holder = (ViewHolder) convertView.getTag();
		}

		// 赋值
		if (info.avatar == 0) {
			// 默认头像
			holder.icon.setImageResource(R.drawable.ic_launcher);
		} else {
			holder.icon.setImageResource(info.avatar);
		}
		// 如果是自己登录的账号,则显示自己,否则显示账号
		// 获得保存在application中的自己登录的账号

		holder.title.setText(info.account + "");

		holder.desc.setText(info.nick);
		return convertView;
	}
}
这样就能够得到当前登录用户的在线好友列表。然而当有好友上线的时候不能够即时的刷新上线好友,需要在好友列表的界面添加监听器,实时的监听是否有好友上线,一旦有好友上线,立马更新界面。添加监听器的方式与登录页面类似,这里不再赘述。好友类表的页面代码如下:

/**
 * 显示联系人
 * 
 * @author ZHY
 * 
 */
public class MainActivity extends Activity {
	/**
	 * listView的使用分三步,获得listView容器,封装集合数据,写数据适配器加载listView条目的布局
	 */
	@ViewInject(R.id.listview)
	ListView listView;
	// listView的集合
	private List<ContactInfo> infos = new ArrayList<ContactInfo>();
	private ImApp app;
	private ContactInfoAdapter adapter;
	/**
	 * 好友上线刷新好友列表,添加消息监听器,如果有新上线的好友,则更新数据集合,通知数据适配器数据发生了变化,进而更新好友列表
	 */
	private OnMessageListener listener = new OnMessageListener() {

		public void onReveive(final QQMessage msg) {
			/**
			 * 注意:onReceive是在子线程中进行,而更新listView列表数据要在Ui线程中
			 */
			ThreadUtils.runInUiThread(new Runnable() {

				public void run() {

					// 如有服务器返回好友列表,则说明有好友上线\
					if (QQMessageType.MSG_TYPE_BUDDY_LIST.equals(msg.type)) {
						// 有好友上线
						String newBuddyListJson = msg.content;// 新上线好友的信息json串
						// 讲json转成集合,更新一下infos集合
						Gson gson = new Gson();
						ContactInfoList newList = gson.fromJson(
								newBuddyListJson, ContactInfoList.class);// 新上线好友的集合
						infos.clear();// 清空一下原来的好友类表集合
						infos.addAll(newList.buddyList);// 新的好友列表
						if (adapter != null) {
							// 更新好友列表界面
							adapter.notifyDataSetChanged();
						}
					}

				}
			});
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		ViewUtils.inject(this);
		// /**
		// * 假数据
		// */
		// for (int i = 0; i < 20; i++) {
		// ContactInfo info = new ContactInfo();
		// info.account = new Long(100 + i);
		// info.avatar = 0;
		// info.nick = "hjahahah" + i;
		// infos.add(info);
		// }
		/**
		 * 把假数据变成真数据
		 */
		// 数据保存在application中
		app = (ImApp) getApplication();
		// 获取长连接,往长连接里添加监听,时刻监听服务器返回来的消息,如果有消息到达,就执行onReceive
		app.getMyConn().addOnMessageListener(listener);

		// 好友列表的json串
		String buddyListJson = app.getBuddyListJson();
		System.out.println(buddyListJson);
		Gson gson = new Gson();
		ContactInfoList list = gson.fromJson(buddyListJson,
				ContactInfoList.class);
		infos.addAll(list.buddyList);// buddyList是一个集合,把buddyList集合里的东西全部添加进infos
		adapter = new ContactInfoAdapter(getBaseContext(), infos);
		listView.setAdapter(adapter);

		listView.setOnItemClickListener(new OnItemClickListener() {

			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				// 获得当前点击条目的信息.包含账号和昵称
				ContactInfo info = infos.get(position);
				// 不能跟自己聊天
				if (info.account != app.getMyAccount()) {
					Intent intent = new Intent(getBaseContext(),
							ChartActivity.class);
					// 将账号和个性签名带到下一个activity
					intent.putExtra("account", info.account);
					intent.putExtra("nick", info.nick);
					// TODO 聊天界面
					startActivity(intent);

				} else {
					Toast.makeText(getBaseContext(), "不能跟自己聊天", 0).show();
				}

			}
		});

	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		app.getMyConn().removeOnMessageListener(listener);

	}
}
好了,好友列表也能正常显示了,接下来就是聊天功能的实现,给listView的条目添加点击事件,当点击某一个条目的时候,拿到该位置的账号和昵称,通过Intent发送到聊天页面,这样才能明确要把消息发给谁。


你可能感兴趣的:(线程,socket,即时通讯,仿qq,客户端与服务器)