Jonathan Andersson
Jonathan Andersson

Reputation: 1057

How to improve the scroll speed of my listview

Edit: Ok, i took the advice given in the answers and the difference is huge! I've replaced my SeriesAdapter in the post with the new one. For one a know make the calculations with in the sql query (to know total number of episodes and totalt numer of watched episodes). I also store the bitmap in a hashmap once it has been loaded so that it don't have to load twice, I'm looking in to some other solution as I'm afraid of OutOfMemoryException.

I am new to android and i want to display an listview with images that i have stored on the external storage.

The images are downloaded earlier and are now as I said stored in the external storage, here is an example of the images http://thetvdb.com/banners/graphical/80348-g32.jpg and I compress the images to 80% when saving them to save some space.

I have tried several methods to make the listview scroll smooth but I'm clearly in over my head here. I have provided my layout for the list items and my adapter in case I do something strange here.

I would appreciate any tips and tricks that would improve my listview.

SeriesAdapter:

public static class SeriesAdapter extends ArrayAdapter<Series> {

    static class viewHolder
    {
        ImageView image;
        TextView information;
        String seriesId;
        String season;
        ProgressBar progress;
        TextView txtSmallView;
    }

    private final Context context;
    private final ArrayList<Series> series;
    private DateHelper dateHelper;
    private final DatabaseHandler db;
    Object mActionMode;
    int resource;

    public SeriesAdapter(Context context, int resource, ListView lv, ArrayList<ExtendedSeries> objects)
    {
        super(context, resource, objects);
        this.context = context;
        this.series = objects;
        this.resource = resource;
        db = new DatabaseHandler(context);
        dateHelper = new DateHelper();  

        cache = new HashMap<String, Bitmap>();
    }



    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {

        viewHolder holder;
        ExtendedSeries s = series.get(position);

        if(convertView == null)
        {
            convertView = View.inflate(context, resource, null);
            holder = new viewHolder();

            holder.image = (ImageView)convertView.findViewById(R.id.imgSeriesImage);
            holder.information = (TextView)convertView.findViewById(R.id.txtUpcomingEpisode);
            holder.progress = (ProgressBar)convertView.findViewById(R.id.pgrWatched);                       

            convertView.setTag(holder);
        }
        else
        {
            holder = (viewHolder)convertView.getTag();
        }


        if(s != null)
        {
            holder.seriesId = s.getImage();


            convertView.setTag(R.string.homeactivity_tag_id,s.getID());
            convertView.setTag(R.string.homeactivity_tag_seriesid,s.getSeriesId());

            holder.progress.setMax(s.getTotalEpisodes());
            holder.progress.setProgress(s.getWatchedEpisodes());
            holder.image.setImageBitmap(getBitmapFromCache(s.getImage()));
            holder.information.setText(s.getNextEpisodeInformation().equals("") ? context.getText(R.string.message_show_ended) : s.getNextEpisodeInformation());        

        }


        return convertView;

    }

Listitem layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<ImageView
    android:id="@+id/imgSeriesImage"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:focusable="false"
    android:scaleType="centerCrop"
    android:src="@drawable/noimage" />

<RelativeLayout
    android:id="@+id/relProgressView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:focusable="false"
    android:orientation="vertical" >

    <ProgressBar
        android:id="@+id/pgrWatched"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="21dp"
        android:max="100"
        android:progress="50"
        android:progressDrawable="@drawable/progressbar" />

    <TextView
        android:id="@+id/txtUpcomingEpisode"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusable="false"
        android:padding="3dp"
        android:scrollHorizontally="true"
        android:scrollbars="none"
        android:shadowColor="@android:color/black"
        android:shadowDx="1"
        android:shadowDy="1"
        android:shadowRadius="1"
        android:textAllCaps="true"
        android:textColor="#ffffffff"
        android:textSize="11sp"
        android:textStyle="normal|bold"
        android:typeface="normal" />
</RelativeLayout>

Activity layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ListView
        android:id="@+id/lstMySeries"
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        android:longClickable="true"
        android:divider="#000000"
         />

Upvotes: 2

Views: 2157

Answers (2)

confucius
confucius

Reputation: 13327

I dont know why your code are doing an IO operation in the getView() method . this is an expensive operation ,can't you make it a field in the DB ??? can't you calcaulated else where ??? perhaps in the data loader i.e where you load the series ,.

Upvotes: 0

cjk
cjk

Reputation: 46425

The getView method needs to be as light as possible as this is called for every item in the row when it is shown onscreen.

You already implement the viewHolder pattern which is good, but you also need to preprocess your "watched episode" logic so you are not looping and counting in the display code. You also need to do the db.GetAiredEpisodes call outside of this method call.

Upvotes: 2

Related Questions