这周在做公司的一个需求时,发现了Handler
的一个坑,记录之。
需求是做一个活动,需要在首页添加悬浮球,下滑时悬浮球隐藏一半,上滑时,全部显示。如果来回上下滑动,则当滑动停止1s后,根据最后的滑动方向来判断悬浮球是否全部显示。
我的想法是使用Handler
延时1s发送个Message
,关键代码如下:
private void handleScroll(int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
mHandler.removeMessages(MSG_SCROLL_STATE_IDLE);
mHandler.sendEmptyMessageDelayed(MSG_SCROLL_STATE_IDLE, 1000);
} else if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
mHandler.removeMessages(MSG_SCROLL_STATE_IDLE);
}
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_SCROLL_STATE_IDLE:
switch (mScrollState) {
case DOWN:
showFullEntrance(true);
break;
case UP:
showFullEntrance(false);
break;
}
break;
}
}
};
private void showFullEntrance(boolean showFullEntrance) {
if (mHomeData == null || mHomeData.floatView == null) {
return;
}
float translationX;
if (showFullEntrance) {
translationX = DisplayUtil.dip2px(getContext(), 0);
} else {
translationX = DisplayUtil.dip2px(getContext(), 50);
}
this.mShowFullEntrance = showFullEntrance;
ObjectAnimator translationXAnimator = ObjectAnimator.ofFloat(mEntranceIv, "translationX", translationX);
translationXAnimator.setDuration(200);
translationXAnimator.start();
}
大眼一看,好像也没什么问题。
但当我们快速滑动之后,然后立马切换到MainActivity
的其他Fragment
页面,那么首页对应的HomeFragment
有可能被销毁,然后getContext()
返回为null
,再然后就崩溃了,,,
同理,当我们自己写了个线程,如果没有在合适的地方终止,而线程内部又有setText()
、getContext()
等操作,则很容易造成空指针异常。
解决方案有二:
- 对控件进行非空判断或者使用
ApplicationContext
替代getContext()
- 在
onDestroy()
中终止:mHandler.removeCallbacksAndMessages(null);
以上。