在回收器视图中更新和控制多个倒数计时器(暂停、恢复、删除)



我已经使用服务在我的Android应用程序中实现了多个倒数计时器。CountDownTimer 与服务一起运行,因此数据到片段通过 BroadcastReceiver 传递。

我想将每个计时器作为单独的项目添加到片段中的 RecyclerView 中,并能够在计时器滴答作响时更新它并控制它 - 暂停、恢复、添加 1 分钟和删除。

目前的问题是计时器运行的每一秒,新项目都会添加到RecyclerView中,而我无法控制它 - 暂停,恢复等。

服务等级:

public int onStartCommand(Intent intent, int flags, int startId) {

        if (intent.getAction().equals(Constants.ACTION.START_FOREGROUND_ACTION)){
            HandlerThread thread = new HandlerThread("ServiceStartArguments",
                    android.os.Process.THREAD_PRIORITY_BACKGROUND);
            thread.setName(nameOfFood);
            thread.start();
            mServiceLooper = thread.getLooper();
            mServiceHandler = new ServiceHandler(mServiceLooper);
    }
     private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }
        @Override
        public void handleMessage(Message msg) {
            // Normally we would do some work here, like download a file.
            Thread.currentThread().setName(nameOfFood);
            try {
                showCountDownTimer(enteredTimeFormatted);
            } catch (Exception e) {
                // Restore interrupt status.
                Thread.currentThread().interrupt();
            }
            stopSelf(msg.arg1);
        }
    private void showCountDownTimer(long number) {
        String normalStartTime = String.format(
                "%02d:%02d:%02d",
                TimeUnit.MILLISECONDS.toHours(number),
                TimeUnit.MILLISECONDS.toMinutes(number) -
                        TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(number)),
                TimeUnit.MILLISECONDS.toSeconds(number) -
                        TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(number)));
        Intent timerStartInfoIntent = new Intent(TIMER_START_INFO);
        timerStartInfoIntent.putExtra("VALUE", normalStartTime);
        timerStartInfoIntent.putExtra("NAME_FOOD", nameOfFood);
        LocalBroadcastManager.getInstance(NotificationService.this).sendBroadcast(timerStartInfoIntent);

        CountDownTimer timer = new CountDownTimer(number, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                timeLeft = millisUntilFinished;

                counter = millisUntilFinished / 1000;
                normalTime = String.format(
                        "%02d:%02d:%02d",
                        TimeUnit.MILLISECONDS.toHours(timeLeft),
                        TimeUnit.MILLISECONDS.toMinutes(timeLeft) -
                                TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(timeLeft)),
                        TimeUnit.MILLISECONDS.toSeconds(timeLeft) -
                                TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeLeft)));
                Intent timerInfoIntent = new Intent(TIME_INFO);
                timerInfoIntent.putExtra("VALUE", normalTime);
                timerInfoIntent.putExtra("NAME_FOOD", nameOfFood);
                LocalBroadcastManager.getInstance(NotificationService.this).sendBroadcast(timerInfoIntent);
            }
            @Override
            public void onFinish() {
                counter = 0;
                Intent timerFinishInfoIntent = new Intent(TIMER_FINISH_INFO);
                LocalBroadcastManager.getInstance(NotificationService.this).sendBroadcast(timerFinishInfoIntent);
            }
        };
        timer.start();
    }

适配器类:

public class TimerRecyclerViewAdapter extends RecyclerView.Adapter<TimerRecyclerViewAdapter.MyViewHolder> {
final private Context mContext;
public List<ModelTimer> mModelTimerList;
private final List<MyViewHolder> listHolder;

public TimerRecyclerViewAdapter(List<ModelTimer> modelTimerList, Context context) {
    super();
    this.mContext = context;
    this.mModelTimerList = modelTimerList;
    listHolder = new ArrayList<>();
}

public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    public final TextView nameTextView;
    public final TextView timerTextView;
    public final Button pauseBtn;
    public final Button addMinBtn;
    public final Button deleteBtn;
    ModelTimer mModelTimer;

    public MyViewHolder(View itemView) {
        super(itemView);
        nameTextView = (TextView) itemView.findViewById(R.id.active_timer_name);
        timerTextView = (TextView) itemView.findViewById(R.id.active_timer_timeLeft);
        pauseBtn = (Button) itemView.findViewById(R.id.active_timer_btn_pause);
        pauseBtn.setOnClickListener(this);
        addMinBtn = (Button) itemView.findViewById(R.id.active_timer_btn_addMin);
        addMinBtn.setOnClickListener(this);
        deleteBtn = (Button) itemView.findViewById(R.id.active_timer_btn_delete);
        deleteBtn.setOnClickListener(this);
    }
    public void setData (ModelTimer modelTimer){
        this.mModelTimer = modelTimer;
        timerTextView.setText(modelTimer.expirationTime);
        nameTextView.setText(modelTimer.name);
    }
    @Override
    public void onClick(View v) {
      // TODO 
    }
}
@Override
public TimerRecyclerViewAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (parent instanceof RecyclerView) {
        View v = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.item_active_timer,
                parent,
                false);
        v.setFocusable(true);
        return new MyViewHolder(v);
    } else {
        throw new RuntimeException("No bound to RecyclerViewSelection");
    }
}
@Override
public void onBindViewHolder(TimerRecyclerViewAdapter.MyViewHolder holder, int position) {
    holder.setData(mModelTimerList.get(position));
    synchronized (listHolder){
        listHolder.add(holder);
    }
}
@Override
public int getItemCount() {
    return mModelTimerList.size();
}

在这里,我尝试创建一种方法,该方法将每秒升级特定位置的计时器,而不是在每次计时器滴答作响时向RecyclerView添加新项目。

public void swap(List<ModelTimer> modelTimerList){
    mModelTimerList.clear();
    mModelTimerList.addAll(modelTimerList);
    notifyItemChanged(???);
}
public void delete() {
    mModelTimerList.clear();
    notifyDataSetChanged();
}
}

使用回收器视图的片段:

public class ActiveTimersFragment extends Fragment {
private RecyclerView mRecyclerView;
private TimerRecyclerViewAdapter mAdapter;
private ArrayList<ModelTimer> listOfTimers;
private TimerStatusReceiver mTimerStatusReceiver;
private static final String ARG_SECTION_NUMBER = "section_number";
public ActiveTimersFragment() {
}
public static ActiveTimersFragment newInstance(int sectionNumber) {
    ActiveTimersFragment activeTimersFragment = new ActiveTimersFragment();
    Bundle args = new Bundle();
    args.putInt(ARG_SECTION_NUMBER, sectionNumber);
    activeTimersFragment.setArguments(args);
    return activeTimersFragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_active_timers, container, false);
    mRecyclerView = (RecyclerView) view.findViewById(R.id.fragment_active_timers_recycler_view);
    mTimerStatusReceiver = new TimerStatusReceiver();
    listOfTimers = new ArrayList<>();
    return view;
}
@Override
public void onResume() {
    super.onResume();
    LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
            mTimerStatusReceiver, new IntentFilter(NotificationService.TIME_INFO));
    LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
            mTimerStatusReceiver, new IntentFilter(NotificationService.TIMER_START_INFO));
    LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
            mTimerStatusReceiver, new IntentFilter(NotificationService.TIMER_FINISH_INFO));
}
@Override
public void onPause() {
    super.onPause();
    LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mTimerStatusReceiver);
}
private class TimerStatusReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent != null && intent.getAction().equals(NotificationService.TIME_INFO)) {
            ModelTimer modelTimer = new ModelTimer();
            if (intent.hasExtra("VALUE")) {
                modelTimer.setexpirationTime(intent.getStringExtra("VALUE"));
            }
            if (intent.hasExtra("NAME_FOOD")) {
                modelTimer.setName(intent.getStringExtra("NAME_FOOD"));
            }
            listOfTimers.add(modelTimer);
            mAdapter = new TimerRecyclerViewAdapter(listOfTimers, getActivity());
            mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
            // Not working
            // mAdapter.swap(listOfTimers);
            mRecyclerView.setAdapter(mAdapter);
        }
        if (intent != null && intent.getAction().equals(NotificationService.TIMER_FINISH_INFO)) {
            mAdapter.delete();
        }
    }
}
}

您的整个回收视图适配器实现是错误的。在 onBindViewHolder() 中,您正在添加新项。onBindViewHolder 在 RecyclerView 尝试显示新项目时调用。所以它会继续迭代,如果你在 onBindViewHolder 中添加新项目。此外,还应使用 onBindViewHolder 在 ViewHolder 类中设置视图值。检查整个适配器实现。

   public class TimerRecyclerViewAdapter extends RecyclerView.Adapter<TimerRecyclerViewAdapter.MyViewHolder> {
    final private Context mContext;
    public List<ModelTimer> mModelTimerList;

    public TimerRecyclerViewAdapter(List<ModelTimer> modelTimerList, Context context) {
        super();
        this.mContext = context;
        this.mModelTimerList = modelTimerList;
    }

    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        public final TextView nameTextView;
        public final TextView timerTextView;
        public final Button pauseBtn;
        public final Button addMinBtn;
        public final Button deleteBtn;

        public MyViewHolder(View itemView) {
            super(itemView);
            nameTextView = (TextView) itemView.findViewById(R.id.active_timer_name);
            timerTextView = (TextView) itemView.findViewById(R.id.active_timer_timeLeft);
            pauseBtn = (Button) itemView.findViewById(R.id.active_timer_btn_pause);
            pauseBtn.setOnClickListener(this);
            addMinBtn = (Button) itemView.findViewById(R.id.active_timer_btn_addMin);
            addMinBtn.setOnClickListener(this);
            deleteBtn = (Button) itemView.findViewById(R.id.active_timer_btn_delete);
            deleteBtn.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            // TODO
        }
    }

    @Override
    public TimerRecyclerViewAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (parent instanceof RecyclerView) {
            View v = LayoutInflater.from(parent.getContext()).inflate(
                    R.layout.item_active_timer,
                    parent,
                    false);
            v.setFocusable(true);
            return new MyViewHolder(v);
        } else {
            throw new RuntimeException("No bound to RecyclerViewSelection");
        }
    }
    @Override
    public void onBindViewHolder(TimerRecyclerViewAdapter.MyViewHolder holder, int position) {
        ModelTimer modelTimer=mModelTimerList.get(position);
        holder.timerTextView.setText(modelTimer.expirationTime);
        holder.nameTextView.setText(modelTimer.name);
    }
    @Override
    public int getItemCount() {
        return mModelTimerList.size();
    }

最新更新