简体   繁体   English

时间到期后从Recyclerview中删除项目

[英]Removing Item From Recyclerview When Time Expired

I need to remove an item when time expired, partially i got output by referring this How to handle multiple countdown timers in ListView? 我需要在时间到期时删除一个项目,部分我通过参考如何在ListView中处理多个倒计时器获得输出

After scrolled the list, some of the time expired items are not removed and times are not updated. 滚动列表后,某些已过期的项目不会被删除,时间也不会更新。

package com.techno.deliveryboy.Adapter;

import android.os.Handler;
import android.support.v4.app.FragmentActivity;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.techno.deliveryboy.Pojos.DummyTimer;
import com.techno.deliveryboy.R;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by developer on 23/7/16.
 */
public class Incoiming_orders_Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>  {

    private LayoutInflater lf;
    Boolean onBind = true;
    private List<MyViewHolder> lstHolders;
    ArrayList<Integer> unbindvalues=new ArrayList<>();
    private Handler mHandler = new Handler();
    List<DummyTimer> lstProducts=new ArrayList<>();
    private Runnable updateRemainingTimeRunnable = new Runnable() {
        @Override
        public void run() {
            synchronized (lstHolders) {
                long currentTime = System.currentTimeMillis();

                for (MyViewHolder holder : lstHolders) {

                    holder.updateTimeRemaining(currentTime);


                }


            }
        }
    };

    public Incoiming_orders_Adapter(FragmentActivity activity, List<DummyTimer> lstProduct) {

        lstHolders = new ArrayList<>();
        lstProducts=lstProduct;

        startUpdateTimer();
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.incoming_orders_item, parent, false);
        return new MyViewHolder(itemView);
    }

    private void startUpdateTimer() {
        Timer tmr = new Timer();
        tmr.schedule(new TimerTask() {
            @Override
            public void run() {
                mHandler.post(updateRemainingTimeRunnable);

            }
        }, 1000, 1000);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
      if(holder instanceof MyViewHolder){
          onBind=true;
          MyViewHolder holder1= (MyViewHolder) holder;
          synchronized (lstHolders) {
              lstHolders.add(holder1);

           }
          holder1.setData(lstProducts.get(position),position);
          onBind=false;

      }
    }

    @Override
    public int getItemCount() {
        return lstProducts.size();
    }
    public void removeAt(int position) {

       /* for (Iterator<MyViewHolder> iterator = lstHolders.iterator(); iterator.hasNext();) {

           iterator.remove();
        }*/


        if(!onBind) {
            if(unbindvalues!=null&&unbindvalues.size()!=0&&position>=0){
                for (Integer i:unbindvalues) {
                    lstProducts.remove(position);
                    notifyItemRemoved(position);
                }
                unbindvalues.clear();

            }else {
                if(position>=0){
                    lstProducts.remove(position);
                    notifyItemRemoved(position);
                }

            }




            notifyDataSetChanged();
        }else {
            System.out.println("+Bind->true+");
            if(position>=0)
            unbindvalues.add(position);
        }
    }


    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView title, tvTimeRemaining, genre;
        DummyTimer mProduct;
        public void setData(DummyTimer item, int position) {
            mProduct = item;
            title.setText(item.name);
            updateTimeRemaining(System.currentTimeMillis());
        }

        public MyViewHolder(View view) {
            super(view);
            title = (TextView) view.findViewById(R.id.Item_Totalvalue);
            tvTimeRemaining= (TextView) view.findViewById(R.id.Item_timeout);
        }

        public void updateTimeRemaining(long currentTime) {
            long timeDiff = mProduct.expirationTime - currentTime;
            if (timeDiff > 0) {
                int seconds = (int) (timeDiff / 1000) % 60;
                int minutes = (int) ((timeDiff / (1000 * 60)) % 60);
                int hours = (int) ((timeDiff / (1000 * 60 * 60)) % 24);
                tvTimeRemaining.setText(hours + " hrs " + minutes + " mins " + seconds + " sec");
            } else {
              // tvTimeRemaining.setText(String.valueOf(getAdapterPosition()));


                removeAt(getAdapterPosition());

            }
        }
    }

    @Override
    public long getItemId(int position) {
        return position;
    }
}

Please give your comment. 请发表评论。

You can achieve this by setting up the CountDownTimer which will trigger onTick() method every second. 你可以通过设置CountDownTimer来实现这一点,它将onTick()触发onTick()方法。 In onTick() method check if there are any objects those are expired? onTick()方法中检查是否有任何过期的对象? If you find any object remove them by calling notifyItemRemoved() . 如果您发现任何对象通过调用notifyItemRemoved()删除它们。

Here is the code of recycler view adapter: 这是Recycler视图适配器的代码:

private class RecyclerViewAdapter extends RecyclerView.Adapter { private ArrayList mData; 私有类RecyclerViewAdapter扩展了RecyclerView.Adapter {private ArrayList mData;

    public RecyclerViewAdapter(ArrayList<RowData> data) {
        mData = data;

        //find out the maximum time the timer
        long maxTime = System.currentTimeMillis();
        for (RowData item : mData) {
            maxTime = Math.max(maxTime, item.endTime);
        }

        //set the timer which will refresh the data every 1 second.
        new CountDownTimer(maxTime - System.currentTimeMillis(), 1000) {
            @Override
            public void onTick(long l) {
                for (int i = 0, dataLength = mData.size(); i < dataLength; i++) {
                    RowData item = mData.get(i);
                    item.timeRemaining -= 1000;
                }

                //remove the expired items
                Iterator<RowData> dataIterator = mData.iterator();
                while (dataIterator.hasNext()) {
                    RowData rd = dataIterator.next();
                    if (rd.timeRemaining <= 0) dataIterator.remove();
                }
                notifyDataSetChanged();
            }

            @Override
            public void onFinish() {
                mData.clear();
                notifyDataSetChanged();
            }
        }.start();
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new MyViewHolder(LayoutInflater.from(MainActivity.this).inflate(android.R.layout.simple_list_item_2, parent, false));
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        RowData rowData = mData.get(position);
        holder.titleTv.setText(rowData.title);
        holder.remainingTimeTv.setText(millToMins(rowData.timeRemaining) + " mins remaining");
    }

    private String millToMins(long millisec) {
        return millisec / (60000) + ":" + (int) (millisec/1000) % (60);
    }

    @Override
    public int getItemCount() {
        return mData.size();
    }

    public class MyViewHolder extends RecyclerView.ViewHolder {
        private TextView remainingTimeTv;
        private TextView titleTv;

        public MyViewHolder(View itemView) {
            super(itemView);
            remainingTimeTv = (TextView) itemView.findViewById(android.R.id.text2);
            titleTv = (TextView) itemView.findViewById(android.R.id.text1);
        }
    }

}

PS : Here is the full code demo available on my GitHub account. PS: 这是我的GitHub帐户上提供的完整代码演示

The thing that you want is similar to filter on difference is that you want the item to be removed . 您想要的东西类似于过滤器的不同之处在于您希望删除该项目。 I would suggest setting an Observer for all the timers in the list and whenever your timer crosses the schedule you have to update the observer , which will remove it form the list or arraylist of items that you have. 我建议为列表中的所有计时器设置一个Observer ,每当你的计时器超过计划时,你必须更新观察者,这将从你拥有的项目的列表或arraylist中删除它。 Notify your data set that a change has occurred which will refresh your RecyclerView. 通知您的数据集已发生更改,这将刷新您的RecyclerView。

You can have a periodic operation set-up that will remove items from RecyclerView adapter. 您可以定期进行操作设置,从RecyclerView适配器中删除项目。 Below is a crude example. 下面是一个粗略的例子。

First, define the item class that represents list items: 首先,定义表示列表项的项类:

import android.text.format.DateFormat;

public class TimedItem {
    private final long expireAt;
    private final String  name;

    public TimedItem(String name, long expireAt) {
        this.name = name;
        this.expireAt = expireAt;
    }

    public String getName() {
        return name;
    }

    public String getDescription(){
        return String.format("Expires at %s.", DateFormat.format("h:mm:ss a ddd, MMM, YYYY",this.expireAt));
    }

    public boolean isExpired(){
        return System.currentTimeMillis() > this.expireAt;
    }
}

Since the items are to be displayed using RecyclerView , define a ViewHolder as well: 由于要使用RecyclerView显示项目,因此也要定义ViewHolder

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;

public class TimedItemHolder extends RecyclerView.ViewHolder {
    private final TextView nameView;
    private final TextView descView;
    public TimedItemHolder(View itemView) {
        super(itemView);
        this.nameView = (TextView) itemView.findViewById(android.R.id.text1);
        this.descView = (TextView) itemView.findViewById(android.R.id.text2);
    }

    public TextView getNameView() {
        return nameView;
    }

    public TextView getDescView() {
        return descView;
    }
}

Now, to display items in RecycleView , we need to define an RecyclerView.Adapter . 现在,要在RecycleView显示项目,我们需要定义RecyclerView.Adapter This will also handle item removal on expiry : 这也将在到期时处理项目删除:

import android.os.Handler;
import android.os.Looper;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;


public class TimerAdapter extends RecyclerView.Adapter<TimedItemHolder> {
    private final List<TimedItem> items = new ArrayList<>();
    private final Handler handler = new Handler(Looper.getMainLooper());
    private final long interval;
    private final Runnable task = new Runnable() {
        @Override
        public void run() {
            int i = 0;
            Iterator<TimedItem> iterator = TimerAdapter.this.items.iterator();
            while (iterator.hasNext()) {
                TimedItem item = iterator.next();
                if (item.isExpired()) {
                    iterator.remove();
                    notifyItemRemoved(i);
                } else {
                    i++;
                }
            }
            handler.postDelayed(this, interval);
        }
    };

    public TimerAdapter(long interval) {
        this.interval = interval;
        handler.postDelayed(task, interval);
    }

    public void addItem(TimedItem item) {
        this.items.add(item);
    }

    public void addAll(Collection<? extends TimedItem> items) {
        this.items.addAll(items);
    }

    public void clear() {
        this.items.clear();
    }

    @Override
    public TimedItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_2, parent, false);
        return new TimedItemHolder(view);
    }

    @Override
    public void onBindViewHolder(TimedItemHolder holder, int position) {
        TimedItem item = this.items.get(position);
        holder.getNameView().setText(item.getName());
        holder.getDescView().setText(item.getDescription());
    }

    @Override
    public int getItemCount() {
        return this.items.size();
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        handler.removeCallbacks(task);
    }
}

Finally, we can test it: 最后,我们可以测试一下:

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import java.util.Random;


public class TestActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        RecyclerView list = new RecyclerView(this);
        list.setLayoutManager(new LinearLayoutManager(this));
        TimerAdapter adapter = new TimerAdapter(1000);
        list.setAdapter(adapter);
        setContentView(list);


        Random random = new Random();

        for (int i = 0; i < 20; i++) {
            String name = "Item: " + i;
            long expireAt = System.currentTimeMillis() + 5000 + random.nextInt(20000);
            adapter.addItem(new TimedItem(name,expireAt));
        }

        adapter.notifyDataSetChanged();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM