1. 程式人生 > >Android即時通訊--仿QQ即時聊天:(五)聊天模組

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即時通訊軟體就介紹完了,功能很醜陋,原理基本能說得通,自己留一份備忘,同時也希望能幫到別人。原始碼的話,稍後整理髮出來,整個專案執行起來的效果如下。有待完善的地方還有很多,望不吝賜教,與君共勉,共同進步!!!

相關推薦

Android即時通訊--仿QQ即時聊天聊天模組

1、複雜ListView的展示 聊天模組其實就是一個複雜的ListView,在資料介面卡中,從application中獲取到當前登入的使用者,與聊天訊息中的from引數進行比較,如果兩者相同則說明是自己傳送的訊息,那麼ListView中就顯示傳送訊息的佈局,否則顯示接收訊息

Android即時通訊--仿QQ即時聊天初識Socket

/** * socket服務端 * * @author ZHY * */ public class ServerSocketTest { public static void main(String[] args) throws IOException { final ServerSock

即時通訊方案之第三方選擇比較參考

引言: 公司有三款電商類的APP,後臺使用者使用的是同一套使用者體系,現需將即時通訊功能接入到此三款APP中。 業務需求如下: 1、別人發來的訊息,此三款APP同步獲取聊

Android 開發初識ListView(列表佈局)

效果: xml: <ListView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/li

張高興的 .NET Core IoT 入門指南串列埠通訊入門

在開始之前,首先要說明的是串列埠通訊所用到的 SerialPort 類並不包含在 System.Device.Gpio NuGet 包中,而是在 System.IO.Ports NuGet 包中。之所以在這裡介紹串列埠通訊,是因為在嵌入式中串列埠通訊是與其他裝置進行互動的一種重要方式,而且在某些沒有螢幕的裝

JVM調優系列JVM常用調試參數和工具

框架 break 統計 進程 -i 內存 文件的 /etc/ action 轉自:http://blog.csdn.net/opensure/article/details/46715769 JVM常用調試參數: –verbose:gc在虛擬機發生內存

從 0 開始的微服務架構代碼給你,看如何用Docker支撐微服務

這一 復用 微軟 .com 擴展 版本發布 生產 通信 ibm 很好的一篇文章,全面、系統。 雖然已經紅了很久,但是“微服務架構”正變得越來越重要,也將繼續火下去。各個公司與技術人員都在分享微服務架構的相關知識與實踐經驗,但我們發現,目前網上的這些相關文章中,要麽上來就

八大排序算法總結快速排序

con 遞歸調用 結果 width 算法總結 調用 小數 排序算法總結 png 目的:掌握 快速排序 的 基本思想與過程、代碼實現、時間復雜度 1、基本思想與過程:(分治思想,挖坑填數)   (1)從數列中選擇一個數作為key值;   (2)將比這個數小的數全部放在它的左邊

Android自助餐】Handler訊息機制完全解析鳥瞰與總結

Android自助餐Handler訊息機制完全解析(五)鳥瞰與總結 Android自助餐Handler訊息機制完全解析五鳥瞰與總結 Message MessageQueue Handler Looper

Android學習筆記——Activity之間的跳轉

1:使用Intent(意圖)的方式實現Activity跳轉 (1)MainActivity.java: public class MainActivity extends Activity { private Button startOther; @Override pro

Spring Boot乾貨系列開發Web應用之JSP篇

前言     上一篇介紹了Spring Boot中使用Thymeleaf模板引擎,今天來介紹一下如何使用SpringBoot官方不推薦的jsp,雖然難度有點大,但是玩起來還是蠻有意思的。 正文      先來看看整體的框架結構,跟前面介紹

演算法字串

(一)字串題目的特點 ①廣泛性 字串可以看作字元型別的陣列,與陣列的排序、查詢、調整有關 很多其他型別的題可看作字串型別的題 ②需要掌握的概念 迴文 子串(連續) 子序列(不連續) 字首樹(Trie樹) 字尾樹和字尾陣列 匹配 字典序 ③需要掌握的操作

阿里雲伺服器的web專案釋出之路nodejs的安裝和專案部署詳細步驟

Nodejs如何部署在雲服務上 第一步:下載nodejs安裝包,並解壓壓縮包[解壓後預設在root下面] wget命令下載Node.js安裝包,該安裝包是編譯好的檔案,解壓之後,無需重複編 命令列:wget https://nodejs.org/dist/v6.

玩轉演算法面試LeetCode連結串列類問題

在連結串列中穿針引線 連結串列和陣列都是線性結構,但是連結串列和陣列的不同在於陣列可以隨機的對於資料進行訪問。給出索引。可以以O(1)的時間複雜度迅速訪問到該元素。 連結串列只能從頭指標開始。 next指標指向哪裡? 206. Reverse Linked List

PWA(Progressive Web App)入門系列Web Worker

前言 在說Service Worker前有必要說一下Web Worker,因為Service Worker本身就屬於Web Worker的延伸,大部分功能也是基於Web Worker進行的擴充套件。 背景 眾所周知,JavaScript引擎是以單執行緒排程的方式進行,我們無法

統計學學習筆記正態分佈

正態分佈:二項分佈極好的近似 X是隨機變數,E(X)是期望值。正態分佈(normal distribution)也稱為高斯分佈(Gaussian distribution),或者鐘形曲線(bell curve)。 (x-μ)/σ也稱為z score(注意:z score是個通用的概念,包括非正態分佈)。因

RabbitMQ學習之Exchange Type 轉貼+我的評論

This is the fourth installment to the series: RabbitMQ for Windows.  In the last installment, we reviewed our Hello World example and introduced the con

Spring Cloud之路Spring Boot + Mybatis小試

一、Mybatis 1、介紹   MyBatis 是一款優秀的持久層框架,它支援定製化 SQL、儲存過程以及高階對映。MyBatis 避免了幾乎所有的 JDBC 程式碼和手動設定引數以及獲取結果集。MyBatis 可以使用簡單的 XML 或註解來配置和對映原生資訊,將介面和 Ja

機器學習系列決策樹——非線性迴歸與分類

和猜猜看一樣,決策樹也是通過對解釋變數序列的逐條測試獲取響應變數結果的。那麼,哪個解釋變數應該先測試?直覺觀察會發現,解釋變數集合包含所有貓或者所有狗的測試,比既包含貓又包含狗的解釋變數集合的測試要好。如果子整合員種類不同,我們還是不能確定種類。我們還需要避免建立那種測試,把單獨的一隻貓或一條狗分離出

Android UI設計——ListView控制元件使用優化

  在上一篇部落格中《Android UI設計——ListView控制元件和自定義Adapter(四) 》(連結)中我們通過一個例項來了解和練習瞭如何去自定義Adapter,本節我們將會繼續以《Android UI設計——ListView控制元件和自定義Adap