注册

环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-会话界面

环信官方Demo源码分析及SDK简单应用

环信官方Demo源码分析及SDK简单应用-ChatDemoUI3.0

环信官方Demo源码分析及SDK简单应用-LoginActivity
 
环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-会话界面
 
环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-通讯录界面
 
环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-设置界面
 
环信官方Demo源码分析及SDK简单应用-EaseUI
 
环信官方Demo源码分析及SDK简单应用-IM集成开发详案及具体代码实现
 
现在来看具体的主界面的三个Fragment
主界面的三个fragment
会话界面


​ 我们来看会话界面的代码
 
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 : 红包回执消息在会话列表最后一条消息的展示
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;
}

}
我们还是挨个来读代码
public class ConversationListFragment extends EaseConversationListFragment
来,我们还是得先去找他爹算账。
public class EaseConversationListFragment extends EaseBaseFragment
哎呀,我们再去找他爷爷。
 public abstract class EaseBaseFragment extends Fragment
爷爷终于正常点是从Android系统类继承下来的了,我们看具体的代码

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();


}
我们还是挨个来看代码,研究他的功能。
@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要干嘛啊,隐藏键盘。果不其然。
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);
}
}
然后呢?

初始化标题头​
 //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);
}
}
好了,爷爷的帐算完了,我们来找他儿子。

EaseConversationListFragment

我们来看代码
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<EMConversation> conversationList = new ArrayList<EMConversation>();
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<EMConversation> loadConversationList(){
// get all conversations
Map<String, EMConversation> conversations = EMClient.getInstance().chatManager().getAllConversations();
List<Pair<Long, EMConversation>> sortList = new ArrayList<Pair<Long, EMConversation>>();
/**
* 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<Long, EMConversation>(conversation.getLastMessage().getMsgTime(), conversation));
}
}
}
try {
// Internal is TimSort algorithm, has bug
sortConversationByLastChatTime(sortList);
} catch (Exception e) {
e.printStackTrace();
}
List<EMConversation> list = new ArrayList<EMConversation>();
for (Pair<Long, EMConversation> sortItem : sortList) {
list.add(sortItem.second);
}
return list;
}

/**
* sort conversations according time stamp of last message
*
* @param conversationList
*/
private void sortConversationByLastChatTime(List<Pair<Long, EMConversation>> conversationList) {
Collections.sort(conversationList, new Comparator<Pair<Long, EMConversation>>() {
@Override
public int compare(final Pair<Long, EMConversation> con1, final Pair<Long, EMConversation> 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);
继续看代码
 
@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);
}
initView()

覆写爷爷的家规,初始化View输入法管理器
  • 会话列表List
  • 查找联系人的输入框
  • 清除搜索的按钮
  • errorItemContainer 错误标签容器
继续看代码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);
会话列表添加全部以及数据填充初始化。我们来看具体的方法
 /** * load conversation list *  * @return */protected List<EMConversation> loadConversationList(){    // get all conversations    Map<String, EMConversation> conversations = EMClient.getInstance().chatManager().getAllConversations();    List<Pair<Long, EMConversation>> sortList = new ArrayList<Pair<Long, EMConversation>>();    /**     * 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<Long, EMConversation>(conversation.getLastMessage().getMsgTime(), conversation));            }        }    }    try {        // Internal is TimSort algorithm, has bug        sortConversationByLastChatTime(sortList);    } catch (Exception e) {        e.printStackTrace();    }    List<EMConversation> list = new ArrayList<EMConversation>();    for (Pair<Long, EMConversation> sortItem : sortList) {        list.add(sortItem.second);    }    return list;}
loadConversationList()返回一个EMConversation对象List。
 // get all conversationsMap<String, EMConversation> conversations = EMClient.getInstance().chatManager().getAllConversations();List<Pair<Long, EMConversation>> sortList = new ArrayList<Pair<Long, EMConversation>>();
通过封装的chatManager拿到所有的会话列表
/** * 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<Long, EMConversation>(conversation.getLastMessage().getMsgTime(), conversation));        }    }}
lastMsgTime会随着新消息的到来排序发生改变,所以我们用同步方法确保最新消息的时间戳不发生改变。英文不好,大致是这么个意思。
 try {            // Internal is TimSort algorithm, has bug            sortConversationByLastChatTime(sortList);        } catch (Exception e) {            e.printStackTrace();        }        List<EMConversation> list = new ArrayList<EMConversation>();        for (Pair<Long, EMConversation> sortItem : sortList) {            list.add(sortItem.second);        }        return list;
其中还特地注释了一把,算法有点bug。
  /**     * sort conversations according time stamp of last message     *      * @param conversationList     */    private void sortConversationByLastChatTime(List<Pair<Long, EMConversation>> conversationList) {        Collections.sort(conversationList, new Comparator<Pair<Long, EMConversation>>() {            @Override            public int compare(final Pair<Long, EMConversation> con1, final Pair<Long, EMConversation> con2) {​                if (con1.first.equals(con2.first)) {                    return 0;                } else if (con2.first.longValue() > con1.first.longValue()) {                    return 1;                } else {                    return -1;                }            }​        });
根据最新的会话时间戳来排序。我们接着看
 List<EMConversation> list = new ArrayList<EMConversation>();for (Pair<Long, EMConversation> 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);        }    });}
然后便是连接接听
  EMClient.getInstance().addConnectionListener(connectionListener);
添加了一个连接的监听。
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);    }};
在断开连接时判断用户是否移除,是否在其他设备登陆,或者服务端的服务受到限制,是的话则标记冲突。不是则发送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;        }    }};
干嘛啊?调用 onConnectionDisconnected 即连接断开的处理方法
 /** * disconnected with server */protected void onConnectionDisconnected(){    errorItemContainer.setVisibility(View.VISIBLE);}
即显示错误条。我们再接着看代码
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;    }});
干了些什么啊?查询、清除搜索、会话列表点击监听。其他方法​
 /** * connected to server */protected void onConnectionConnected(){    errorItemContainer.setVisibility(View.GONE);}
连接后将错误条隐藏
case MSG_REFRESH: {   conversationList.clear();     conversationList.addAll(loadConversationList());     conversationListView.refresh();     break; }
服务器告诉要刷新了,那么我们就去清楚列表,然后去服务器拿并排序,然后刷新listview。其中该listview为自定义的EaseConversationList。那么儿子齐活了,我们再看孙子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 : 红包回执消息在会话列表最后一条消息的展示        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()
 @Overrideprotected 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);}
添加了错误的容器、初始化错误消息控件。
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);        }    }});
条目的点击监听其中做了这么些事情:
  • 判断用户名是否等于当前登陆用户,是则提示不能跟自己聊天
  • 如果是群聊的话,则继续判断是聊天室还是群组,并带值给ChatActivity即聊天界面
  • 最后将用户名带上,跳转ChatActivity。

//red packet code : 红包回执消息在会话列表最后一条消息的展示
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();
最后是红包回执信息。

我们接着看其他的方法
 
@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[url=http://www.imgeek.org/article/825308690]环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-通讯录界面[/url]
((MainActivity) getActivity()).updateUnreadLabel();
return true;
}
上下文菜单选择的处理方法

删除消息并更新未读消息。

好,至此,第一个界面,会话界面到此结束。

我们再来看通讯录界面。
 
环信官方Demo源码分析及SDK简单应用-主界面的三个fragment-通讯录界面

0 个评论

要回复文章请先登录注册