Search code examples
androidcountdowntimerandroid-recyclerviewonscrolllistener

To keep Count Down Timer running without affecting in Recyclerview when applied Pagination


I have a timer in each List Item of a Recyclerview for which I applied Pagination, these all works fine.Now For Example one of my count down timer is 02:50 mins I fetched from API and plotted it in Page 0 now if I scroll down to other pages in Pagination and come back to page 0 say in 10 secs back so it is suppose to be 02.39 or 02:40 but it is taking again the old API value and plotting 02:50 and starts counting down again which is wrong. Is there any ways to handle count down timer in recyclerView with Pagination.

// In Activity Pagination and a Call API method based on PageNo
        buyeroffer_rv.addOnScrollListener(new EndlessScrollListener(mLayoutManager) {
            @Override
            public void onLoadMore(int page, int totalItemsCount) {

                System.out.print("NUMPAGE_SCROLLED");
                System.out.print("PAge No"+page);


                progress_loader.setVisibility(View.VISIBLE);
                if (Internet.isConnectedToInternet()) {

                    pageno=page;
                    callApi(page);
                }
                else
                {
                    progress_loader.setVisibility(View.VISIBLE);
                    CustomToast.getInstance().toastMsg(activity,Internet.interNetMsg,ApiService.INTERNET_FLAG);
                }


            }
        });

Then in Recycle View Adapter On BindViewHolder The timer is fetched from API in seconds and timer starts based on that value.

    // Adapter Code Snippet
    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {

        // Timer current value is fetched from API for each Item
        if (res.getTimeSloteOne() != null && !res.getTimeSloteOne().toString().isEmpty()) {
            timer = res.getTimeSloteOne();
        }

        // Here based on activeFlag hide or show Timer text
        if ((activeflag.equalsIgnoreCase("0") && !res.getBidtype().toString().equalsIgnoreCase("5")) || (activeflag.equalsIgnoreCase("4")) && (res.getBidtype().toString().equalsIgnoreCase("0") || res.getBidtype().toString().equalsIgnoreCase("0.0"))) {
            if (timer > 0) {
                timer = timer * 1000;
                holder.timer = new CountDownTimer(timer, 1000) {
                    public void onTick(long millisUntilFinished) {

                        holder.timmertext.setText("" + String.format(FORMAT,
                                TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) - TimeUnit.HOURS.toMinutes(
                                        TimeUnit.MILLISECONDS.toHours(millisUntilFinished)),
                                TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(
                                        TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished))));

                        if (TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millisUntilFinished)) >= 30) {
                            holder.timmertext.setTextColor(activity.getResources().getColor(R.color.timer1));
                        } else if (TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millisUntilFinished)) >= 10 &&
                                TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millisUntilFinished)) < 30) {
                            holder.timmertext.setTextColor(activity.getResources().getColor(R.color.timer2));
                        } else if (TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millisUntilFinished)) < 10) {
                            holder.timmertext.setTextColor(activity.getResources().getColor(R.color.timer3));
                        }
                    }

                    public void onFinish() {
                        holder.timmertext.setText("00:00");
                        holder.timmertext.setTextColor(activity.getResources().getColor(R.color.color_black));
                    }
                }.start();
            }
        }
        else {
            // 
            holder.timmertext.setVisibility(View.GONE);
        }
    }
}

// XML for the Activity

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".uibuyer.BuyerOfferAct"
    android:background="#f0f0f0">
   <android.support.v4.widget.SwipeRefreshLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/swipe_layout"
                android:background="#e6e6e6"
                android:layout_marginBottom="50dp">
                <android.support.v7.widget.RecyclerView
                    android:id="@+id/recycler_view"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_marginBottom="50dp"
                    android:clipToPadding="false"
                    android:paddingBottom="10dp" />
            </android.support.v4.widget.SwipeRefreshLayout>
            <RelativeLayout
                android:id="@+id/loader_lay"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/loader_bg"
                android:layout_below="@+id/toolbar_container"
                android:layout_marginBottom="50dp"
                android:visibility="gone">
                <include
                    android:id="@+id/loader"
                    layout="@layout/common_loader"
                    />
            </RelativeLayout>
</RelativeLayout>

In Adapter the Layout Snippet

           <com.xelpmoc.zommodity.utils.TextViewWithFont
            android:id="@+id/time_lft_txt"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Time Left"
            android:textAlignment="textEnd"
            android:textAllCaps="true"
            android:textColor="@color/texttwo"
            android:textSize="@dimen/font8"
            font:name="FONT_OPENSANS_BOLD" />

        <com.xelpmoc.zommodity.utils.TextViewWithFont
            android:id="@+id/timmertext"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="03:50"
            android:textAlignment="textEnd"
            android:textAllCaps="true"
            android:textSize="15dp"
            font:name="FONT_OPENSANS_BOLD" />

        <com.xelpmoc.zommodity.utils.TextViewWithFont
            android:id="@+id/time_mins"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="MINS"
            android:textAlignment="viewEnd"
            android:textAllCaps="true"
            android:textColor="@color/text_one"
            android:textSize="11dp"
            font:name="FONT_OPENSANS_BOLDITALIC" />

Solution

  • First we have to Create one boolen variable in viewHolder and we have to make it as false.

     public class MyViewHolder extends RecyclerView.ViewHolder {
                  boolean timerflag=false;
              CountDownTimer timer;
                        public MyViewHolder(View view) {
                            super(view);
                }
                }
    

    And in onBindViewHolder we have to handle the flag

        @Override
        public void onBindViewHolder(final MyViewHolder holder, final int position) {
            if (holder.timerflag == false) {
    
                if (holder.timer != null) {
                    holder.timer.cancel();
                }
    
    
                if (timeslot != null) {
                    timer = timeslot;
                    holder.timerflag = true;
                }
    
    
                if (timer > 0) {
                    timer = timer * 1000;
                    holder.timer = new CountDownTimer(timer, 1000) {
                        public void onTick(long millisUntilFinished) {
    
                            //do the task
                        }
    
                        public void onFinish() {
    
                        }
                    }.start();
                }
            }
    }