recycler view reset items - android

时间:2016-07-15 17:25:31

标签: android android-recyclerview adapter countdowntimer android-viewholder

我已经在应用程序上工作了很长时间。这个应用程序应该采用姓氏并测量访问时间,这是恒定的(30分钟)。我有一个Family对象,其中包含名称,成员数和访问结束等信息,表示为未来的毫秒值。

我实现定时器部分的方法只是创建一个名为CountDownManager的类,它负责更新和计算列出的所有系列视图持有者的剩余时间。

问题是,如果我清理我的数据(持有者和数据集)并添加一个新系列,则该系列不会添加到CountDownTimer类中。

以下是正确添加家庭时的图像:

As you can see, the timer on the left is working fine

这是我清理数据并尝试添加新系列后的图像: As you can see, the left side is not shown at all

以下是我的适配器,我的视图持有者和我的CoundDownManager类的代码:

package bikurim.silverfix.com.bikurim.adapters;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filterable;
import android.widget.Toast;

import java.util.ArrayList;

import bikurim.silverfix.com.bikurim.Constants;
import bikurim.silverfix.com.bikurim.adapters.holders.FamilyViewHolder;
import bikurim.silverfix.com.bikurim.adapters.holders.GenericViewHolder;
import bikurim.silverfix.com.bikurim.adapters.holders.TimeUpViewHolder;
import bikurim.silverfix.com.bikurim.models.Family;
import bikurim.silverfix.com.bikurim.R;
import bikurim.silverfix.com.bikurim.utils.managers.MediaPlayerManager;
import bikurim.silverfix.com.bikurim.utils.Utils;
import bikurim.silverfix.com.bikurim.utils.interfaces.HolderListener;
import bikurim.silverfix.com.bikurim.utils.managers.CountDownManager;
import bikurim.silverfix.com.bikurim.utils.interfaces.EventListener;

public class FamiliesAdapter extends GenericAdapter implements Filterable, EventListener, HolderListener {

    // last position holds the last position of the element that was added, for animation purposes
    private static int lastPosition = -1;

    private int[] viewTypes;

    private ItemTouchHelper touchHelper;

    private CountDownManager countDownManager;

    public FamiliesAdapter(Context context, ArrayList<Family> families, ItemTouchHelper touchHelper) {
        super(context, families);
        this.touchHelper = touchHelper;

        viewTypes = Constants.Tags.VIEW_TYPES;

        countDownManager = new CountDownManager(Constants.Values.TIME_INTERVAL, this);
        countDownManager.start();
    }


    @Override
    public GenericViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // Inflating the view from a given layout resource file
        Log.d("A function has called", "onCreateViewHolder() was invoked");
        View v;
        switch (viewType) {
            case Constants.Tags.FAMILY_VIEW:
                v = LayoutInflater.from(context).inflate(R.layout.family_list_item, parent, false);
                FamilyViewHolder fvh = new FamilyViewHolder(context, v);
                return fvh;
            case Constants.Tags.TIME_UP_VIEW:
                v = LayoutInflater.from(context).inflate(R.layout.timeup_list_item, parent, false);
                TimeUpViewHolder tvh = new TimeUpViewHolder(context, v, this);
                return tvh;
        }
        return null;
    }

    @Override
    public void onBindViewHolder(GenericViewHolder holder, int position) {
        // Binds the Family object to the holder view
        Family family = families.get(position);
        holder.bindData(family);

        Log.d("A function has called", "onBindViewHolder() was invoked, IS FAMILY ADDED: " + ((FamilyViewHolder) holder).isHolderAdded);

        if(holder instanceof FamilyViewHolder){
            if(!((FamilyViewHolder) holder).isHolderAdded) {
                countDownManager.addHolder((FamilyViewHolder) holder);

                ((FamilyViewHolder) holder).isHolderAdded = true;
            }
        }

        // Sets animation on the given view, in case it wasn't displayed before
        Utils.setSlideAnimation(context, holder.getView(), position, lastPosition, false);
    }

    @Override
    public int getItemViewType(int position) {
        if(families.get(position).whenInMillis <= System.currentTimeMillis())
            return viewTypes[1];
        return viewTypes[0];
    }

    /* Changes the UI of a holder to a time's up view with a flickering ImageButton and a TextView*/

    @Override
    public void onFinish(FamilyViewHolder holder) {
        // Resets the holder for future uses
        holder.reset();

        // Play a sound for notifying purposes
        MediaPlayerManager.playSound(MediaPlayerManager.Sound.END);

        // Vibrates the device for 1.5 seconds
        Utils.vibrate(context, Constants.Values.VIBRATION_LENGTH_SHORT);

        notifyItemChanged(holder.getAdapterPosition());
    }

    @Override
    public void onLessThanMinute(FamilyViewHolder holder) {
        // if the sound option is on, play a swoosh sound
        MediaPlayerManager.playSound(MediaPlayerManager.Sound.ALERT);
        Drawable stroke = ContextCompat.getDrawable(context, R.drawable.family_item_red_stroke);
        holder.frame.setBackground(stroke);

        Utils.setFadeAnimation(holder.frame);
        holder.isStrokeChanged = true;
    }

    @Override
    public void onRemoveTimeUpViewHolder(int pos, GenericViewHolder holder) {
        touchHelper.startSwipe(holder);
        removeData(pos, holder);
    }

    public void removeData(int pos, GenericViewHolder holder) {
        // Sets the last position to the given deleted position for animation purposes
        lastPosition = pos;

        // Removes the family object from the data set
        String name = Utils.getLastName(families.get(pos).name);

        families.remove(pos);
        notifyItemRemoved(pos);
        notifyItemRangeChanged(pos, getItemCount());

        if(holder instanceof FamilyViewHolder)
            // Cancels the the timer and removes it from the entry set
            countDownManager.removeHolder((FamilyViewHolder) holder);

        holder.reset();
        Toast.makeText(context, "משפחת "+name+" נמחקה מהרשימה", Toast.LENGTH_SHORT).show();
    }


    /* Cancels the timers and clears the entry set */
    public void cancelTimers() {
        countDownManager.reset();
        countDownManager.clear();
        countDownManager.stop();
    }

    /* Clears the adapter's data and resets the last position to -1 */
    @Override
    public void clearData() {
        super.clearData();
        cancelTimers();
        lastPosition = -1;
    }
}

FamilyViewHolder:

package bikurim.silverfix.com.bikurim.adapters.holders;

import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.CardView;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import bikurim.silverfix.com.bikurim.R;
import bikurim.silverfix.com.bikurim.models.Family;
import bikurim.silverfix.com.bikurim.utils.Utils;

/**
 * Created by David on 07/07/2016.
 *
 * The official view holder of the adapter. Holds references to the relevant views inside the layout
 */

public class FamilyViewHolder extends GenericViewHolder {
    public boolean isStrokeChanged, isHolderAdded;

    public CardView cardView;
    public RelativeLayout frame;
    public TextView name;
    public TextView timeLeft;
    public TextView visitors;


    public Family family;

    private ColorStateList colorStateList;

    public FamilyViewHolder(Context context, View v) {
        super(v, context);
        // isStrokeChanged represents whether the holder is under 60 seconds or not
        isStrokeChanged = false;
        isHolderAdded = false;

        // Getting the references for the UI components
        cardView = (CardView) v.findViewById(R.id.cv);
        frame = (RelativeLayout) v.findViewById(R.id.card_frame);
        name = (TextView) v.findViewById(R.id.person_Lname);
        visitors = (TextView) v.findViewById(R.id.visitors);
        timeLeft = (TextView) v.findViewById(R.id.person_timeLeft);

        // Sets a reference to the old colors of the text view
        colorStateList = timeLeft.getTextColors();
    }

    @Override
    public void bindData(Family family) {
        this.family = family;
        name.setText(Utils.formatNameString(family.name));
        visitors.setText(" מבקרים: "+family.visitorsNum);
    }

    @Override
    public void reset() {
        family = null;
        name.setText("");
        visitors.setText("");
        timeLeft.setText("");

        Drawable drawable = ContextCompat.getDrawable(context, R.drawable.family_item_blue_stroke);

        this.frame.clearAnimation();
        this.frame.setAnimation(null);

        this.frame.setBackground(drawable);

        isStrokeChanged = false;
        isHolderAdded = false;
    }

    public ColorStateList getOriginalColors() {
        return colorStateList;
    }

}

CountDownManager:

package bikurim.silverfix.com.bikurim.utils.managers;

import android.os.Handler;
import android.os.Message;
import android.util.Log;

import java.util.ArrayList;
import java.util.ConcurrentModificationException;

import bikurim.silverfix.com.bikurim.Constants;
import bikurim.silverfix.com.bikurim.adapters.holders.FamilyViewHolder;
import bikurim.silverfix.com.bikurim.utils.interfaces.EventListener;
import bikurim.silverfix.com.bikurim.utils.Utils;

/**
 * Created by David on 07/07/2016.
 * @author David
 * Inspired by MiguelLavigne
 *
 * A custom CountDownTimer class, which takes care of all the running timers
 */
public class CountDownManager {

    private final long interval;
    private long base;

    // Holds references for all the visible text views
    private ArrayList<FamilyViewHolder> holders;

    private EventListener listener;

    public CountDownManager(long interval, EventListener listener) {
        this.listener = listener;
        this.interval = interval;
        holders = new ArrayList<>();
    }

    public void start() {
        base = System.currentTimeMillis();
        handler.sendMessage(handler.obtainMessage(MSG));
    }

    public void stop() {
        handler.removeMessages(MSG);
    }

    public void reset() {
        synchronized (this) {
            base = System.currentTimeMillis();
        }
    }

    public void addHolder(FamilyViewHolder holder) {
        synchronized (holders) {
            holders.add(holder);
        }
    }

    public void removeHolder(FamilyViewHolder holder) {
        synchronized (holders) {
            holders.remove(holder);
        }
    }

    private void onTick(long elapsedTime) {
       try {
           if(!holders.isEmpty()) {
               long timeLeft, lengthOfVisit;
               for (FamilyViewHolder holder : holders) {
                   lengthOfVisit = holder.family.whenInMillis - base;
                   timeLeft =  lengthOfVisit - elapsedTime;
                   if(timeLeft > 0) {
                       if(timeLeft <= Constants.Values.ALERT_TIME && !holder.isStrokeChanged) {
                           listener.onLessThanMinute(holder);
                       }
                       holder.family.timeLeft = timeLeft;
                       holder.timeLeft.setText(Utils.updateFormatTime(timeLeft));
                   } else {
                       listener.onFinish(holder);
                       removeHolder(holder);
                   }
               }

               Log.d("Holder length:", "" + holders.size());
           }
       } catch (ConcurrentModificationException e) {
            Log.d("Concurrent Error", "App will shut down now");
            e.printStackTrace();
       }
    }

    public void clear() {
        synchronized (holders) {
            for(FamilyViewHolder holder : holders)
                holder.reset();
            holders.clear();
        }
    }

    private static final int MSG = 1;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            synchronized (CountDownManager.this) {
                long elapsedTime = System.currentTimeMillis() - base;
                onTick(elapsedTime);
                sendMessageDelayed(obtainMessage(MSG), interval);
            }
        }
    };
}

有什么问题?

0 个答案:

没有答案