在RecyclerView中更新并控制多个CountDownTimer(暂停,恢复,删除)

时间:2016-06-09 14:24:47

标签: android android-recyclerview countdowntimer android-handler notifydatasetchanged

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

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

目前问题计时器正在运行的每一秒,新项目被添加到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();
}
}

使用RecyclerView进行分段:

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

    }
}
}

1 个答案:

答案 0 :(得分:1)

您对recyclelerview适配器的整个实现是错误的。在onBindViewHolder()中,您要添加新项目。当RecyclerView尝试显示新项时,将调用onBindViewHolder。因此,如果在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();
    }