【问题标题】:Removing Item From Recyclerview When Time Expired时间到期时从 Recyclerview 中删除项目
【发布时间】:2016-07-25 07:18:02
【问题描述】:

我需要在时间到期时删除一个项目,部分我通过引用这个How to handle multiple countdown timers in ListView?得到输出

滚动列表后,一些时间过期的项目没有被删除,时间也没有更新。

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;
    }
}

请发表您的意见。

【问题讨论】:

    标签: java android timer android-recyclerview


    【解决方案1】:

    您可以通过设置CountDownTimer 来实现此目的,该onTick() 方法将每秒触发一次。在onTick() 方法中检查是否有任何对象过期?如果您发现任何对象,请致电notifyItemRemoved() 将其删除。

    这里是recycler view adapter的代码:

    私有类 RecyclerViewAdapter 扩展 RecyclerView.Adapter { 私有 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);
            }
        }
    
    }
    

    P.S. : 这是我的 GitHub 帐户上提供的完整代码 demo

    【讨论】:

      【解决方案2】:

      您想要的类似于过滤差异的事情是您希望删除该项目。我建议为列表中的所有计时器设置一个 Observer ,并且每当您的计时器超过时间表时,您必须更新观察者,这会将其从您拥有的项目列表或数组列表中删除。通知您的数据集发生了更改,这将刷新您的 RecyclerView。

      【讨论】:

        【解决方案3】:

        您可以进行定期操作设置,从RecyclerView 适配器中删除项目。下面是一个粗略的例子。

        首先,定义代表列表项的项目类:

        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;
            }
        }
        

        由于要使用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;
            }
        }
        

        现在,要在RecycleView 中显示项目,我们需要定义一个RecyclerView.Adapter。这也将处理到期时的项目删除:

        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);
            }
        }
        

        最后,我们可以测试一下:

        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();
            }
        }
        

        【讨论】:

        • 时间计数不会更新到项目。但是一旦时间到期,项目就会删除。无论如何感谢您的回复。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-01
        • 1970-01-01
        相关资源
        最近更新 更多