Scrollable ListView with customized BaseAdapter is very slow

余生颓废 提交于 2019-12-23 02:55:34

问题


I have a customized BaseAdapter for my listView with this code:

public View getView(int position, View convertView, ViewGroup parent) {
  ViewHolder holder;
  if (convertView == null) 
  { 
  } 
  else 
  {
   holder = (ViewHolder) convertView.getTag();
  }
  convertView = mInflater.inflate(R.layout.user_submissions_customisation, null);
   holder = new ViewHolder();
   holder.JournalName = (TextView) convertView.findViewById(R.id.JournalName);
   holder.SubmissionTitle = (TextView) convertView.findViewById(R.id.SubmissionTitle);
   holder.SubmissionDate = (TextView) convertView.findViewById(R.id.SubmissionDate);
   holder.statusOk=(ImageView)convertView.findViewById(R.id.statusOkImage);
   holder.statusRejected=(ImageView)convertView.findViewById(R.id.statusRejectedImage);
   holder.statusProcessing=(ImageView)convertView.findViewById(R.id.statusProcessingImage);
   convertView.setTag(holder);

  ImageView statusOk=(ImageView)convertView.findViewById(R.id.statusOkImage);
  ImageView statusRejected=(ImageView)convertView.findViewById(R.id.statusRejectedImage);
  ImageView statusProcessing=(ImageView)convertView.findViewById(R.id.statusProcessingImage);

  MDPIActivity mdpi = new MDPIActivity();
  Context context =mdpi.getContext();
  LocalDatabase localDatabase = new LocalDatabase(context); //Instantiation of the DB
  int status = localDatabase.getSubmissionStatus(position+1);

  if (status==102 | status==19)
  {
      statusRejected.setVisibility(View.VISIBLE);
  }
  else
  {
      if (status==29)
      {
      statusOk.setVisibility(View.VISIBLE);
      }
      else
      {
          statusProcessing.setVisibility(View.VISIBLE);
      }
  }

  holder.JournalName.setText(submissionsArrayList.get(position).getJournalTitle()+"-"+submissionsArrayList.get(position).getID());
  holder.SubmissionTitle.setText(submissionsArrayList.get(position).getTitle());
  holder.SubmissionDate.setText(submissionsArrayList.get(position).getDate());

  return convertView;
}

 static class ViewHolder {
  TextView JournalName;
  TextView SubmissionTitle;
  TextView SubmissionDate;
  ImageView statusOk;
  ImageView statusRejected;
  ImageView statusProcessing;
 }

All works wel but the creation of the list on the display and the scrolling is pretty slow. I used this for éy list too:

android:fastScrollEnabled="true"
android:scrollingCache="true"
android:smoothScrollbar="true"

But the view changing from the previeous view to the listview is slow and the scrolling of the list too.


回答1:


All apart first do this thing
Move this code in the if condition when "convert view is null"

convertView = mInflater.inflate(R.layout.user_submissions_customisation, null); holder = new ViewHolder(); holder.JournalName = (TextView) convertView.findViewById(R.id.JournalName); holder.SubmissionTitle = (TextView) convertView.findViewById(R.id.SubmissionTitle); holder.SubmissionDate = (TextView) convertView.findViewById(R.id.SubmissionDate); holder.statusOk=(ImageView)convertView.findViewById(R.id.statusOkImage); holder.statusRejected=(ImageView)convertView.findViewById(R.id.statusRejectedImage); holder.statusProcessing=(ImageView)convertView.findViewById(R.id.statusProcessingImage); convertView.setTag(holder);

You are not using the adapter efficiently by coding as you did.
The above way will improve the performance for sure.

In nutshell, you must inflate the view for list row only when the convert view is null.
Also, different views in the row's view must be initialized with the convertView itself.
Then you set holder view as the tag to the convert view and the adapter will continuously provide the same view instead of inflating the new one every time.

Edit:You should move the code for getting the context and instantiating the db from the getView() method.
Just make a class level variable "mContext" in your adapter class and instantiate it in the constructor of your adapter by passing activity's context.
Then at same place (constructor) instantiate the db also.




回答2:


Why you always inflate a convertView? If view not null you should change view as you want and no inflate a view again. Use code like this on the top of getView

if (convertView == null) {
    convertView = mInflater.inflate(R.layout.user_submissions_customisation, null);
} else {
    //convertView  is already inflated. No inflate it again!
    holder = (ViewHolder) convertView.getTag();
}
holder = new ViewHolder();
holder.JournalName = (TextView) convertView.findViewById(R.id.JournalName);



回答3:


try this:

public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;

    if (convertView == null) 
      { 
         convertView = mInflater.inflate(R.layout.user_submissions_customisation, null);
         holder = new ViewHolder();
         holder.JournalName = (TextView) convertView.findViewById(R.id.JournalName);
         holder.SubmissionTitle = (TextView) convertView.findViewById(R.id.SubmissionTitle);
         holder.SubmissionDate = (TextView) convertView.findViewById(R.id.SubmissionDate);
         holder.statusOk=(ImageView)convertView.findViewById(R.id.statusOkImage);
         holder.statusRejected=(ImageView)convertView.findViewById(R.id.statusRejectedImage);
         holder.statusProcessing=ImageView)convertView.findViewById(R.id.statusProcessingImage);
         convertView.setTag(holder);
      } 
      else 
      {
       holder = (ViewHolder) convertView.getTag();
      }

   ...
}

This way,your initialization of holder's object would just be for first element of your list.then it will always be in else grabbing previous settings.



来源:https://stackoverflow.com/questions/9324181/scrollable-listview-with-customized-baseadapter-is-very-slow

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!