0

I've got a question about multiple timers in recycler view. I've got functional rv by the moment, but I'm stuck on overriding onStop, onPause, onResume methods. I want my application to continue countdown while it's closed. Please help me to find solution, i'm a bit new to android.

My code :

Holder class

public class MyViewHolder extends RecyclerView.ViewHolder {

private long timeCountInMilliSeconds = 1 * 60000;

public long timeLeft = 0;

private enum TimerStatus {
    STARTED,
    STOPPED
}

public TextView title;
private TimerStatus timerStatus = TimerStatus.STOPPED;
private ProgressBar progressBarCV;
public TextView textViewTimeCV;
private CountDownTimer countDownTimer;

public MyViewHolder(View view) {
    super(view);
    initViews(view);
}

private void initViews(View view) {
    title = (TextView) view.findViewById(R.id.title);
    progressBarCV = (ProgressBar) view.findViewById(R.id.progressBarCV);
    textViewTimeCV = (TextView) view.findViewById(R.id.textViewTimeCV);
}

public void startStop(String minutes) {
    if (timerStatus == TimerStatus.STOPPED) {

        // call to initialize the timer values
        setTimerValues(minutes);
        // call to initialize the progress bar values
        setProgressBarValues();
        // changing the timer status to started
        timerStatus = TimerStatus.STARTED;
        // call to start the count down timer
        startCountDownTimer();

    } else {

        // changing the timer status to stopped
        timerStatus = TimerStatus.STOPPED;
        stopCountDownTimer();
    }
}

private void setTimerValues(String minutes) {
    int time = 0;
    if (!minutes.isEmpty() || Integer.parseInt(minutes) != 0) {

        time = Integer.parseInt(minutes);
    }

    // assigning values after converting to milliseconds
    timeCountInMilliSeconds = time * 60 * 1000;
}

private void startCountDownTimer() {
    countDownTimer = new CountDownTimer(timeCountInMilliSeconds, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {

            textViewTimeCV.setText(hmsTimeFormatter(millisUntilFinished));

            progressBarCV.setProgress((int) (millisUntilFinished / 1000));

            timeLeft = millisUntilFinished;

            Log.d("timeLeft", String.valueOf(timeLeft));

        }

        @Override
        public void onFinish() {

            textViewTimeCV.setText(hmsTimeFormatter(timeCountInMilliSeconds));
            // call to initialize the progress bar values
            setProgressBarValues();
            // changing the timer status to stopped
            timerStatus = TimerStatus.STOPPED;
        }

    }.start();
}

private void stopCountDownTimer() {
    countDownTimer.cancel();
}

private void setProgressBarValues() {

    progressBarCV.setMax((int) timeCountInMilliSeconds / 1000);
    progressBarCV.setProgress((int) timeCountInMilliSeconds / 1000);
}

private String hmsTimeFormatter(long milliSeconds) {

    String hms = String.format("%02d:%02d:%02d",
            TimeUnit.MILLISECONDS.toHours(milliSeconds),
            TimeUnit.MILLISECONDS.toMinutes(milliSeconds) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(milliSeconds)),
            TimeUnit.MILLISECONDS.toSeconds(milliSeconds) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milliSeconds)));

    return hms;
}}

Model class

public class Task {
private String title;
private String time;

public Task() {
}

public Task(String title, String description, String time) {
    this.title = title;
    this.time = time;
}

public String getTitle() {
    return title;
}

public void setTitle(String name) {
    this.title = name;
}

public String getTime() {
    return time;
}

public void setTime(String time) {
    this.time = time;
}}

Adapter

public class TaskAdapter extends RecyclerView.Adapter<MyViewHolder> {

private List<Task> taskList;

public TaskAdapter(List<Task> taskList) {
    this.taskList = taskList;
}

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

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    Task task = taskList.get(position);
    holder.title.setText(task.getTitle());
    holder.textViewTimeCV.setText(task.getTime());
    holder.startStop(task.getTime());
}


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

Main Activity (initializing here adapter and etc)

public class MainActivity extends AppCompatActivity {


public static List<Task> taskList = new ArrayList<>();
private RecyclerView recyclerView;
public static TaskAdapter tAdapter;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    initializeDrawer();

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            startActivity(new Intent(MainActivity.this, SecondActivity.class));
        }
    });

    recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
    recyclerView.setDrawingCacheEnabled(true);
    recyclerView.setItemViewCacheSize(50);

    tAdapter = new TaskAdapter(taskList);
    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
    recyclerView.setLayoutManager(mLayoutManager);
    recyclerView.addOnItemTouchListener(new RecyclerViewTouchListener());
    recyclerView.setAdapter(tAdapter);


}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

@Override
protected void onResume() {
    super.onResume();
    tAdapter.notifyItemChanged(taskList.size()-1);
}

private void initializeDrawer()
{

    AccountHeader headerResult = initializeHeader();

    PrimaryDrawerItem item1 = new PrimaryDrawerItem().withIdentifier(1).withName(R.string.app_name);
    SecondaryDrawerItem item2 = new SecondaryDrawerItem().withIdentifier(2).withName(R.string.slogan_main);
    //create the drawer and remember the `Drawer` result object
    Drawer result = new DrawerBuilder()
            .withActivity(this)
            .withAccountHeader(headerResult)
            //.withToolbar(toolbar)
            .addDrawerItems(
                    item1,
                    new DividerDrawerItem(),
                    item2,
                    new SecondaryDrawerItem().withName(R.string.material_drawer_close)
            )
            .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                @Override
                public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                    // do something with the clicked item :D





                    return true;
                }
            })
            .build();
}
private AccountHeader initializeHeader()
{

    AccountHeader headerResult = new AccountHeaderBuilder()
            .withActivity(this)
            .withHeaderBackground(R.drawable.drawable_circle_dark_blue)
            .addProfiles(
                    new ProfileDrawerItem().withName("Mike Penz").withEmail("mikepenz@gmail.com").withIcon(getResources().getDrawable(R.drawable.drawable_circle_dark_blue))
            )
            .withOnAccountHeaderListener(new AccountHeader.OnAccountHeaderListener() {
                @Override
                public boolean onProfileChanged(View view, IProfile profile, boolean currentProfile) {
                    return false;
                }
            })
            .build();

    return headerResult;}

Second Activity (here i set values to my list, which is connected to my adadpter)

public class SecondActivity extends AppCompatActivity implements View.OnClickListener {

Task task;


private EditText editTextMinute;
private ImageView imageViewStartStop;
private EditText editTextTitle;

private String title;
private String minutes;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);

    // method call to initialize the views
    initViews();
    // method call to initialize the listeners
    initListeners();

}

/**
 * method to initialize the views
 */
private void initViews() {
    editTextMinute = (EditText) findViewById(R.id.editTextMinute);
    imageViewStartStop = (ImageView) findViewById(R.id.imageViewStartStop);
    editTextTitle = (EditText) findViewById(R.id.editTextTitle);
}

/**
 * method to initialize the click listeners
 */
private void initListeners() {
    imageViewStartStop.setOnClickListener(this);
}

/**
 * implemented method to listen clicks
 *
 * @param view
 */
@Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.imageViewStartStop:
            prepareTaskData(title, null, minutes);

            break;
    }
}


private void prepareTaskData(String title, String description, String time) {

    time = editTextMinute.getText().toString().trim();
    // fetching minutes for Task obj
    minutes = editTextMinute.getText().toString();
    // fetching value from edit text and type cast to string
    title = editTextTitle.getText().toString();
    // toast message to fill edit text
    if(minutes.isEmpty() || minutes == null || minutes == String.valueOf(0) ||  title.isEmpty() )
    {
        Toast.makeText(getApplicationContext(), getString(R.string.message_minutes_or_title), Toast.LENGTH_LONG).show();
    }
    else
    {
        task = new Task(title, description, time);
        taskList.add(task);
        tAdapter.notifyItemChanged(taskList.size() - 1);
        finish();
    }
}}

Maybe I should implement Service class in my project? Any inofrmation will be very useful for me

kboskin
  • 422
  • 3
  • 12

1 Answers1

1

You need to add count down timer in your onCreateViewHolder method of RecyclerView because onCreateViewHolder will be called only once.

onBindViewHolder will be called every time user scroll up or down

Refer this

Mani
  • 2,599
  • 4
  • 30
  • 49
  • Thank you, it helped me a lot! But, my question is how to set my timers also in background of my application. I spend several days in search, and i've found that solution is to use Service class. But i still don't understand, how to implement it with ctd timers in recycler view – kboskin Aug 03 '17 at 16:19
  • You require working code for the same? or more detailed explanation? – Mani Aug 03 '17 at 18:09
  • Both of, if it possible – kboskin Aug 04 '17 at 21:30