Android开发经验分享-GridView、ListView内容错乱

在使用GridView、ListView的过程中遇到内容错乱的问题,费了较长时间才找到问题的根源,特地总结一下。

1、在自定义adapter中没有给每一项都设置内容导致内容错乱:

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    if( null == convertView ){
        mGridHolder = new GridHolder( );
         
    convertView = mLayoutInflater.inflate( R.layout.view_log_word_item_layout, null );
     
    mGridHolder.mBackTopLayout = (LinearLayout)convertView.findViewById( R.id.logItemTopLayoutId);
    mGridHolder.mBackBottomLayout = ( RelativeLayout )convertView.findViewById( R.id.logItemBottomLayoutId );
    mGridHolder.mRightWordTxt = ( TextView )convertView.findViewById( R.id.rightWordTxtId );
    mGridHolder.mUserWriteImg = ( ImageView )convertView.findViewById( R.id.userWordImgId );
    mGridHolder.mWriteResultImg = ( ImageView )convertView.findViewById( R.id.writeResultImgId );
    mGridHolder.mReasonTxt = ( TextView )convertView.findViewById( R.id.reasonTxtId );
    mGridHolder.mRightWordTxt.setTypeface( mTypeface );
     
      convertView.setTag( mGridHolder );
  }else{
    mGridHolder = ( GridHolder )convertView.getTag( );
  }
     
  showContent( mDictationInfoList.get( position ) );
     
  return convertView;
}
 
@SuppressWarnings("deprecation")
private void showContent( DictationInfo dictationInfo ){
    mGridHolder.mRightWordTxt.setText( dictationInfo.getmWord( ) );
    if( null != dictationInfo.getmDrawable( ) ){
        mGridHolder.mUserWriteImg.setBackgroundDrawable( dictationInfo.getmDrawable( ) );
         
        if( !TextUtils.isEmpty( dictationInfo.getDetailReason( ) ) ){
            mGridHolder.mReasonTxt.setText( dictationInfo.getDetailReason( ) );
        }else{
            mGridHolder.mReasonTxt.setText( "" );
        }
         
      setWriteResult( dictationInfo.getmWriteResult( ) );
    }else{
        // 没有为内容项为空的项设置内容
    }
}

上面是一个自定义adapter中的一段代码,在getView中为每一项设置内容时只处理了有内容的项,没有内容的项没有赋值,导致在滑动内容时内容错乱,分析发现这是由于使用了adapter的缓存机制导致的,正确的处理方式是需要为内容为空的项也要赋值,修改后的代码如下:

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    if( null == convertView ){
        mGridHolder = new GridHolder( );
         
    convertView = mLayoutInflater.inflate( R.layout.view_log_word_item_layout, null );
     
    mGridHolder.mBackTopLayout = (LinearLayout)convertView.findViewById( R.id.logItemTopLayoutId);
    mGridHolder.mBackBottomLayout = ( RelativeLayout )convertView.findViewById( R.id.logItemBottomLayoutId );
    mGridHolder.mRightWordTxt = ( TextView )convertView.findViewById( R.id.rightWordTxtId );
    mGridHolder.mUserWriteImg = ( ImageView )convertView.findViewById( R.id.userWordImgId );
    mGridHolder.mWriteResultImg = ( ImageView )convertView.findViewById( R.id.writeResultImgId );
    mGridHolder.mReasonTxt = ( TextView )convertView.findViewById( R.id.reasonTxtId );
    mGridHolder.mRightWordTxt.setTypeface( mTypeface );
     
      convertView.setTag( mGridHolder );
  }else{
    mGridHolder = ( GridHolder )convertView.getTag( );
  }
     
  showContent( mDictationInfoList.get( position ) );
     
  return convertView;
}
 
@SuppressWarnings("deprecation")
private void showContent( DictationInfo dictationInfo ){
    mGridHolder.mRightWordTxt.setText( dictationInfo.getmWord( ) );
    if( null != dictationInfo.getmDrawable( ) ){
        mGridHolder.mUserWriteImg.setBackgroundDrawable( dictationInfo.getmDrawable( ) );
         
        if( !TextUtils.isEmpty( dictationInfo.getDetailReason( ) ) ){
            mGridHolder.mReasonTxt.setText( dictationInfo.getDetailReason( ) );
        }else{
            mGridHolder.mReasonTxt.setText( "" );
        }
         
      setWriteResult( dictationInfo.getmWriteResult( ) );
    }else{
        mGridHolder.mUserWriteImg.setBackgroundResource( Color.TRANSPARENT );
        mGridHolder.mReasonTxt.setText( "" );
        mGridHolder.mWriteResultImg.setBackgroundResource( R.drawable.log_unknown );
        mGridHolder.mBackTopLayout.setBackgroundResource( R.drawable.log_item_wrong_top_background );
        mGridHolder.mBackBottomLayout.setBackgroundResource( R.drawable.log_item_wrong_bottom_background );
    }
}

2、在自定义adapter的getview方法中,每一项的内容加载时间过长导致内容错乱。

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    mViewHolder = new ViewHolder( );
 
    convertView = mLayoutInflater.inflate( R.layout.adapter_score_list_layout, null );
    mViewHolder.mScoreLayout = ( RelativeLayout )convertView.findViewById( R.id.scoreLayoutId );
    mViewHolder.mScoreLayout.setClickable( false );
    mViewHolder.mPositionTxt = ( TextView )convertView.findViewById( R.id.positionTxtId );
    mViewHolder.mUserNameTxt = ( TextView )convertView.findViewById( R.id.userNameTxtId );
    mViewHolder.mUserNameTxt.setTypeface( mTypeface );
    mViewHolder.mUserIconImg = ( ImageView )convertView.findViewById( R.id.userIconImgId );
    mViewHolder.mUserScoreTxt = ( TextView )convertView.findViewById( R.id.userScoreTxtId );
     
    showContent( position, mUserInfoList.get( position ) );
    return convertView;
}
 
private void showContent( int index, UserScoreInfo userInfo ){
    // 从网络获取头像
    handleUserIcon( mImageLoader, userInfo, mUserId );
    mViewHolder.mPositionTxt.setVisibility(TextView.VISIBLE);
    mViewHolder.mPositionTxt.setText( "第" + userInfo.getScoreRank( ) + "名" );
     
    if( mUserId.equals( userInfo.getUserId( ) ) ){
        mMyPosition = index;
        mViewHolder.mScoreLayout.setBackgroundResource( R.drawable.chinese_dictation_score_list_select );
    }else{
        mViewHolder.mScoreLayout.setBackgroundResource( R.drawable.chinese_dictation_score_list_normal );
    }
     
    String userName = userInfo.getNickName( );
    if( !TextUtils.isEmpty( userName ) ){
        userName = ( userName.length( ) > 10 )?( userName.substring(0, 7) + "..." ):userName;
    }else{
        userName = "佚名";
    }
     
    if( mUserId.equals( userInfo.getUserId( ) ) ){
        String localUserName = PersonalInfo.getCurrentUserName( mContext );
        mMyPosition = index;
        mViewHolder.mScoreLayout.setBackgroundResource( R.drawable.chinese_dictation_score_list_select );
        if( TextUtils.isEmpty( userName ) || ( !localUserName.equals( userName ) ) ){
            mViewHolder.mUserNameTxt.setText( localUserName  );
        }else{
            mViewHolder.mUserNameTxt.setText( userName  );
        }
             
    }else{
        mViewHolder.mScoreLayout.setBackgroundResource( R.drawable.chinese_dictation_score_list_normal );
        mViewHolder.mUserNameTxt.setText( userName );
    }
     
    mViewHolder.mUserScoreTxt.setText( StringUtils.getSplitByComma( userInfo.getScore( ) + "" ) );
}

上面是一个获取用户排名列表所自定义adapter中的一段代码,handleUserIcon方法是从网络获取用户头像,在滑动排名列表的时候发现用户头像会错乱,最后跟踪找到具体的原因是由于从网络获取用户头像耗时,正确的做法应该是在获取完成用户头像之后再通知adapter更新。


在使用gridview和listview的过程中,由于需要加载大量的内容,android建议我们采用viewholder的缓存机制,这样能够提高列表加载的效率,但是在使用的过程中一定要注意上面这两个问题,否则可能会让你很头疼。


你可能感兴趣的:(ListView,缓存机制,经验分享)