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 UIEventSource::removeCallbacks(const Runnable& what){
int count=0; int count=0;
for(auto it = mRunnables.begin();it != mRunnables.end();it++){ for(auto it = mRunnables.begin();it != mRunnables.end();){
if(it->run == what){ if(it->run == what){
it = mRunnables.erase(it); it = mRunnables.erase(it);
count++; count++;
} }else it++;
} }
return count; 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){ void DefaultItemAnimator::onMoveAnimationStart(RecyclerView::ViewHolder*holder,Animator& animator,bool isReverse){
dispatchMoveStarting(*holder); 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) { if (deltaX != 0) {
holder->itemView->setTranslationX(0); holder->itemView->setTranslationX(0);
} }
@ -223,7 +224,7 @@ void DefaultItemAnimator::onMoveAnimationEnd(RecyclerView::ViewHolder*holder,Ani
ViewPropertyAnimator& animation = holder->itemView->animate(); ViewPropertyAnimator& animation = holder->itemView->animate();
animation.setListener({}); animation.setListener({});
dispatchMoveFinished(*holder); 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); mMoveAnimations.erase(it);//mMoveAnimations.remove(holder);
dispatchFinishedWhenDone(); dispatchFinishedWhenDone();
} }
@ -246,7 +247,7 @@ void DefaultItemAnimator::animateMoveImpl(RecyclerView::ViewHolder& holder, int
Animator::AnimatorListener al; Animator::AnimatorListener al;
al.onAnimationStart = std::bind(&DefaultItemAnimator::onMoveAnimationStart,this,&holder,std::placeholders::_1,std::placeholders::_2); 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); al.onAnimationEnd = std::bind(&DefaultItemAnimator::onMoveAnimationEnd,this,&holder,std::placeholders::_1,std::placeholders::_2);
animation.setDuration(getMoveDuration()).setListener(al).start(); animation.setDuration(getMoveDuration()).setListener(al).start();
} }

View File

@ -49,7 +49,7 @@ protected:
void onRemoveAnimationStart(RecyclerView::ViewHolder*,Animator& animator,bool isReverse); void onRemoveAnimationStart(RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
void onRemoveAnimationEnd(RecyclerView::ViewHolder*,Animator& animator,bool isReverse); void onRemoveAnimationEnd(RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
void onMoveAnimationStart(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 onMoveAnimationEnd(RecyclerView::ViewHolder*,Animator& animator,bool isReverse);
void onChangeAnimationStart(bool,ChangeInfo*,Animator& animator,bool isReverse); void onChangeAnimationStart(bool,ChangeInfo*,Animator& animator,bool isReverse);
void onChangeAnimationEnd(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{ class MyRecoverAnimation:public ItemTouchHelper::RecoverAnimation{
private: private:
std::function<void(Animator&,bool)>mOnAnimationEndListener; std::function<void(Animator&,bool)>mOnAnimationEndListener;
public:
Runnable mRunnable;
public: public:
MyRecoverAnimation(RecyclerView::ViewHolder* viewHolder, int animationType, MyRecoverAnimation(RecyclerView::ViewHolder* viewHolder, int animationType,
int actionState, float startDx, float startDy, float targetX, float targetY) 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) { void ItemTouchHelper::postDispatchSwipe(RecoverAnimation* anim,int swipeDir) {
// wait until animations are complete. // 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 if (mRecyclerView && mRecyclerView->isAttachedToWindow() && !anim->mOverridden
&& (anim->mViewHolder->getAdapterPosition() != RecyclerView::NO_POSITION) ) { && (anim->mViewHolder->getAdapterPosition() != RecyclerView::NO_POSITION) ) {
RecyclerView::ItemAnimator* animator = mRecyclerView->getItemAnimator(); RecyclerView::ItemAnimator* animator = mRecyclerView->getItemAnimator();
@ -377,11 +380,11 @@ void ItemTouchHelper::postDispatchSwipe(RecoverAnimation* anim,int swipeDir) {
&& !hasRunningRecoverAnim()) { && !hasRunningRecoverAnim()) {
mCallback->onSwiped(*anim->mViewHolder, swipeDir); mCallback->onSwiped(*anim->mViewHolder, swipeDir);
} else { } else {
mRecyclerView->post(r); mRecyclerView->post(((MyRecoverAnimation*)anim)->mRunnable);
} }
} }
}); });
mRecyclerView->post(r); mRecyclerView->post(myAnim->mRunnable);
} }
bool ItemTouchHelper::hasRunningRecoverAnim() { bool ItemTouchHelper::hasRunningRecoverAnim() {