Android进阶之解决RecyclerView notifyItem闪屏问题

1 RecyclerView刷新方法

1.1操作内容

ListView的getView方法的渲染数据部分的代码相当于onBindViewHolder(),如果调用adapter.notifyDataSetChanged()方法,会重新调用onBindViewHolder()方法。

1.2其他刷新方法

除了adapter.notifyDataSetChanged()这个方法之外,新的Adapter还提供了其他的方法,如下:

//刷新所有
public final void notifyDataSetChanged();
//position数据发生了改变,那调用这个方法,就会回调对应position的onBindViewHolder()方法了
public final void notifyItemChanged(int position);
//刷新从positionStart开始itemCount数量的item了(这里的刷新指回调onBindViewHolder()方法)
public final void notifyItemRangeChanged(int positionStart, int itemCount);
//在第position位置被插入了一条数据的时候可以使用这个方法刷新,注意这个方法调用后会有插入的动画,这个动画可以使用默认的,也可以自己定义
public final void notifyItemInserted(int position);
//从fromPosition移动到toPosition为止的时候可以使用这个方法刷新
public final void notifyItemMoved(int fromPosition, int toPosition);
//批量添加
public final void notifyItemRangeInserted(int positionStart, int itemCount);
//第position个被删除的时候刷新,同样会有动画
public final void notifyItemRemoved(int position);
//批量删除
public final void notifyItemRangeRemoved(int positionStart, int itemCount);

2 闪屏问题

2.1 问题描述

RecyclerView做了一个notifyItemChanged()的操作,功能都顺利实现,问题当前Item闪烁,QA甚至为此提了Bug。

2.2 问题原因

闪烁主要由于RecyclerView使用的默认的动画导致的,所以解决的方法就是修改默认的动画。

2.3 问题解决

2.3.1 更新部分item

(1)个别更新

imgAdapter.notifyItemChanged(i);// 只更新修改的item

(2)删除某个

selectedImgs.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(0,selectedImgs.size());

2.3.2 屏蔽动画方法

DefaultItemAnimator继承自SimpleItemAnimator,里面有个方法是:

    /**
     * Sets whether this ItemAnimator supports animations of item change events.
     * If you set this property to false, actions on the data set which change the
     * contents of items will not be animated. What those animations do is left
     * up to the discretion of the ItemAnimator subclass, in its
     * {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)} implementation.
     * The value of this property is true by default.
     *
     */
    public void setSupportsChangeAnimations(boolean supportsChangeAnimations) {
        mSupportsChangeAnimations = supportsChangeAnimations;
    }

只要设置为false,就可以不显示动画了,也就解决了闪烁问题。 关键代码:

((SimpleItemAnimator)recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);

2.3.3 设置动画执行时间为0来解决闪烁问题

recyclerView.getItemAnimator().setChangeDuration(0);// 通过设置动画执行时间为0来解决闪烁问题

2.3.4 修改默认的动画方法

//1.定义动画类
public class NoAlphaItemAnimator extends SimpleItemAnimator {
   
   

}
//2.将DefaultItemAnimator类里的代码全部copy到自己写的动画类中,然后做一些修改。

//3.首先找到private void animateChangeImpl(final ChangeInfo changeInfo) {}方法。

//4.找到方法里这两句代码:
4.1 去掉alpha(0)
oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() {
  
  ...}).start();
oldViewAnim.setListener(new VpaListenerAdapter() {
  
  ...}).start();

4.2 去掉alpha(1)
newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).
                    alpha(1).setListener(new VpaListenerAdapter() {
  
  ...}).start();
newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).
                    setListener(new VpaListenerAdapter() {
  
  ...}).start();

//5.最后使用修改后的动画
recyclerView.setItemAnimator(new NoAlphaItemAnimator());

例子如:

package com.example.splash.pictureselecters.view;

import android.support.annotation.NonNull;
import android.support.v4.animation.AnimatorCompatHelper;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorCompat;
import android.support.v4.view.ViewPropertyAnimatorListener;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SimpleItemAnimator;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by chenliguan on 2017/5/3 0003.
 */
public class NoAlphaItemAnimator extends SimpleItemAnimator {
   
   

    private static final boolean DEBUG = false;

    private ArrayList<RecyclerView.ViewHolder> mPendingRemovals = new ArrayList<>();
    private ArrayList<RecyclerView.ViewHolder> mPendingAdditions = new ArrayList<>();
    private ArrayList<NoAlphaItemAnimator.MoveInfo> mPendingMoves = new ArrayList<>();
    private ArrayList<NoAlphaItemAnimator.ChangeInfo> mPendingChanges = new ArrayList<>();

    ArrayList<ArrayList<RecyclerView.ViewHolder>> mAdditionsList = new ArrayList<>();
    ArrayList<ArrayList<NoAlphaItemAnimator.MoveInfo>> mMovesList = new ArrayList<>();
    ArrayList<ArrayList<NoAlphaItemAnimator.ChangeInfo>> mChangesList = new ArrayList<>();

    ArrayList<RecyclerView.ViewHolder> mAddAnimations = new ArrayList<>();
    ArrayList<RecyclerView.ViewHolder> mMoveAnimation
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值