最近在做使用网易云信仿微信项目,在获取最近联系人未读消息总数后需要刷新底部提示数字,因为底部提示数字的控件在Activity中,获取未读消息数的操作是在Fragment中(Fragment+ViewPager),在得到总未读消息数后需要更新activity中的控件显示信息,所以用到了getActivity(),但是得到NullPointException,通过debug得到getActivity()得到的是null。但是我在其他方法中又可以得到,经排查只要是在网易云信的静态方法回调中使用getActivity()就会得到null。
/**
* 监听最近联系人
*/
private void observeRecentContact() {
mMessageObserver = new Observer<List<RecentContact>>() {
@Override
public void onEvent(List<RecentContact> recentContacts) {
if (recentContacts != null && recentContacts.size() > 0) {
if (mAdapter != null)
mAdapter.setData(recentContacts);
updateTotalUnReadCount();//这里调用的方法中调用getActivity()
}
}
};
NimRecentContactSDK.observeRecentContact(mMessageObserver, true);
}
/**
* 更新未读总数
*/
private void updateTotalUnReadCount() {
int totalUnreadCount = NimRecentContactSDK.getTotalUnreadCount();
activity = (MainActivity) getActivity();//得到null
if (totalUnreadCount > 0) {
activity.mTvMessageCount.setVisibility(View.VISIBLE);
activity.mTvMessageCount.setText(String.valueOf(totalUnreadCount));
} else {
activity.mTvMessageCount.setVisibility(View.GONE);
}
}
通过观察代码,我猜测网易云信的接口回调应该是在别的进程中运行的,而理论上getActivity()应该得到的是主线程的activity,但是代码中是在网易云信的回调中调用,也就是在别的进程中调用,故得不到activity。又因为getActivity()必须在生命周期onAttach与onDetach之间调用才有效,所以解决的办法在onAttach中将上下文进行保存,如下:
MainActivity activity;
@Override
public void onAttach(Context context) {
super.onAttach(context);
activity = (MainActivity) context;//保存Context引用
}
这下问题解决了:
/**
* 更新未读总数
*/
private void updateTotalUnReadCount() {
int totalUnreadCount = NimRecentContactSDK.getTotalUnreadCount();
//activity = (MainActivity) getActivity();//activity在onAttach中保存了
if (totalUnreadCount > 0) {
activity.mTvMessageCount.setVisibility(View.VISIBLE);
activity.mTvMessageCount.setText(String.valueOf(totalUnreadCount));
} else {
activity.mTvMessageCount.setVisibility(View.GONE);
}
}
总结:当遇到getActivity()为null,或getContext()时,先冷静想想以下3点:
1. 是不是放在了第三方的回调中
2. 是不是在其他进程中调用了(其实第一点就是在其他进程中调用了)
3. 是不是调用时不在指定生命周期范围内(onAttach与onDetach之间)
一般不是上述情况就不会得到null啦,如有不足,欢迎提出,谢谢。