2017-05-07 179 views
0

我在RecyclerView中实现倒计时定时器有问题。 RecyclerView的数据输入来自对话框,其中用户输入项目名称,设置SeekBar时间(以秒为单位),并使用自定义小部件选择日期。信息保存在Realm数据库中。在RecyclerViewAdapter中实现定时器

问题是,在重新启动应用程序或添加新项目后,所有项目中的所有计时器都会重新启动并从头开始计数。如何实现定时器,即使应用程序不会处于活动状态或在添加新项目期间也不会计数。预先感谢您的帮助。

public class AdapterDrops extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements SwipeListener { 

public static final int COUNT_FOOTER = 1; 
public static final int COUNT_NO_ITEMS = 1; 
public static final int ITEM = 0; 
public static final int NO_ITEM = 1; 
public static final int FOOTER = 2; 
private final ResetListener mResetListener; 
private MarkListener mMarkListener; 
//inflater object which converts xml file to view object 
private LayoutInflater mInflater; 
public RealmResults<Drop> mResults; 
private AddListener mAddListener; 
private int mFilterOption; 
private Realm mRealm; 
private Context mContext; 
Handler handler; 
public long duration; 


public AdapterDrops(Context context, Realm realm, RealmResults<Drop> results, AddListener listener, MarkListener markListener, ResetListener resetListener) { 
    mContext = context; 
    mInflater = LayoutInflater.from(context); 
    update(results); 
    mRealm = realm; 
    mAddListener = listener; 
    mMarkListener = markListener; 
    mResetListener = resetListener; 

} 

public void update(RealmResults<Drop> results) { 
    mResults = results; 
    mFilterOption = AppBucketDrops.load(mContext); 
    //notification do Apdapter that database was changed 
    notifyDataSetChanged(); 

} 

@Override 
public long getItemId(int position) { 
    if (position < mResults.size()) { 
     return mResults.get(position).getAdded(); 
    } 
    return RecyclerView.NO_ID; 
} 

@Override 
public int getItemViewType(int position) { 
    if (!mResults.isEmpty()) { 
     if (position < mResults.size()) { 
      return ITEM; 
     } else { 
      return FOOTER; 
     } 
    } else { 
     if (mFilterOption == Filter.COMPLETE || 
       mFilterOption == Filter.INCOMPLETE) { 
      if (position == 0) { 
       return NO_ITEM; 
      } else { 
       return FOOTER; 
      } 
     } else { 
      return ITEM; 
     } 
    } 
} 

@Override 
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    if (viewType == FOOTER) { 
     View view = mInflater.inflate(R.layout.footer, parent, false); 
     //footerHolder class which we created below 
     return new FooterHolder(view); 
    } else if (viewType == NO_ITEM) { 
     View view = mInflater.inflate(R.layout.no_item, parent, false); 
     return new NoItemsHolder(view); 
    } else { 
     //layourInflater converts xml file to java View object 
     View view = mInflater.inflate(R.layout.row_drop, parent, false); 
     return new DropHolder(view, mMarkListener); 
    } 
} 

@Override 
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
    if (holder instanceof DropHolder) { 
     DropHolder dropHolder = (DropHolder) holder; 
     //returning an item from the paricular position 
     Drop drop = mResults.get(position); 
     //seting MtextView to proper drop.getWhat text 
     dropHolder.setWhat(drop.getWhat()); 
     dropHolder.setWhen(drop.getWhen()); 
     dropHolder.setTimer(drop.getTimer()); 
     dropHolder.setBackground(drop.isCompleted()); 
    } 

} 

@Override 
public int getItemCount() { 
    if (!mResults.isEmpty()) { 
     return mResults.size() + COUNT_FOOTER; 
    } else { 
     if (mFilterOption == Filter.LEAST_TIME_LEFT 
       || mFilterOption == Filter.MOST_TIME_LEFT 
       || mFilterOption == Filter.NONE) { 
      return 0; 
     } else { 
      return COUNT_NO_ITEMS + COUNT_FOOTER; 
     } 
    } 

} 


@Override 
public void onSwipe(int position) { 
    //delete item with transaction from database 
    if (position < mResults.size()) { 
     mRealm.beginTransaction(); 
     mResults.get(position).deleteFromRealm(); 
     mRealm.commitTransaction(); 
     notifyItemRemoved(position); 
    } 
    resetFilterIfEmpty(); 
} 

private void resetFilterIfEmpty() { 
    if (mResults.isEmpty() && (mFilterOption == Filter.COMPLETE || mFilterOption == Filter.INCOMPLETE)) { 
     mResetListener.onReset(); 
    } 
} 

public void markComplete(int position) { 
    //checking that item is not a footer 
    if (position < mResults.size()) { 
     mRealm.beginTransaction(); 
     mResults.get(position).setCompleted(true); 
     mRealm.commitTransaction(); 
     notifyItemChanged(position); 
    } 
} 

public static class DropHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 
    TextView mTextWhat; 
    TextView mTextWhen; 
    MarkListener mMarkListener; 
    Context mContext; 
    View mItemView; 
    TextView mTimer; 
    //timer 
    Handler handler; 
    public long timeRemaining; 
    public Drop drop; 

    public DropHolder(View itemView, MarkListener listener) { 
     super(itemView); 
     mItemView = itemView; 
     mContext = itemView.getContext(); 
     itemView.setOnClickListener(this); 
     mTextWhat = (TextView) itemView.findViewById(R.id.tv_what); 
     mTextWhen = (TextView) itemView.findViewById(R.id.tv_when); 
     mTimer = (TextView) itemView.findViewById(R.id.tv_timer); 
     mMarkListener = listener; 

    } 

    public void setWhat(String what) { 
     mTextWhat.setText(what); 
    } 

    public Drop getDrop(Drop drop) { 
     return drop; 
    } 

    public void setTimer(long timer) { 

     handler = new Handler(); 
     timeRemaining = timer * 1000; 
     final Runnable runnable = new Runnable() { 
      @Override 
      public void run() { 
       timeRemaining = timeRemaining - 1000; 

       if (timeRemaining > 0) { 
        handler.postDelayed(this, 1000); 
        timeRemaining = timeRemaining/1000; 
        mTimer.setText(Long.toString(timeRemaining)); 
        timeRemaining = timeRemaining * 1000; 
       } 
       if (timeRemaining == 0) { 
        mTimer.setText("Czas na lek !"); 
       } 
      } 
     }; 
     //kickstart 
     handler.postDelayed(runnable, 1000); 
    } 

    @Override 
    public void onClick(View v) { 
     mMarkListener.onMark(getAdapterPosition()); 
    } 

    public void setBackground(boolean completed) { 
     Drawable drawable; 
     if (completed) { 
      drawable = ContextCompat.getDrawable(mContext, R.color.colorLightBlueAfterClick); 
     } else { 
      drawable = ContextCompat.getDrawable(mContext, R.drawable.bg_row_drop); 
     } 
     /*if(Build.VERSION.SDK_INT > 15){ 
      mItemView.setBackground(drawable); 
     } else{ 
      mItemView.setBackgroundDrawable(drawable); 
     }*/ 
     Util.setBackground(mItemView, drawable); 

    } 

    public void setWhen(long when) { 
     mTextWhen.setText(DateUtils.getRelativeTimeSpanString(when, System.currentTimeMillis(), DateUtils.DAY_IN_MILLIS, 0)); 

    } 
} 

public static class NoItemsHolder extends RecyclerView.ViewHolder { 

    public NoItemsHolder(View itemView) { 
     super(itemView); 
    } 
} 

public class FooterHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 
    Button mBtnAdd; 

    public FooterHolder(View itemView) { 
     super(itemView); 
     mBtnAdd = (Button) itemView.findViewById(R.id.btn_footer); 
     mBtnAdd.setOnClickListener(this); 

    } 

    @Override 
    public void onClick(View v) { 
     //were using from this place AddListener 
     mAddListener.add(); 
    } 
} 

}

回答

0

代替节省倒计时时间,保存日期时间结束(现在的日期时间倒计时+)和基座上,所述逻辑。通过这种方式,当应用程序重置或查看重置时,通过将日期时间与结束日期时间进行比较,倒数逻辑将继续停留在停止位置。

此外,您发布的代码每隔一秒发布一次Runnable,即使对于用户不可见的代码也是如此。这会导致应用程序性能不佳。相反,创建一个可能由主办RecyclerView.AdapterActivity控制的单个计时器,并且它将调用RecyclerView.Adapter.notifyDataSetChanged(),这又将调用RecyclerView.Adapter.onBindViewHolder()来更新UI。因此,适配器将更新所有可见的UI元素,这意味着倒计时用户界面(当然只有可见的UI)每秒都会更新一次。即使滚动RecyclerView.Adapter.onBindViewHolder()将被调用,以便照顾。这将大大提高应用程序在数据集较大时的性能。

+0

太好了,非常感谢您的建议。我会尽力按照你所描述的来制作。祝你今天愉快 ! :) – mateolas

+0

像魔术一样工作!谢谢 ! – mateolas