Reputation: 5064
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
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
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