package com.netease.nim.uikit.cache;
import android.text.TextUtils;
import android.util.Log;
import com.netease.nim.uikit.NimUIKit;
import com.netease.nim.uikit.UIKitLogTag;
import com.netease.nim.uikit.common.util.log.LogUtil;
import com.netease.nimlib.sdk.NIMClient;
import com.netease.nimlib.sdk.Observer;
import com.netease.nimlib.sdk.RequestCallback;
import com.netease.nimlib.sdk.RequestCallbackWrapper;
import com.netease.nimlib.sdk.ResponseCode;
import com.netease.nimlib.sdk.friend.model.Friend;
import com.netease.nimlib.sdk.uinfo.UserService;
import com.netease.nimlib.sdk.uinfo.UserServiceObserve;
import com.netease.nimlib.sdk.uinfo.model.NimUserInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 用户资料数据缓存,适用于用户体系使用网易云信用户资料托管
* 注册缓存变更通知,请使用UserInfoHelper的registerObserver方法
* Created by huangjun on 2015/8/20.
*/
public class NimUserInfoCache {
public static NimUserInfoCache getInstance() {
return InstanceHolder.instance;
}
private Map<String, NimUserInfo> account2UserMap = new ConcurrentHashMap<>();
private Map<String, List<RequestCallback<NimUserInfo>>> requestUserInfoMap = new ConcurrentHashMap<>(); // 重复请求处理
/**
* 构建缓存与清理
*/
public void buildCache() {
List<NimUserInfo> users = NIMClient.getService(UserService.class).getAllUserInfo();
addOrUpdateUsers(users, false);
LogUtil.i(UIKitLogTag.USER_CACHE, "build NimUserInfoCache completed, users count = " + account2UserMap.size());
}
public void clear() {
clearUserCache();
}
/**
* 从云信服务器获取用户信息(重复请求处理)[异步]
*/
public void getUserInfoFromRemote(final String account, final RequestCallback<NimUserInfo> callback) {
if (TextUtils.isEmpty(account)) {
return;
}
if (requestUserInfoMap.containsKey(account)) {
if (callback != null) {
requestUserInfoMap.get(account).add(callback);
}
return; // 已经在请求中,不要重复请求
} else {
List<RequestCallback<NimUserInfo>> cbs = new ArrayList<>();
if (callback != null) {
cbs.add(callback);
}
requestUserInfoMap.put(account, cbs);
}
List<String> accounts = new ArrayList<>(1);
accounts.add(account);
NIMClient.getService(UserService.class).fetchUserInfo(accounts).setCallback(new RequestCallbackWrapper<List<NimUserInfo>>() {
@Override
public void onResult(int code, List<NimUserInfo> users, Throwable exception) {
if (exception != null) {
callback.onException(exception);
return;
}
NimUserInfo user = null;
boolean hasCallback = requestUserInfoMap.get(account).size() > 0;
if (code == ResponseCode.RES_SUCCESS && users != null && !users.isEmpty()) {
user = users.get(0);
// 这里不需要更新缓存,由监听用户资料变更(添加)来更新缓存
}
// 处理回调
if (hasCallback) {
List<RequestCallback<NimUserInfo>> cbs = requestUserInfoMap.get(account);
for (RequestCallback<NimUserInfo> cb : cbs) {
if (code == ResponseCode.RES_SUCCESS) {
cb.onSuccess(user);
} else {
cb.onFailed(code);
}
}
}
requestUserInfoMap.remove(account);
}
});
}
/**
* 从云信服务器获取批量用户信息[异步]
*/
public void getUserInfoFromRemote(List<String> accounts, final RequestCallback<List<NimUserInfo>> callback) {
NIMClient.getService(UserService.class).fetchUserInfo(accounts).setCallback(new RequestCallback<List<NimUserInfo>>() {
@Override
public void onSuccess(List<NimUserInfo> users) {
Log.i(UIKitLogTag.USER_CACHE, "fetch userInfo completed, add users size =" + users.size());
// 这里不需要更新缓存,由监听用户资料变更(添加)来更新缓存
if (callback != null) {
callback.onSuccess(users);
}
}
@Override
public void onFailed(int code) {
if (callback != null) {
callback.onFailed(code);
}
}
@Override
public void onException(Throwable exception) {
if (callback != null) {
callback.onException(exception);
}
}
});
}
/**
* ******************************* 业务接口(获取缓存的用户信息) *********************************
*/
public List<NimUserInfo> getAllUsersOfMyFriend() {
List<String> accounts = FriendDataCache.getInstance().getMyFriendAccounts();
List<NimUserInfo> users = new ArrayList<>();
List<String> unknownAccounts = new ArrayList<>();
for (String account : accounts) {
if (hasUser(account)) {
users.add(getUserInfo(account));
} else {
unknownAccounts.add(account);
}
}
// fetch unknown userInfo,根本不会发生,再次仅作测试校验,可以删去
if (!unknownAccounts.isEmpty()) {
DataCacheManager.Log(unknownAccounts, "lack friend userInfo", UIKitLogTag.USER_CACHE);
getUserInfoFromRemote(unknownAccounts, null);
}
return users;
}
public NimUserInfo getUserInfo(String account) {
if (TextUtils.isEmpty(account) || account2UserMap == null) {
LogUtil.e(UIKitLogTag.USER_CACHE, "getUserInfo null, account=" + account + ", account2UserMap=" + account2UserMap);
return null;
}
return account2UserMap.get(account);
}
public boolean hasUser(String account) {
if (TextUtils.isEmpty(account) || account2UserMap == null) {
LogUtil.e(UIKitLogTag.USER_CACHE, "hasUser null, account=" + account + ", account2UserMap=" + account2UserMap);
return false;
}
return account2UserMap.containsKey(account);
}
/**
* 获取用户显示名称。
* 若设置了备注名,则显示备注名。
* 若没有设置备注名,用户有昵称则显示昵称,用户没有昵称则显示帐号。
*
* @param account 用户帐号
* @return
*/
public String getUserDisplayName(String account) {
String alias = getAlias(account);
if (!TextUtils.isEmpty(alias)) {
return alias;
}
return getUserName(account);
}
public String getAlias(String account) {
Friend friend = FriendDataCache.getInstance().getFriendByAccount(account);
if (friend != null && !TextUtils.isEmpty(friend.getAlias())) {
return friend.getAlias();
}
return null;
}
// 获取用户原本的昵称
public String getUserName(String account) {
NimUserInfo userInfo = getUserInfo(account);
if (userInfo != null && !TextUtils.isEmpty(userInfo.getName())) {
return userInfo.getName();
} else {
return account;
}
}
public String getUserDisplayNameEx(String account) {
if (account.equals(NimUIKit.getAccount())) {
return "我";
}
return getUserDisplayName(account);
}
public String getUserDisplayNameYou(String account) {
if (account.equals(NimUIKit.getAccount())) {
return "你"; // 若为用户自己,显示“你”
}
return getUserDisplayName(account);
}
private void clearUserCache() {
account2UserMap.clear();
}
/**
* ************************************ 用户资料变更监听(监听SDK) *****************************************
*/
/**
* 在Application的onCreate中向SDK注册用户资料变更观察者
*/
public void registerObservers(boolean register) {
NIMClient.getService(UserServiceObserve.class).observeUserInfoUpdate(userInfoUpdateObserver, register);
}
private Observer<List<NimUserInfo>> userInfoUpdateObserver = new Observer<List<NimUserInfo>>() {
@Override
public void onEvent(List<NimUserInfo> users) {
if (users == null || users.isEmpty()) {
return;
}
addOrUpdateUsers(users, true);
}
};
/**
* *************************************** User缓存管理与变更通知 ********************************************
*/
private void addOrUpdateUsers(final List<NimUserInfo> users, boolean notify) {
if (users == null || users.isEmpty()) {
return;
}
// update cache
for (NimUserInfo u : users) {
account2UserMap.put(u.getAccount(), u);
}
// log
List<String> accounts = getAccounts(users);
DataCacheManager.Log(accounts, "on userInfo changed", UIKitLogTag.USER_CACHE);
// 通知变更
if (notify && accounts != null && !accounts.isEmpty()) {
NimUIKit.notifyUserInfoChanged(accounts); // 通知到UI组件
}
}
private List<String> getAccounts(List<NimUserInfo> users) {
if (users == null || users.isEmpty()) {
return null;
}
List<String> accounts = new ArrayList<>(users.size());
for (NimUserInfo user : users) {
accounts.add(user.getAccount());
}
return accounts;
}
/**
* ************************************ 单例 **********************************************
*/
static class InstanceHolder {
final static NimUserInfoCache instance = new NimUserInfoCache();
}
}