fix itemtouchhelper's crash

This commit is contained in:
侯歌 2024-07-06 22:33:48 +08:00
parent 5214d47d8d
commit d0fa48c6e8
4 changed files with 13 additions and 9 deletions

View File

@ -92,11 +92,11 @@ bool UIEventSource::hasDelayedRunners()const{
int UIEventSource::removeCallbacks(const Runnable& what){
int count=0;
for(auto it = mRunnables.begin();it != mRunnables.end();it++){
for(auto it = mRunnables.begin();it != mRunnables.end();){
if(it->run == what){
it = mRunnables.erase(it);
count++;
}
}else it++;
}
return count;
}

View File

@ -211,7 +211,8 @@ bool DefaultItemAnimator::animateMove(RecyclerView::ViewHolder& holder, int from
void DefaultItemAnimator::onMoveAnimationStart(RecyclerView::ViewHolder*holder,Animator& animator,bool isReverse){
dispatchMoveStarting(*holder);
}
void DefaultItemAnimator::onMoveAnimationCancel(int deltaX,int deltaY,RecyclerView::ViewHolder*holder,Animator& animator,bool isReverse){
void DefaultItemAnimator::onMoveAnimationCancel(int deltaX,int deltaY,RecyclerView::ViewHolder*holder,Animator& animator){
if (deltaX != 0) {
holder->itemView->setTranslationX(0);
}
@ -223,7 +224,7 @@ void DefaultItemAnimator::onMoveAnimationEnd(RecyclerView::ViewHolder*holder,Ani
ViewPropertyAnimator& animation = holder->itemView->animate();
animation.setListener({});
dispatchMoveFinished(*holder);
auto it =std::find(mMoveAnimations.begin(),mMoveAnimations.end(),holder);
auto it = std::find(mMoveAnimations.begin(),mMoveAnimations.end(),holder);
mMoveAnimations.erase(it);//mMoveAnimations.remove(holder);
dispatchFinishedWhenDone();
}
@ -246,7 +247,7 @@ void DefaultItemAnimator::animateMoveImpl(RecyclerView::ViewHolder& holder, int
Animator::AnimatorListener al;
al.onAnimationStart = std::bind(&DefaultItemAnimator::onMoveAnimationStart,this,&holder,std::placeholders::_1,std::placeholders::_2);
//al.onAnimationCancel = std::bind(&DefaultItemAnimator::onMoveAnimationCancel,this,deltaX,deltaY,&holder,std::placeholders::_1,std::placeholders::_2);
al.onAnimationCancel = std::bind(&DefaultItemAnimator::onMoveAnimationCancel,this,deltaX,deltaY,&holder,std::placeholders::_1);
al.onAnimationEnd = std::bind(&DefaultItemAnimator::onMoveAnimationEnd,this,&holder,std::placeholders::_1,std::placeholders::_2);
animation.setDuration(getMoveDuration()).setListener(al).start();
}

View File

@ -49,7 +49,7 @@ protected:
void onRemoveAnimationStart(RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
void onRemoveAnimationEnd(RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
void onMoveAnimationStart(RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
void onMoveAnimationCancel(int deltaX,int deltaY,RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
void onMoveAnimationCancel(int deltaX,int deltaY,RecyclerView::ViewHolder*,Animator& animator);
void onMoveAnimationEnd(RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
void onChangeAnimationStart(bool,ChangeInfo*,Animator& animator,bool isReverse);
void onChangeAnimationEnd(bool,ChangeInfo*,Animator& animator,bool isReverse);

View File

@ -236,6 +236,8 @@ template <typename T>static int signum(T val) {
class MyRecoverAnimation:public ItemTouchHelper::RecoverAnimation{
private:
std::function<void(Animator&,bool)>mOnAnimationEndListener;
public:
Runnable mRunnable;
public:
MyRecoverAnimation(RecyclerView::ViewHolder* viewHolder, int animationType,
int actionState, float startDx, float startDy, float targetX, float targetY)
@ -366,7 +368,8 @@ void ItemTouchHelper::select(RecyclerView::ViewHolder* selected, int actionState
void ItemTouchHelper::postDispatchSwipe(RecoverAnimation* anim,int swipeDir) {
// wait until animations are complete.
Runnable r([this,anim,&r,swipeDir]() {
MyRecoverAnimation*myAnim = (MyRecoverAnimation*)anim;
myAnim->mRunnable = ([this,anim,swipeDir]() {
if (mRecyclerView && mRecyclerView->isAttachedToWindow() && !anim->mOverridden
&& (anim->mViewHolder->getAdapterPosition() != RecyclerView::NO_POSITION) ) {
RecyclerView::ItemAnimator* animator = mRecyclerView->getItemAnimator();
@ -377,11 +380,11 @@ void ItemTouchHelper::postDispatchSwipe(RecoverAnimation* anim,int swipeDir) {
&& !hasRunningRecoverAnim()) {
mCallback->onSwiped(*anim->mViewHolder, swipeDir);
} else {
mRecyclerView->post(r);
mRecyclerView->post(((MyRecoverAnimation*)anim)->mRunnable);
}
}
});
mRecyclerView->post(r);
mRecyclerView->post(myAnim->mRunnable);
}
bool ItemTouchHelper::hasRunningRecoverAnim() {