Tushar Monirul
Tushar Monirul

Reputation: 5064

Does not scroll smooth when fastScrollEnabled is used in ListView

I am using a listview in my app. I made a custom adapter and used viewholder design pattern. The problem is when I scroll the listview by swiping its scroll smoothly but when I scroll it by dragging the fastscroll thumb it lags too much. It freezes for some moment frequently. I have checked other application in my phone such as default music player, the listview scroll like winds no matter how i scroll it. I am not using any imageview in the list, just three textviews per row.

here is the full code:

public class CustomListViewSongs extends BaseAdapter{


    private Context context;

    private ArrayList songs, artist, songduration;


    private static LayoutInflater inflater = null;

    public CustomListViewSongs(Context context, ArrayList songs, ArrayList artist, ArrayList songDuration){
        this.context = context;
        this.songs = songs;
        this.artist = artist;
        this.songduration = songDuration;



    }

    @Override
    public int getCount() {
        return songs.size();
    }

    @Override
    public Object getItem(int position) {
        return songs.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }



    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        Holder holder;
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rowView = convertView;
        if(rowView == null){
            rowView = inflater.inflate(R.layout.customlistviewsongssinglerow, null);
            holder = new Holder();
            holder.songTitle = (TextView) rowView.findViewById(R.id.songTitle);
            holder.songTitleArtist = (TextView) rowView.findViewById(R.id.songTitleArtist);
            holder.songDuration = (TextView) rowView.findViewById(R.id.songDuration);
            rowView.setTag(holder);
        }else{
            holder = (Holder) rowView.getTag();
        }
        holder.songTitle.setText("" + songs.get(position));
        holder.songTitleArtist.setText("" + artist.get(position));
        long duration = Long.parseLong("" + songduration.get(position));
        int seconds = (int) ((duration / 1000) % 60);
        long minutes = ((duration - seconds) / 1000) / 60;
        if (seconds < 10) {
            holder.songDuration.setText("" + minutes + ":0" + seconds);
        } else {
            holder.songDuration.setText("" + minutes + ":" + seconds);
        }
        return rowView;
    }

    public class Holder {
        TextView songTitle, songTitleArtist, songDuration;
        int position;

    }


}

and the listview xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"
    android:layout_height="match_parent">
        <ListView
            android:fastScrollEnabled="true"
            android:fastScrollAlwaysVisible="false"
            android:background="@android:color/transparent"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/listView"/>
</RelativeLayout>

and calling it:

    public class f1 extends Fragment {

    private MainActivity f = new MainActivity();
    private ListView lv;
    private View view;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.f1, container, false);
        populate();
        return view;
    }
    private void populate() {
        lv = (ListView) view.findViewById(R.id.listView);
        lv.setAdapter(new CustomListViewSongs(getActivity(), f.songs, f.artist, f.songsDuration));
    }

}

Upvotes: 0

Views: 586

Answers (2)

gdaramouskas
gdaramouskas

Reputation: 3747

The getView() method is being called for every item in your listview. It seems that you are doing a lot of view inflations and processing in your getView() method. Refactor this method for smoother performance. Try minimize the code that is executing within the method, for as you scroll down the system might need more memory and run a garbage clean in your previous views thus when you move up and down the getView() is called again. Plus why do you View rowView = convertView;? The convertView is the old view that must be reused if possible, to avoid performance issues. For more information check here.

Upvotes: 0

SigmaFive
SigmaFive

Reputation: 13

You can try moving this line

inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

inside when rowView == null. It's being called too many times unnecessarily since the views are being recycled, and the only place it's being used is inside that if condition.

Not sure if that's the main issue though.

You could also test to see if your calculation on song duration is causing the the lag by just setting a default value to the textView and commenting out the the calculations. If you see an improvement then you should do the calculations in a background thread.

Edit: Just noticed that your view holder pattern should be implemented as a static class. Replace your code with this

static class Holder {
        TextView songTitle, songTitleArtist, songDuration;
        int position;
}

Upvotes: 1

Related Questions