Android实现倒计时功能

一.我们先看看需求:实现item上面倒计时效果,当倒计时完成之后移除该item条目并请求网络之后刷新该item
二.这边使用的是recycleView+CountDownTimer,下面给出伪代码,仅供参考。
三.伪代码
1.老规矩先贴出布局文件


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:addStatesFromChildren="true"
    android:fitsSystemWindows="true"
    android:clipToPadding="true"
    android:orientation="vertical">
    <LinearLayout
        android:id="@+id/ll_top"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/activity"
        android:orientation="horizontal">LinearLayout>

    <android.support.v7.widget.Toolbar
        android:id="@+id/ws_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="#F7F7F7">

        <TextView
            android:id="@+id/will_title"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:gravity="center_vertical|center_horizontal"
            android:text="倒计时"
            android:textColor="@color/black"
            android:textSize="@dimen/sp_16" />
    android.support.v7.widget.Toolbar>

    <com.aspsine.swipetoloadlayout.SwipeToLoadLayout
        android:id="@+id/stwillshow"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white">

        <include
            android:id="@id/swipe_refresh_header"
            layout="@layout/layout_twitter_header" />

        <FrameLayout
            android:id="@id/swipe_target"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/white">

            <android.support.design.widget.CoordinatorLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    app:layout_behavior="@string/appbar_scrolling_view_behavior">

                    <LinearLayout
                        android:id="@+id/wsbottom"
                        android:layout_width="match_parent"
                        android:layout_height="40dp"
                        android:layout_alignParentBottom="true"
                        android:gravity="center"
                        android:orientation="horizontal"
                        android:visibility="gone">
                        <ProgressBar
                            android:id="@+id/willshowBar"
                            style="?android:attr/progressBarStyleSmall"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="center"
                            android:layout_marginRight="6dp" />

                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="center"
                            android:text="正在加载"
                            android:textColor="@color/gray_bottom"
                            android:textSize="@dimen/sp_14" />
                    LinearLayout>

                    <android.support.v7.widget.RecyclerView
                        android:id="@+id/rvwillshow"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_alignParentLeft="true"
                        android:layout_alignParentStart="true"
                        android:layout_below="@+id/wsbottom"
                        android:overScrollMode="never"
                        android:scrollbars="none" />
                    <include layout="@layout/layout_no_data"
                        android:visibility="gone"/>
                RelativeLayout>
            android.support.design.widget.CoordinatorLayout>
        FrameLayout>
    com.aspsine.swipetoloadlayout.SwipeToLoadLayout>
LinearLayout>

2.再看看adapter里面的具体实现逻辑
(1)首先业务需求要加载两种不同类型的item,这个比较easy,代码如下

//代表着正在倒计时的item
    private static final int TYPE_NOW = 0;
    //代表着已经倒计时完毕的item
    private static final int TYPE_AGO= 1;
@Override
    public int getItemViewType(int position) {
        if (0 == Integer.valueOf(dataList.get(position).getFlag())) {
            return TYPE_NOW;
        } else if (1 == Integer.valueOf(dataList.get(position).getFlag())) {
            return TYPE_AGO;
        }
        return 0;
    }
 @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {
        if (viewType == TYPE_NOW) {
            // 填充正在开始倒计时的item
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_willshow_now, parent, false);
            viewHolderL = new LotteryNowViewHolder(view);
            return viewHolderL;
        }
        if (viewType == TYPE_AGO) {
            // 已经倒计时完毕的item
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_willshow_already, parent, false);
            viewHolderW = new WaitViewHolder(view);
            view.setOnClickListener(this);
            return viewHolderW;
        }
        return null;
    }

3.在onBindViewHolder里面进行分类加载

public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof LotteryNowViewHolder) {

        }
        if (holder instanceof WaitViewHolder) {
        }   
    }

4.CountDownTimer实现倒计时:在onTick方法里面给item的倒计时赋值,在onFinish方法里面做倒计时完后移除item并添加刷新后的item方法
有几点需要注意的是:
1.这里就不得不注意到臭名昭著的Cancel();解决方法是加入一个非空判断,必须加这个非空判断,不然会出现空指针,因为倒计时结束调用finish方法的时候要知道当前activity或者fragment时候存在
2.解决时间复用导致时间乱跳的问题:打上tag区分对待
下面是伪代码仅供参考

int countTime = Integer.valueOf(dataList.get(position).getCountdown());
                //打上tag防止复用的时候导致时间乱跳
                if (((LotteryNowViewHolder) holder).tvMinute.getTag() != null) {

                } else {
                    CountDownTimer timer = new CountDownTimer((long) countTime * 1000, 1000) {
                        //每个一秒钟就会执行一次
                        @Override
                        public void onTick(long millisUntilFinished) {
                            newTime = (int) (millisUntilFinished / 1000);
                            ((LotteryNowViewHolder) holder).tvSeconds.setText(getSecond(newTime));
                            ((LotteryNowViewHolder) holder).tvMinute.setText(getMinute(newTime));
                        }
                        //执行结束后调用的方法
                        @Override
                        public void onFinish() {
                            //倒计时完毕之后开始发送消息给fragment重新联网,为了移除该item把位置信息一并传过去
                            if (context != null) {
                                RxBusHelper.post("你接收到了吗" + dataList.get(position).getItemid() + "这是位置" + position);
                            }
                            //先移除item后然后进行再刷新数据
                            dataList.remove(position);
                            //开始刷新数据
                            notifyItemChanged(position);
                            ((LotteryNowViewHolder) holder).tvMinute.setTag(null);
                        }
                    }.start();
                    ((LotteryNowViewHolder) holder).tvMinute.setTag(position);
                }

换算时间的方式

public String getMinute(int time) {
        return time / 60 % 60 + "";
    }

    public String getSecond(int time) {
        int num = time % 60;
        return num < 10 ? (0 + "" + num) : (num + "");
    }

在adapter里面创建刷新item位置的构造方法

public void addElement(WillShowBean.ListBean listBean, int position) {
        this.dataList.add(position, listBean);
        notifyItemChanged(position);
    }

下面是fragment里面联网成功后走的方法调用addElement()方法

//这是当计时器为0的时候请求网络刷新数据
    //1.有新的数据进来的情况下,就有新的数据替换当前已经倒计时完成的item
    //2.没有新的数据进来的情况下,就移除当前item
    @Override
    public void getFutureAgain(AgainShowBean againShowBean) {
        if(againShowBean.getList()!=null&& againShowBean!=null){
            listBean.setFlag(againShowBean.getList().getFlag());
            ......//自己去添加需要加入的数据
            //通知去刷新adapter
            adapter.addElement(listBean,Integer.valueOf(position));
        }
    }

这是小弟第一篇博客也是开始以后会有更多原创的博客,望广大的技术大牛不吝赐教,学知识的人会散发迷人的魅力,也可以找我切磋技术,尊重知识,转载请注明出处谢谢:
联系方式:qq:1129126470
WeChat:ym1129126470 加的时候请备注来意谢谢。

你可能感兴趣的:(Android,随笔)