Recyclerview与计时器重用旧视图

时间:2016-05-16 10:51:15

标签: android listview android-recyclerview

我在Recyclerview中有20个自定义计时计时器的列表,如果我从第一个开始,第14行或第15行也在textview中显示相同的计时器。我猜计时器正在保持对第一个textview的引用,并且它会连续更新它,这将在第14行或第15行重用。谁能告诉我如何有效地做到这一点。在此先感谢。

MainActivity.java

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity  {

    private static final String TAG = "MainActivity";
    private RecyclerView mRecyclerView;
    private CountAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mAdapter = new CountAdapter(getCount(), this);
        mRecyclerView = (RecyclerView) findViewById(R.id.rv);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(linearLayoutManager);
        mRecyclerView.setAdapter(mAdapter);

    }

    private List<String> getCount() {
        List<String> strings = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            strings.add(i + "");
        }
        return strings;
    }

}

CountAdapter.java

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageButton;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class CountAdapter extends RecyclerView.Adapter<CountAdapter.ViewHolder> {
    private static final String TAG = "CountAdapter";
    private final List<String> mData;
    private final List<CountUpTimer> mCountUpList = new ArrayList<>();
    private final ArrayList<Boolean> mSelectedRows = new ArrayList<>();
    private final Context mContext;

    public CountAdapter(List<String> mData, Context mContext) {
        this.mData = mData;
        this.mContext = mContext;

        mCountUpList.clear();
        for (int i = 0; i < mData.size(); i++) {
            mCountUpList.add(i, null);
        }
        mSelectedRows.clear();
        for (int i = 0; i < mData.size(); i++) {
            mSelectedRows.add(i, false);
        }
    }


    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent,
                                         int viewType) {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item, parent, false);
        return new ViewHolder(v, mContext, mCountUpList, mSelectedRows);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

        checkTimerStatus(holder, position);
        Log.d(TAG, "onBindViewHolder: " + position + " " + String.valueOf(mCountUpList.get(position)));
    }

    private void checkTimerStatus(final ViewHolder holder, int position) {

        CountUpTimer countUpTimer = mCountUpList.get(position);
        if (countUpTimer != null) {
            Log.d(TAG, "checkTimerStatus: " + position);
            countUpTimer.setOnTickListener(new CountUpTimer.OnTickListener() {
                @Override
                public void OnTick(long elapsed) {
                    holder.mTimeText.setText(elapsed + "");
                }
            });
        } else {
            holder.mTimeText.setText("00:00:00");
        }

        boolean state = mSelectedRows.get(position);
        holder.mCheckBox.setChecked(state);

    }

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

    static class ViewHolder extends RecyclerView.ViewHolder implements
            CountUpTimer.OnTickListener, View.OnClickListener {
        private static final String TAG = "ViewHolder";
        private final Context mContext;
        private final ArrayList<Boolean> mSelectedRows;
        private final TextView mTimeText;
        private final ImageButton mStartButton;
        private final CheckBox mCheckBox;
        private final List<CountUpTimer> mCountUpList;

        public ViewHolder(View v, Context mContext, List<CountUpTimer> mCountUp,
                          ArrayList<Boolean> mSelectedRows) {

            super(v);
            this.mContext = mContext;
            this.mCountUpList = mCountUp;
            this.mSelectedRows = mSelectedRows;
            mTimeText = (TextView) v.findViewById(R.id.itemText);
            mStartButton = (ImageButton) v.findViewById(R.id.ibPlay);
            mCheckBox = (CheckBox) v.findViewById(R.id.checkBox);
            mStartButton.setOnClickListener(this);
            mCheckBox.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {

            switch (v.getId()) {

                case R.id.ibPlay:
                    final CountUpTimer upTimer = new CountUpTimer(100);
                    upTimer.setOnTickListener(this);
                    upTimer.start();
                    mCountUpList.set(getAdapterPosition(), upTimer);
                    break;

                case R.id.checkBox:
                    mSelectedRows.set(getAdapterPosition(),
                            !mSelectedRows.get(getAdapterPosition()));
                    break;
            }
        }

        @Override
        public void OnTick(long elapsed) {

            mTimeText.setText(elapsed + "");
        }
    }

} 

CountUpTimer.java

import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;

public class CountUpTimer {

    private final long interval;
    private long base;
    public long mElapsedTime;
    private OnTickListener onTickListener;

    public CountUpTimer(long interval) {
        this.interval = interval;
    }

    public void start() {
        base = SystemClock.elapsedRealtime();
        handler.sendMessage(handler.obtainMessage(MSG));
    }

    public void stop() {
        handler.removeMessages(MSG);
    }

    public void reset() {
        synchronized (this) {
            base = SystemClock.elapsedRealtime();
        }
    }

    public void setOnTickListener(OnTickListener onTickListener) {
        this.onTickListener = onTickListener;
    }

    private static final int MSG = 1;

    private Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            synchronized (CountUpTimer.this) {
                long elapsedTime = SystemClock.elapsedRealtime() - base;
                if (onTickListener != null) {
                    mElapsedTime = elapsedTime;
                    onTickListener.OnTick(elapsedTime);
                }
                sendMessageDelayed(obtainMessage(MSG), interval);
            }
        }
    };

    interface OnTickListener {
        void OnTick(long elapsed);
    }
}

1 个答案:

答案 0 :(得分:-1)

这可能是因为您不是每次都在onBindViewHolder上更新holder.mTimeText。即你的代码没有到达声明:因此视图正在回收物品。

            holder.mTimeText.setText(elapsed + "");

每次更新视图时 尝试设置

if(countUpTimer != null) {
 holder.mTimeText.setText(elapsed + "");
}

或任何与此有关的事情,看它是否有效