環(huán)信官方Demo源碼分析及SDK簡(jiǎn)單應(yīng)用-主界面的三個(gè)fragment-會(huì)話(huà)界面

環(huán)信官方Demo源碼分析及SDK簡(jiǎn)單應(yīng)用

環(huán)信官方Demo源碼分析及SDK簡(jiǎn)單應(yīng)用-ChatDemoUI3.0

環(huán)信官方Demo源碼分析及SDK簡(jiǎn)單應(yīng)用-LoginActivity

環(huán)信官方Demo源碼分析及SDK簡(jiǎn)單應(yīng)用-主界面的三個(gè)fragment-會(huì)話(huà)界面

環(huán)信官方Demo源碼分析及SDK簡(jiǎn)單應(yīng)用-主界面的三個(gè)fragment-通訊錄界面

環(huán)信官方Demo源碼分析及SDK簡(jiǎn)單應(yīng)用-主界面的三個(gè)fragment-設(shè)置界面

環(huán)信官方Demo源碼分析及SDK簡(jiǎn)單應(yīng)用-EaseUI

環(huán)信官方Demo源碼分析及SDK簡(jiǎn)單應(yīng)用-IM集成開(kāi)發(fā)詳案及具體代碼實(shí)現(xiàn)

現(xiàn)在來(lái)看具體的主界面的三個(gè)Fragment

主界面的三個(gè)fragment

會(huì)話(huà)界面

? 我們來(lái)看會(huì)話(huà)界面的代碼

package com.hyphenate.chatuidemo.ui;

?

import android.content.Intent;

import android.view.ContextMenu;

import android.view.ContextMenu.ContextMenuInfo;

import android.view.MenuItem;

import android.view.View;

import android.widget.AdapterView;

import android.widget.AdapterView.AdapterContextMenuInfo;

import android.widget.AdapterView.OnItemClickListener;

import android.widget.LinearLayout;

import android.widget.TextView;

import android.widget.Toast;

?

import com.easemob.redpacketsdk.constant.RPConstant;

import com.hyphenate.chat.EMClient;

import com.hyphenate.chat.EMConversation;

import com.hyphenate.chat.EMConversation.EMConversationType;

import com.hyphenate.chat.EMMessage;

import com.hyphenate.chatuidemo.Constant;

import com.hyphenate.chatuidemo.R;

import com.hyphenate.chatuidemo.db.InviteMessgeDao;

import com.hyphenate.easeui.model.EaseAtMessageHelper;

import com.hyphenate.easeui.ui.EaseConversationListFragment;

import com.hyphenate.easeui.widget.EaseConversationList.EaseConversationListHelper;

import com.hyphenate.util.NetUtils;

?

public class ConversationListFragment extends EaseConversationListFragment{

?

private TextView errorText;

?

@Override

protected void initView() {

super.initView();

View errorView = (LinearLayout) View.inflate(getActivity(),R.layout.em_chat_neterror_item, null);

errorItemContainer.addView(errorView);

errorText = (TextView) errorView.findViewById(R.id.tv_connect_errormsg);

}

@Override

protected void setUpView() {

super.setUpView();

// register context menu

registerForContextMenu(conversationListView);

conversationListView.setOnItemClickListener(new OnItemClickListener() {

?

@Override

public void onItemClick(AdapterView parent, View view, int position, long id) {

EMConversation conversation = conversationListView.getItem(position);

String username = conversation.conversationId();

if (username.equals(EMClient.getInstance().getCurrentUser()))

Toast.makeText(getActivity(), R.string.Cant_chat_with_yourself, Toast.LENGTH_SHORT).show();

else {

// start chat acitivity

Intent intent = new Intent(getActivity(), ChatActivity.class);

if(conversation.isGroup()){

if(conversation.getType() == EMConversationType.ChatRoom){

// it's group chat

intent.putExtra(Constant.EXTRA_CHAT_TYPE, Constant.CHATTYPE_CHATROOM);

}else{

intent.putExtra(Constant.EXTRA_CHAT_TYPE, Constant.CHATTYPE_GROUP);

}

}

// it's single chat

intent.putExtra(Constant.EXTRA_USER_ID, username);

startActivity(intent);

}

}

});

//red packet code : 紅包回執(zhí)消息在會(huì)話(huà)列表最后一條消息的展示

conversationListView.setConversationListHelper(new EaseConversationListHelper() {

@Override

public String onSetItemSecondaryText(EMMessage lastMessage) {

if (lastMessage.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_ACK_MESSAGE, false)) {

String sendNick = lastMessage.getStringAttribute(RPConstant.EXTRA_RED_PACKET_SENDER_NAME, "");

String receiveNick = lastMessage.getStringAttribute(RPConstant.EXTRA_RED_PACKET_RECEIVER_NAME, "");

String msg;

if (lastMessage.direct() == EMMessage.Direct.RECEIVE) {

msg = String.format(getResources().getString(R.string.msg_someone_take_red_packet), receiveNick);

} else {

if (sendNick.equals(receiveNick)) {

msg = getResources().getString(R.string.msg_take_red_packet);

} else {

msg = String.format(getResources().getString(R.string.msg_take_someone_red_packet), sendNick);

}

}

return msg;

} else if (lastMessage.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_TRANSFER_PACKET_MESSAGE, false)) {

String transferAmount = lastMessage.getStringAttribute(RPConstant.EXTRA_TRANSFER_AMOUNT, "");

String msg;

if (lastMessage.direct() == EMMessage.Direct.RECEIVE) {

msg =? String.format(getResources().getString(R.string.msg_transfer_to_you), transferAmount);

} else {

msg =? String.format(getResources().getString(R.string.msg_transfer_from_you),transferAmount);

}

return msg;

}

return null;

}

});

super.setUpView();

//end of red packet code

}

?

@Override

protected void onConnectionDisconnected() {

super.onConnectionDisconnected();

if (NetUtils.hasNetwork(getActivity())){

errorText.setText(R.string.can_not_connect_chat_server_connection);

} else {

errorText.setText(R.string.the_current_network);

}

}

@Override

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {

getActivity().getMenuInflater().inflate(R.menu.em_delete_message, menu);

}

?

@Override

public boolean onContextItemSelected(MenuItem item) {

boolean deleteMessage = false;

if (item.getItemId() == R.id.delete_message) {

deleteMessage = true;

} else if (item.getItemId() == R.id.delete_conversation) {

deleteMessage = false;

}

EMConversation tobeDeleteCons = conversationListView.getItem(((AdapterContextMenuInfo) item.getMenuInfo()).position);

if (tobeDeleteCons == null) {

return true;

}

if(tobeDeleteCons.getType() == EMConversationType.GroupChat){

EaseAtMessageHelper.get().removeAtMeGroup(tobeDeleteCons.conversationId());

}

try {

// delete conversation

EMClient.getInstance().chatManager().deleteConversation(tobeDeleteCons.conversationId(), deleteMessage);

InviteMessgeDao inviteMessgeDao = new InviteMessgeDao(getActivity());

inviteMessgeDao.deleteMessage(tobeDeleteCons.conversationId());

} catch (Exception e) {

e.printStackTrace();

}

refresh();

?

// update unread count

((MainActivity) getActivity()).updateUnreadLabel();

return true;

}

?

}

我們還是挨個(gè)來(lái)讀代碼

public class ConversationListFragment extends EaseConversationListFragment

來(lái),我們還是得先去找他爹算賬。

public class EaseConversationListFragment extends EaseBaseFragment

哎呀,我們?cè)偃フ宜麪敔敗?/p>

public abstract class EaseBaseFragment extends Fragment

爺爺終于正常點(diǎn)是從Android系統(tǒng)類(lèi)繼承下來(lái)的了,我們看具體的代碼

EaseBaseFragment

package com.hyphenate.easeui.ui;

import android.content.Context;

import android.os.Bundle;

import android.support.v4.app.Fragment;

import android.view.View;

import android.view.WindowManager;

import android.view.inputmethod.InputMethodManager;

import com.hyphenate.easeui.R;

import com.hyphenate.easeui.widget.EaseTitleBar;

public abstract class EaseBaseFragment extends Fragment{

protected EaseTitleBar titleBar;

protected InputMethodManager inputMethodManager;

@Override

public void onActivityCreated(Bundle savedInstanceState) {

super.onActivityCreated(savedInstanceState);

inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);

//noinspection ConstantConditions

titleBar = (EaseTitleBar) getView().findViewById(R.id.title_bar);

initView();

setUpView();

}

public void showTitleBar(){

if(titleBar != null){

titleBar.setVisibility(View.VISIBLE);

}

}

public void hideTitleBar(){

if(titleBar != null){

titleBar.setVisibility(View.GONE);

}

}

protected void hideSoftKeyboard() {

if (getActivity().getWindow().getAttributes().softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) {

if (getActivity().getCurrentFocus() != null)

inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),

InputMethodManager.HIDE_NOT_ALWAYS);

}

}

protected abstract void initView();

protected abstract void setUpView();

}

我們還是挨個(gè)來(lái)看代碼,研究他的功能。

@Override

public void onActivityCreated(Bundle savedInstanceState) {

super.onActivityCreated(savedInstanceState);

inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);

//noinspection ConstantConditions

titleBar = (EaseTitleBar) getView().findViewById(R.id.title_bar);

initView();

setUpView();

}

隱藏輸入法

看到inputmethdManager要干嘛啊,隱藏鍵盤(pán)。果不其然。

protected void hideSoftKeyboard() {

if (getActivity().getWindow().getAttributes().softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) {

if (getActivity().getCurrentFocus() != null)

inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),

InputMethodManager.HIDE_NOT_ALWAYS);

}

}

然后呢?

初始化標(biāo)題頭?

//noinspection ConstantConditions

titleBar = (EaseTitleBar) getView().findViewById(R.id.title_bar);

最后初始化標(biāo)題頭,并且讓子孫們?nèi)?shí)現(xiàn)抽象方法initView和setUpView().

隱藏和顯示標(biāo)題頭

其中還提供了兩個(gè)方法,隱藏和顯示標(biāo)題頭

public void showTitleBar(){

if(titleBar != null){

titleBar.setVisibility(View.VISIBLE);

}

}

public void hideTitleBar(){

if(titleBar != null){

titleBar.setVisibility(View.GONE);

}

}

好了,爺爺?shù)膸に阃炅耍覀儊?lái)找他兒子。

EaseConversationListFragment

我們來(lái)看代碼

package com.hyphenate.easeui.ui;

?

import android.content.Context;

import android.os.Bundle;

import android.os.Handler;

import android.text.Editable;

import android.text.TextWatcher;

import android.util.Pair;

import android.view.LayoutInflater;

import android.view.MotionEvent;

import android.view.View;

import android.view.View.OnClickListener;

import android.view.View.OnTouchListener;

import android.view.ViewGroup;

import android.view.WindowManager;

import android.view.inputmethod.InputMethodManager;

import android.widget.AdapterView;

import android.widget.AdapterView.OnItemClickListener;

import android.widget.EditText;

import android.widget.FrameLayout;

import android.widget.ImageButton;

?

import com.hyphenate.EMConnectionListener;

import com.hyphenate.EMConversationListener;

import com.hyphenate.EMError;

import com.hyphenate.chat.EMClient;

import com.hyphenate.chat.EMConversation;

import com.hyphenate.easeui.R;

import com.hyphenate.easeui.widget.EaseConversationList;

?

import java.util.ArrayList;

import java.util.Collections;

import java.util.Comparator;

import java.util.List;

import java.util.Map;

?

/**

* conversation list fragment

*

*/

public class EaseConversationListFragment extends EaseBaseFragment{

private final static int MSG_REFRESH = 2;

protected EditText query;

protected ImageButton clearSearch;

protected boolean hidden;

protected List conversationList = new ArrayList();

protected EaseConversationList conversationListView;

protected FrameLayout errorItemContainer;

?

protected boolean isConflict;

protected EMConversationListener convListener = new EMConversationListener(){

?

@Override

public void onCoversationUpdate() {

refresh();

}

};

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

return inflater.inflate(R.layout.ease_fragment_conversation_list, container, false);

}

?

@Override

public void onActivityCreated(Bundle savedInstanceState) {

if(savedInstanceState != null && savedInstanceState.getBoolean("isConflict", false))

return;

super.onActivityCreated(savedInstanceState);

}

?

@Override

protected void initView() {

inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);

conversationListView = (EaseConversationList) getView().findViewById(R.id.list);

query = (EditText) getView().findViewById(R.id.query);

// button to clear content in search bar

clearSearch = (ImageButton) getView().findViewById(R.id.search_clear);

errorItemContainer = (FrameLayout) getView().findViewById(R.id.fl_error_item);

}

@Override

protected void setUpView() {

conversationList.addAll(loadConversationList());

conversationListView.init(conversationList);

if(listItemClickListener != null){

conversationListView.setOnItemClickListener(new OnItemClickListener() {

?

@Override

public void onItemClick(AdapterView parent, View view, int position, long id) {

EMConversation conversation = conversationListView.getItem(position);

listItemClickListener.onListItemClicked(conversation);

}

});

}

EMClient.getInstance().addConnectionListener(connectionListener);

query.addTextChangedListener(new TextWatcher() {

public void onTextChanged(CharSequence s, int start, int before, int count) {

conversationListView.filter(s);

if (s.length() > 0) {

clearSearch.setVisibility(View.VISIBLE);

} else {

clearSearch.setVisibility(View.INVISIBLE);

}

}

?

public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

?

public void afterTextChanged(Editable s) {

}

});

clearSearch.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

query.getText().clear();

hideSoftKeyboard();

}

});

conversationListView.setOnTouchListener(new OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

hideSoftKeyboard();

return false;

}

});

}

protected EMConnectionListener connectionListener = new EMConnectionListener() {

@Override

public void onDisconnected(int error) {

if (error == EMError.USER_REMOVED || error == EMError.USER_LOGIN_ANOTHER_DEVICE || error == EMError.SERVER_SERVICE_RESTRICTED) {

isConflict = true;

} else {

handler.sendEmptyMessage(0);

}

}

@Override

public void onConnected() {

handler.sendEmptyMessage(1);

}

};

private EaseConversationListItemClickListener listItemClickListener;

protected Handler handler = new Handler(){

public void handleMessage(android.os.Message msg) {

switch (msg.what) {

case 0:

onConnectionDisconnected();

break;

case 1:

onConnectionConnected();

break;

case MSG_REFRESH:

{

conversationList.clear();

conversationList.addAll(loadConversationList());

conversationListView.refresh();

break;

}

default:

break;

}

}

};

/**

* connected to server

*/

protected void onConnectionConnected(){

errorItemContainer.setVisibility(View.GONE);

}

/**

* disconnected with server

*/

protected void onConnectionDisconnected(){

errorItemContainer.setVisibility(View.VISIBLE);

}

?

/**

* refresh ui

*/

public void refresh() {

if(!handler.hasMessages(MSG_REFRESH)){

handler.sendEmptyMessage(MSG_REFRESH);

}

}

/**

* load conversation list

*

* @return

+? ? */

protected List loadConversationList(){

// get all conversations

Map conversations = EMClient.getInstance().chatManager().getAllConversations();

List> sortList = new ArrayList>();

/**

* lastMsgTime will change if there is new message during sorting

* so use synchronized to make sure timestamp of last message won't change.

*/

synchronized (conversations) {

for (EMConversation conversation : conversations.values()) {

if (conversation.getAllMessages().size() != 0) {

sortList.add(new Pair(conversation.getLastMessage().getMsgTime(), conversation));

}

}

}

try {

// Internal is TimSort algorithm, has bug

sortConversationByLastChatTime(sortList);

} catch (Exception e) {

e.printStackTrace();

}

List list = new ArrayList();

for (Pair sortItem : sortList) {

list.add(sortItem.second);

}

return list;

}

?

/**

* sort conversations according time stamp of last message

*

* @param conversationList

*/

private void sortConversationByLastChatTime(List> conversationList) {

Collections.sort(conversationList, new Comparator>() {

@Override

public int compare(final Pair con1, final Pair con2) {

?

if (con1.first.equals(con2.first)) {

return 0;

} else if (con2.first.longValue() > con1.first.longValue()) {

return 1;

} else {

return -1;

}

}

?

});

}

protected void hideSoftKeyboard() {

if (getActivity().getWindow().getAttributes().softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) {

if (getActivity().getCurrentFocus() != null)

inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),

InputMethodManager.HIDE_NOT_ALWAYS);

}

}

?

@Override

public void onHiddenChanged(boolean hidden) {

super.onHiddenChanged(hidden);

this.hidden = hidden;

if (!hidden && !isConflict) {

refresh();

}

}

?

@Override

public void onResume() {

super.onResume();

if (!hidden) {

refresh();

}

}

@Override

public void onDestroy() {

super.onDestroy();

EMClient.getInstance().removeConnectionListener(connectionListener);

}

@Override

public void onSaveInstanceState(Bundle outState) {

super.onSaveInstanceState(outState);

if(isConflict){

outState.putBoolean("isConflict", true);

}

}

public interface EaseConversationListItemClickListener {

/**

* click event for conversation list

* @param conversation -- clicked item

*/

void onListItemClicked(EMConversation conversation);

}

/**

* set conversation list item click listener

* @param listItemClickListener

*/

public void setConversationListItemClickListener(EaseConversationListItemClickListener listItemClickListener){

this.listItemClickListener = listItemClickListener;

}

?

}

填充布局

首先onCreateView(),正常的填充了布局

return inflater.inflate(R.layout.ease_fragment_conversation_list, container, false);

繼續(xù)看代碼

@Override

public void onActivityCreated(Bundle savedInstanceState) {

if(savedInstanceState != null && savedInstanceState.getBoolean("isConflict", false))

return;

super.onActivityCreated(savedInstanceState);

}

判斷沖突標(biāo)志位

@Override

protected void initView() {

inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);

conversationListView = (EaseConversationList) getView().findViewById(R.id.list);

query = (EditText) getView().findViewById(R.id.query);

// button to clear content in search bar

clearSearch = (ImageButton) getView().findViewById(R.id.search_clear);

errorItemContainer = (FrameLayout) getView().findViewById(R.id.fl_error_item);

}

initView()

覆寫(xiě)爺爺?shù)募乙?guī),初始化View輸入法管理器

會(huì)話(huà)列表List

查找聯(lián)系人的輸入框

清除搜索的按鈕

errorItemContainer 錯(cuò)誤標(biāo)簽容器

繼續(xù)看代碼setUpView()方法

setUpView()

conversationList.addAll(loadConversationList());

conversationListView.init(conversationList);

?

if(listItemClickListener != null){

conversationListView.setOnItemClickListener(new OnItemClickListener() {

?

@Override

public void onItemClick(AdapterView parent, View view, int position, long id) {

EMConversation conversation = conversationListView.getItem(position);

listItemClickListener.onListItemClicked(conversation);

}

});

}

?

EMClient.getInstance().addConnectionListener(connectionListener);

?

query.addTextChangedListener(new TextWatcher() {

public void onTextChanged(CharSequence s, int start, int before, int count) {

conversationListView.filter(s);

if (s.length() > 0) {

clearSearch.setVisibility(View.VISIBLE);

} else {

clearSearch.setVisibility(View.INVISIBLE);

}

}

?

public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

?

public void afterTextChanged(Editable s) {

}

});

clearSearch.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

query.getText().clear();

hideSoftKeyboard();

}

});

?

conversationListView.setOnTouchListener(new OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

hideSoftKeyboard();

return false;

}

});

我們一句句的看

conversationList.addAll(loadConversationList());

conversationListView.init(conversationList);

會(huì)話(huà)列表添加全部以及數(shù)據(jù)填充初始化。

我們來(lái)看具體的方法

/**

* load conversation list

*

* @return

*/

protected List loadConversationList(){

// get all conversations

Map conversations = EMClient.getInstance().chatManager().getAllConversations();

List> sortList = new ArrayList>();

/**

* lastMsgTime will change if there is new message during sorting

* so use synchronized to make sure timestamp of last message won't change.

*/

synchronized (conversations) {

for (EMConversation conversation : conversations.values()) {

if (conversation.getAllMessages().size() != 0) {

sortList.add(new Pair(conversation.getLastMessage().getMsgTime(), conversation));

}

}

}

try {

// Internal is TimSort algorithm, has bug

sortConversationByLastChatTime(sortList);

} catch (Exception e) {

e.printStackTrace();

}

List list = new ArrayList();

for (Pair sortItem : sortList) {

list.add(sortItem.second);

}

return list;

}

loadConversationList()返回一個(gè)EMConversation對(duì)象List。

// get all conversations

Map conversations = EMClient.getInstance().chatManager().getAllConversations();

List> sortList = new ArrayList>();

通過(guò)封裝的chatManager拿到所有的會(huì)話(huà)列表

/**

* lastMsgTime will change if there is new message during sorting

* so use synchronized to make sure timestamp of last message won't change.

*/

synchronized (conversations) {

for (EMConversation conversation : conversations.values()) {

if (conversation.getAllMessages().size() != 0) {

sortList.add(new Pair(conversation.getLastMessage().getMsgTime(), conversation));

}

}

}

lastMsgTime會(huì)隨著新消息的到來(lái)排序發(fā)生改變,所以我們用同步方法確保最新消息的時(shí)間戳不發(fā)生改變。

英文不好,大致是這么個(gè)意思。

try {

// Internal is TimSort algorithm, has bug

sortConversationByLastChatTime(sortList);

} catch (Exception e) {

e.printStackTrace();

}

List list = new ArrayList();

for (Pair sortItem : sortList) {

list.add(sortItem.second);

}

return list;

其中還特地注釋了一把,算法有點(diǎn)bug。

/**

* sort conversations according time stamp of last message

*

* @param conversationList

*/

private void sortConversationByLastChatTime(List> conversationList) {

Collections.sort(conversationList, new Comparator>() {

@Override

public int compare(final Pair con1, final Pair con2) {

?

if (con1.first.equals(con2.first)) {

return 0;

} else if (con2.first.longValue() > con1.first.longValue()) {

return 1;

} else {

return -1;

}

}

?

});

根據(jù)最新的會(huì)話(huà)時(shí)間戳來(lái)排序。

我們接著看

List list = new ArrayList();

for (Pair sortItem : sortList) {

list.add(sortItem.second);

}

return list;

添加完了返回list。

conversationListView.init(conversationList);

接著就初始化了。

if(listItemClickListener != null){

conversationListView.setOnItemClickListener(new OnItemClickListener() {

?

@Override

public void onItemClick(AdapterView parent, View view, int position, long id) {

EMConversation conversation = conversationListView.getItem(position);

listItemClickListener.onListItemClicked(conversation);

}

});

}

然后便是連接接聽(tīng)

EMClient.getInstance().addConnectionListener(connectionListener);

添加了一個(gè)連接的監(jiān)聽(tīng)。

protected EMConnectionListener connectionListener = new EMConnectionListener() {

@Override

public void onDisconnected(int error) {

if (error == EMError.USER_REMOVED || error == EMError.USER_LOGIN_ANOTHER_DEVICE || error == EMError.SERVER_SERVICE_RESTRICTED) {

isConflict = true;

} else {

handler.sendEmptyMessage(0);

}

}

@Override

public void onConnected() {

handler.sendEmptyMessage(1);

}

};

在斷開(kāi)連接時(shí)判斷用戶(hù)是否移除,是否在其他設(shè)備登陸,或者服務(wù)端的服務(wù)受到限制,是的話(huà)則標(biāo)記沖突。不是則發(fā)送handler空消息。

protected Handler handler = new Handler(){

public void handleMessage(android.os.Message msg) {

switch (msg.what) {

case 0:

onConnectionDisconnected();

break;

case 1:

onConnectionConnected();

break;

case MSG_REFRESH:

{

conversationList.clear();

conversationList.addAll(loadConversationList());

conversationListView.refresh();

break;

}

default:

break;

}

}

};

干嘛啊?調(diào)用 onConnectionDisconnected 即連接斷開(kāi)的處理方法

/**

* disconnected with server

*/

protected void onConnectionDisconnected(){

errorItemContainer.setVisibility(View.VISIBLE);

}

即顯示錯(cuò)誤條。

我們?cè)俳又创a

query.addTextChangedListener(new TextWatcher() {

public void onTextChanged(CharSequence s, int start, int before, int count) {

conversationListView.filter(s);

if (s.length() > 0) {

clearSearch.setVisibility(View.VISIBLE);

} else {

clearSearch.setVisibility(View.INVISIBLE);

}

}

?

public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

?

public void afterTextChanged(Editable s) {

}

});

clearSearch.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

query.getText().clear();

hideSoftKeyboard();

}

});

?

conversationListView.setOnTouchListener(new OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

hideSoftKeyboard();

return false;

}

});

干了些什么啊?查詢(xún)、清除搜索、會(huì)話(huà)列表點(diǎn)擊監(jiān)聽(tīng)。

其他方法?

/**

* connected to server

*/

protected void onConnectionConnected(){

errorItemContainer.setVisibility(View.GONE);

}

連接后將錯(cuò)誤條隱藏

case MSG_REFRESH:

{

conversationList.clear();

conversationList.addAll(loadConversationList());

conversationListView.refresh();

break;

}

服務(wù)器告訴要刷新了,那么我們就去清楚列表,然后去服務(wù)器拿并排序,然后刷新listview。其中該listview為自定義的EaseConversationList。

那么兒子齊活了,我們?cè)倏磳O子

ConversationListFragment

package com.hyphenate.chatuidemo.ui;

?

import android.content.Intent;

import android.view.ContextMenu;

import android.view.ContextMenu.ContextMenuInfo;

import android.view.MenuItem;

import android.view.View;

import android.widget.AdapterView;

import android.widget.AdapterView.AdapterContextMenuInfo;

import android.widget.AdapterView.OnItemClickListener;

import android.widget.LinearLayout;

import android.widget.TextView;

import android.widget.Toast;

?

import com.easemob.redpacketsdk.constant.RPConstant;

import com.hyphenate.chat.EMClient;

import com.hyphenate.chat.EMConversation;

import com.hyphenate.chat.EMConversation.EMConversationType;

import com.hyphenate.chat.EMMessage;

import com.hyphenate.chatuidemo.Constant;

import com.hyphenate.chatuidemo.R;

import com.hyphenate.chatuidemo.db.InviteMessgeDao;

import com.hyphenate.easeui.model.EaseAtMessageHelper;

import com.hyphenate.easeui.ui.EaseConversationListFragment;

import com.hyphenate.easeui.widget.EaseConversationList.EaseConversationListHelper;

import com.hyphenate.util.NetUtils;

?

public class ConversationListFragment extends EaseConversationListFragment{

?

private TextView errorText;

?

@Override

protected void initView() {

super.initView();

View errorView = (LinearLayout) View.inflate(getActivity(),R.layout.em_chat_neterror_item, null);

errorItemContainer.addView(errorView);

errorText = (TextView) errorView.findViewById(R.id.tv_connect_errormsg);

}

@Override

protected void setUpView() {

super.setUpView();

// register context menu

registerForContextMenu(conversationListView);

conversationListView.setOnItemClickListener(new OnItemClickListener() {

?

@Override

public void onItemClick(AdapterView parent, View view, int position, long id) {

EMConversation conversation = conversationListView.getItem(position);

String username = conversation.conversationId();

if (username.equals(EMClient.getInstance().getCurrentUser()))

Toast.makeText(getActivity(), R.string.Cant_chat_with_yourself, Toast.LENGTH_SHORT).show();

else {

// start chat acitivity

Intent intent = new Intent(getActivity(), ChatActivity.class);

if(conversation.isGroup()){

if(conversation.getType() == EMConversationType.ChatRoom){

// it's group chat

intent.putExtra(Constant.EXTRA_CHAT_TYPE, Constant.CHATTYPE_CHATROOM);

}else{

intent.putExtra(Constant.EXTRA_CHAT_TYPE, Constant.CHATTYPE_GROUP);

}

}

// it's single chat

intent.putExtra(Constant.EXTRA_USER_ID, username);

startActivity(intent);

}

}

});

//red packet code : 紅包回執(zhí)消息在會(huì)話(huà)列表最后一條消息的展示

conversationListView.setConversationListHelper(new EaseConversationListHelper() {

@Override

public String onSetItemSecondaryText(EMMessage lastMessage) {

if (lastMessage.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_ACK_MESSAGE, false)) {

String sendNick = lastMessage.getStringAttribute(RPConstant.EXTRA_RED_PACKET_SENDER_NAME, "");

String receiveNick = lastMessage.getStringAttribute(RPConstant.EXTRA_RED_PACKET_RECEIVER_NAME, "");

String msg;

if (lastMessage.direct() == EMMessage.Direct.RECEIVE) {

msg = String.format(getResources().getString(R.string.msg_someone_take_red_packet), receiveNick);

} else {

if (sendNick.equals(receiveNick)) {

msg = getResources().getString(R.string.msg_take_red_packet);

} else {

msg = String.format(getResources().getString(R.string.msg_take_someone_red_packet), sendNick);

}

}

return msg;

} else if (lastMessage.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_TRANSFER_PACKET_MESSAGE, false)) {

String transferAmount = lastMessage.getStringAttribute(RPConstant.EXTRA_TRANSFER_AMOUNT, "");

String msg;

if (lastMessage.direct() == EMMessage.Direct.RECEIVE) {

msg =? String.format(getResources().getString(R.string.msg_transfer_to_you), transferAmount);

} else {

msg =? String.format(getResources().getString(R.string.msg_transfer_from_you),transferAmount);

}

return msg;

}

return null;

}

});

super.setUpView();

//end of red packet code

}

?

@Override

protected void onConnectionDisconnected() {

super.onConnectionDisconnected();

if (NetUtils.hasNetwork(getActivity())){

errorText.setText(R.string.can_not_connect_chat_server_connection);

} else {

errorText.setText(R.string.the_current_network);

}

}

@Override

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {

getActivity().getMenuInflater().inflate(R.menu.em_delete_message, menu);

}

?

@Override

public boolean onContextItemSelected(MenuItem item) {

boolean deleteMessage = false;

if (item.getItemId() == R.id.delete_message) {

deleteMessage = true;

} else if (item.getItemId() == R.id.delete_conversation) {

deleteMessage = false;

}

EMConversation tobeDeleteCons = conversationListView.getItem(((AdapterContextMenuInfo) item.getMenuInfo()).position);

if (tobeDeleteCons == null) {

return true;

}

if(tobeDeleteCons.getType() == EMConversationType.GroupChat){

EaseAtMessageHelper.get().removeAtMeGroup(tobeDeleteCons.conversationId());

}

try {

// delete conversation

EMClient.getInstance().chatManager().deleteConversation(tobeDeleteCons.conversationId(), deleteMessage);

InviteMessgeDao inviteMessgeDao = new InviteMessgeDao(getActivity());

inviteMessgeDao.deleteMessage(tobeDeleteCons.conversationId());

} catch (Exception e) {

e.printStackTrace();

}

refresh();

?

// update unread count

((MainActivity) getActivity()).updateUnreadLabel();

return true;

}

?

}

initView()

@Override

protected void initView() {

super.initView();

View errorView = (LinearLayout) View.inflate(getActivity(),R.layout.em_chat_neterror_item, null);

errorItemContainer.addView(errorView);

errorText = (TextView) errorView.findViewById(R.id.tv_connect_errormsg);

}

添加了錯(cuò)誤的容器、初始化錯(cuò)誤消息控件。

registerForContextMenu(conversationListView);

注冊(cè)上下文菜單

conversationListView.setOnItemClickListener(new OnItemClickListener() {

?

@Override

public void onItemClick(AdapterView parent, View view, int position, long id) {

EMConversation conversation = conversationListView.getItem(position);

String username = conversation.conversationId();

if (username.equals(EMClient.getInstance().getCurrentUser()))

Toast.makeText(getActivity(), R.string.Cant_chat_with_yourself, Toast.LENGTH_SHORT).show();

else {

// start chat acitivity

Intent intent = new Intent(getActivity(), ChatActivity.class);

if(conversation.isGroup()){

if(conversation.getType() == EMConversationType.ChatRoom){

// it's group chat

intent.putExtra(Constant.EXTRA_CHAT_TYPE, Constant.CHATTYPE_CHATROOM);

}else{

intent.putExtra(Constant.EXTRA_CHAT_TYPE, Constant.CHATTYPE_GROUP);

}

}

// it's single chat

intent.putExtra(Constant.EXTRA_USER_ID, username);

startActivity(intent);

}

}

});

條目的點(diǎn)擊監(jiān)聽(tīng)

其中做了這么些事情:

判斷用戶(hù)名是否等于當(dāng)前登陸用戶(hù),是則提示不能跟自己聊天

如果是群聊的話(huà),則繼續(xù)判斷是聊天室還是群組,并帶值給ChatActivity即聊天界面

最后將用戶(hù)名帶上,跳轉(zhuǎn)ChatActivity。

//red packet code : 紅包回執(zhí)消息在會(huì)話(huà)列表最后一條消息的展示

conversationListView.setConversationListHelper(new EaseConversationListHelper() {

@Override

public String onSetItemSecondaryText(EMMessage lastMessage) {

if (lastMessage.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_RED_PACKET_ACK_MESSAGE, false)) {

String sendNick = lastMessage.getStringAttribute(RPConstant.EXTRA_RED_PACKET_SENDER_NAME, "");

String receiveNick = lastMessage.getStringAttribute(RPConstant.EXTRA_RED_PACKET_RECEIVER_NAME, "");

String msg;

if (lastMessage.direct() == EMMessage.Direct.RECEIVE) {

msg = String.format(getResources().getString(R.string.msg_someone_take_red_packet), receiveNick);

} else {

if (sendNick.equals(receiveNick)) {

msg = getResources().getString(R.string.msg_take_red_packet);

} else {

msg = String.format(getResources().getString(R.string.msg_take_someone_red_packet), sendNick);

}

}

return msg;

} else if (lastMessage.getBooleanAttribute(RPConstant.MESSAGE_ATTR_IS_TRANSFER_PACKET_MESSAGE, false)) {

String transferAmount = lastMessage.getStringAttribute(RPConstant.EXTRA_TRANSFER_AMOUNT, "");

String msg;

if (lastMessage.direct() == EMMessage.Direct.RECEIVE) {

msg =? String.format(getResources().getString(R.string.msg_transfer_to_you), transferAmount);

} else {

msg =? String.format(getResources().getString(R.string.msg_transfer_from_you),transferAmount);

}

return msg;

}

return null;

}

});

super.setUpView();

最后是紅包回執(zhí)信息。

我們接著看其他的方法

@Override

protected void onConnectionDisconnected() {

super.onConnectionDisconnected();

if (NetUtils.hasNetwork(getActivity())){

errorText.setText(R.string.can_not_connect_chat_server_connection);

} else {

errorText.setText(R.string.the_current_network);

}

}

端口網(wǎng)絡(luò)則提示沒(méi)網(wǎng)標(biāo)簽。

@Override

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {

getActivity().getMenuInflater().inflate(R.menu.em_delete_message, menu);

}

創(chuàng)建上下文菜單

@Overridepublic boolean onContextItemSelected(MenuItem item) {? ? boolean deleteMessage = false;? ? if (item.getItemId() == R.id.delete_message) {? ? ? ? deleteMessage = true;? ? } else if (item.getItemId() == R.id.delete_conversation) {? ? ? ? deleteMessage = false;? ? }? EMConversation tobeDeleteCons = conversationListView.getItem(((AdapterContextMenuInfo) item.getMenuInfo()).position);? if (tobeDeleteCons == null) {? ? ? return true;? }? ? if(tobeDeleteCons.getType() == EMConversationType.GroupChat){? ? ? ? EaseAtMessageHelper.get().removeAtMeGroup(tobeDeleteCons.conversationId());? ? }? ? try {? ? ? ? // delete conversation? ? ? ? EMClient.getInstance().chatManager().deleteConversation(tobeDeleteCons.conversationId(), deleteMessage);? ? ? ? InviteMessgeDao inviteMessgeDao = new InviteMessgeDao(getActivity());? ? ? ? inviteMessgeDao.deleteMessage(tobeDeleteCons.conversationId());? ? } catch (Exception e) {? ? ? ? e.printStackTrace();? ? }? ? refresh();?? ? // update unread count[url=http://www.imgeek.org/article/825308690]環(huán)信官方Demo源碼分析及SDK簡(jiǎn)單應(yīng)用-主界面的三個(gè)fragment-通訊錄界面[/url]? ? ((MainActivity) getActivity()).updateUnreadLabel();? ? return true;}

上下文菜單選擇的處理方法

刪除消息并更新未讀消息。

好,至此,第一個(gè)界面,會(huì)話(huà)界面到此結(jié)束。

我們?cè)賮?lái)看通訊錄界面。

環(huán)信官方Demo源碼分析及SDK簡(jiǎn)單應(yīng)用-主界面的三個(gè)fragment-通訊錄界面

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容