我只有一种布局夸大了。将新项目添加到列表视图后,我按如下方式捕获了此异常,当我尝试向上滚动时会发生这种情况。如果getViewTypeCount()返回1,则我会有一个很大的problem
D/countOfType﹕ getViewTypeCount() = 8
D/countOfType﹕ getViewTypeCount() = 7
java.lang.ArrayIndexOutOfBoundsException: length=9; index=9
at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:6563)
这是我的适配器的代码
@Override
public View getView(final int position, final View convertView, ViewGroup parent) {
View row = convertView;
final Tracker tracker = trackerList.get(position);
final Thread thread = tracker.getThread();
ViewHolder holder;
long days,hours,minutes,seconds;
long eDays,eHours,eMins,eSecs;
if(row == null){
row = inflater.inflate(R.layout.list_item,parent,false);
holder = new ViewHolder(row);
row.setTag(holder);
}else {
holder = (ViewHolder) row.getTag();
}
//изнальначальный вид
final ViewHolder finalHolder = holder;
finalHolder.start.setVisibility(View.VISIBLE);
finalHolder.stop.setVisibility(View.GONE);
finalHolder.name.setText(tracker.getName());
Log.d("TrackAdapter","getView() = "+position);
if(tracker.getElapsedTime()!=0 && tracker.getLimitTime()==0){//если прошедшее время !=0 и таймер без лимита
days = tracker.getElapsedTime()/86400000;
hours = (tracker.getElapsedTime()/3600000)%24;
minutes = (tracker.getElapsedTime()/60000)%60;
seconds = (tracker.getElapsedTime()/1000)%60;
if(days!=0)
finalHolder.days.setText(Util.concat(days <= 9 ? 0 : "", days));
if(hours!=0)
finalHolder.hours.setText(Util.concat(hours <=9 ?0:"",hours));
if(minutes!=0)
finalHolder.minutes.setText(Util.concat(minutes<=9?0:"",minutes));
if(seconds!=0)
finalHolder.seconds.setText(Util.concat(seconds<=9?0:"",seconds));
}else{
if(tracker.getIsFinished()){//если таск закончен, дошел до лимита
hours = (tracker.getLimitTime()/3600000)%24;
minutes = (tracker.getLimitTime()/60000)%60;
seconds = (tracker.getLimitTime()/1000)%60;
finalHolder.start.setVisibility(View.GONE);
finalHolder.textFinish.setVisibility(View.VISIBLE);
finalHolder.stop.setVisibility(View.GONE);
if(seconds!=60)
finalHolder.seconds.setText(Util.concat(seconds<=9?0:"",seconds));
if(minutes!=60)
finalHolder.minutes.setText(Util.concat(minutes<=9?0:"",minutes));
if(hours!=24)
finalHolder.hours.setText(Util.concat(hours <= 9 ? 0 : "", hours));
}else{
if(tracker.getLimitTime()!=0){//если установлен лимит, но еще не дошел до конца
days = tracker.getLimitTime()/86400000;
hours = (tracker.getLimitTime()/3600000)%24;
minutes = (tracker.getLimitTime()/60000)%60;
finalHolder.textLimit.setVisibility(View.VISIBLE);
finalHolder.limHours.setVisibility(View.VISIBLE);
finalHolder.limDay.setVisibility(View.VISIBLE);
finalHolder.limMin.setVisibility(View.VISIBLE);
finalHolder.limDay.setText(Util.concat(days <= 9 ? 0 : "", days, ":"));
finalHolder.limHours.setText(Util.concat(hours <= 9 ? 0 : "", hours, ":"));
finalHolder.limMin.setText(Util.concat(minutes<=9?0:"",minutes));
eDays = (tracker.getElapsedTime() / 86400000);
eHours = (tracker.getElapsedTime()/3600000)%24;
eMins = (tracker.getElapsedTime()/60000)%60;
eSecs = (tracker.getElapsedTime()/1000)%60;
if(eSecs!=0)
finalHolder.seconds.setText(Util.concat(eSecs<=9?0:"",eSecs));
if(eMins!=0)
finalHolder.minutes.setText(Util.concat(minutes<=9?0:"",eMins));
if(eHours!=0)
finalHolder.hours.setText(Util.concat(hours<= 9 ? 0 : "", eHours));
if(eSecs!=0)
finalHolder.days.setText(Util.concat(days<= 9 ? 0 : "", eDays));
}else {
finalHolder.textLimit.setVisibility(View.GONE);
finalHolder.limHours.setVisibility(View.GONE);
finalHolder.limDay.setVisibility(View.GONE);
finalHolder.limMin.setVisibility(View.GONE);
}
}
}
if(tracker.getIsStart() && !tracker.getIsFinished()) {//если был стартован
finalHolder.start.setVisibility(View.GONE);
finalHolder.stop.setVisibility(View.VISIBLE);
}
tracker.setHolder(finalHolder);
View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btStart:
tracker.setStartTime(System.currentTimeMillis());
tracker.setIsStart(true);
tracker.setHolder(finalHolder);
finalHolder.start.setVisibility(View.GONE);
finalHolder.stop.setVisibility(View.VISIBLE);
if(tracker.getUpdateTime()==0)
thread.start();
else
tracker.getThread().start();
break;
case R.id.btStop:
tracker.setLastPause(tracker.getUpdateTime());
finalHolder.stop.setVisibility(View.GONE);
finalHolder.start.setVisibility(View.VISIBLE);
tracker.setIsStart(false);
break;
}
}
};
finalHolder.start.setOnClickListener(onClickListener);
finalHolder.stop.setOnClickListener(onClickListener);
return row;
}
@Override
public int getViewTypeCount() {
Log.d("countOfType","getViewTypeCount() = "+getCount());
if(getCount()==0)
return super.getViewTypeCount();
else
return getCount();
//return 1;
}
@Override
public int getItemViewType(int position) {
return position;
}
static class ViewHolder{
@InjectView(R.id.tvName) TextView name;
@InjectView(R.id.tvDays) TextView days;
@InjectView(R.id.tvHours) TextView hours;
@InjectView(R.id.tvMinutes) TextView minutes;
@InjectView(R.id.tvSeconds) TextView seconds;
@InjectView(R.id.btStart) ButtonFloatSmall start;
@InjectView(R.id.btStop) ButtonFloatSmall stop;
@InjectView(R.id.txtFinish) TextView textFinish;
@InjectView(R.id.txtLimit) TextView textLimit;
@InjectView(R.id.limDay) TextView limDay;
@InjectView(R.id.limHours) TextView limHours;
@InjectView(R.id.limMin) TextView limMin;
public ViewHolder(View view){
ButterKnife.inject(this,view);
}
}
最佳答案
TL; DR作为一般规则,对于if
中的每个getView(...)
,请确保有一个处理负数的else
,否则您将在视图中看到旧数据。
您似乎误解了getItemViewType(int position)
和getViewTypeCount()
的角色。 Here很好地说明了为什么以及如何使用它们。
在您的情况下,由于只有一种布局,因此不必实现这两种方法。如果您在视图中看到回收的数据,则getView(...)
方法中存在一些错误。使用数据填充视图时,请确保处理所有情况。
例如,假设您有一个项目列表,并且如果位置为偶数,则要显示红色背景,如果位置为奇数,则要显示蓝色。让我们还假设默认情况下您的视图具有红色背景。您可以这样实现getView(...)
:
@Override
public View getView(final int position, final View convertView, ViewGroup parent) {
if(convertView == null) {
//Inflate your view here
}
if(position % 2 != 1) {
//Only need to change background if we're odd, since it's red by default
convertView.setBackgroundColor(Color.BLUE);
}
}
乍一看,这似乎是一个不错的实现。但是,当您添加视图回收时,您会发现某些偶数视图最终可能带有蓝色背景。这样做的原因是因为您没有显式设置偶数视图的背景,因此它们将保持其在上一行中使用的颜色。更好的实现是:
@Override
public View getView(final int position, final View convertView, ViewGroup parent) {
if(convertView == null) {
//Inflate your view here
}
if(position % 2 != 1) {
convertView.setBackgroundColor(Color.BLUE);
} else {
//Set the background no matter what so we make sure our view reflects our data
convertView.setBackgroundColor(Color.RED);
}
}