2015-06-09 100 views
1

我只有一個充氣的佈局。在向listview添加新項目後,我如下捕獲這個exeption,當我嘗試滾動時,它會發生。如果getViewTypeCount()將返回1,我將有一個大的problem爲什麼getViewTypeCount()返回不同的值?

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); 
    } 
} 
+0

「爲什麼getViewTypeCount()返回不同的值?「 - 因爲你寫它返回不同的值。如果你想要它有一個固定值,返回一個固定值,而不是'getCount()'。 – CommonsWare

+0

@CommonsWare 你是對的,但如果我將返回1,我的項目將與滾動 –

+0

混合「我的項目將混合滾動」 - 這將指示您的'getView()'實現中的錯誤。修復錯誤。 – CommonsWare

回答

1

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); 
    } 
} 
相關問題