Video thumbnail arrayadopter is slow on scroll
android, android-arrayadapter, thumbnails, video
Solution
The listview is lagging because you are creating new Thumbnails in getView() every time. There is just no caching or re-use. As the use scrolls up/down , getView() is called and time consuming process of creating thumbnails happen, hence the lag. You will also run `Out of Memory` soon.
Create and keep an Array of Bitmaps, with the same length as the number of elements in the datasource and store your thumbnails in the array. Take out the bitmap from the array for that particular position inside `getView()`. This should considerably increase the performance.
EDIT I have added a Hasmap of bitmaps to demonstrate the re-use.
public MyAdapter(Activity context, String[] names) {
super(context, R.layout.rowlayout, names);
this.context = context;
this.names = names;
filePath = Environment.getExternalStorageDirectory() + dirNameSlash;
formatter = new SimpleDateFormat(dateFormat);
cacheBitmap = new HashMap<String, Bitmap>(names.length);
initCacheBitmap();
}
private void initCacheBitmap() {
for(String string:names)
cacheBitmap.put(string, ThumbnailUtils.createVideoThumbnail(filePath+string, Thumbnails.MICRO_KIND));
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.rowlayout, null);
ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) rowView.findViewById(R.id.label);
viewHolder.image = (ImageView) rowView.findViewById(R.id.icon);
rowView.setTag(viewHolder);
}
ViewHolder holder = (ViewHolder) rowView.getTag();
// Video file name
String s = names[position];
holder.text.setText(s);
holder.image.setImageBitmap(cacheBitmap.get(s));
return rowView;
}}
Problem
I have created an adopter to display images thumbnail of video form the specific folder but when I scroll it lags a little but why is that? Below is the code: Main activity class ``` public class TestvideolistingActivity extends ListActivity { String filename = null; String filePath = null; String dirNameSlash = "/videotest/"; String dirName = "videotest"; String path = Environment.getExternalStorageDirectory() + dirNameSlash ; String[] values; String deleteFile ; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // getting the own adapter getInit(); } @Override protected void onResume() { getInit(); super.onResume(); } public void getInit() { deleteFile = null; values = getFilesArrayFromSdCard(); setListAdapter(new MyAdapter(this, values)); } protected void onListItemClick(ListView l, View v, int position, long id) { String item = (String) getListAdapter().getItem(position); Intent intentToPlayVideo = new Intent(Intent.ACTION_VIEW); intentToPlayVideo.setDataAndType(Uri.parse(path + item), "video/*"); startActivity(intentToPlayVideo); } public String[] getFilesArrayFromSdCard() { String[] fileList = null; File videoFiles = new File(path); if (videoFiles.isDirectory()) { fileList = videoFiles.list(); } return fileList; } } this the adopter class which show;s the text and the thumbnail public class MyAdapter extends ArrayAdapter<String> { private final Activity context; private final String[] names; private String filePath = null; private Bitmap bmThumbnail; private String dateFormat = "dd/MM/yyyy HH:mm:ss"; private SimpleDateFormat formatter; private String filename; String dirNameSlash = "/videotest/"; static class ViewHolder { // value for the name of the file public TextView text; // video file thumbnail public ImageView image; } public MyAdapter(Activity context, String[] names) { super(context, R.layout.rowlayout, names); this.context = context; this.names = names; filePath = Environment.getExternalStorageDirectory() + dirNameSlash; formatter = new SimpleDateFormat(dateFormat); } @Override public View getView(int position, View convertView, ViewGroup parent) { View rowView = convertView; if (rowView == null) { LayoutInflater inflater = context.getLayoutInflater(); rowView = inflater.inflate(R.layout.rowlayout, null); ViewHolder viewHolder = new ViewHolder(); viewHolder.text = (TextView) rowView.findViewById(R.id.label); viewHolder.image = (ImageView) rowView.findViewById(R.id.icon); rowView.setTag(viewHolder); } ViewHolder holder = (ViewHolder) rowView.getTag(); // Video file name String s = names[position]; holder.text.setText(s); bmThumbnail = ThumbnailUtils.createVideoThumbnail(filename, Thumbnails.MICRO_KIND); holder.image.setImageBitmap(bmThumbnail); return rowView; } } ``` This is the error by using Akhil code ``` 04-04 18:09:59.078: E/AndroidRuntime(10625): FATAL EXCEPTION: main 04-04 18:09:59.078: E/AndroidRuntime(10625): java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0 04-04 18:09:59.078: E/AndroidRuntime(10625): at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:257) 04-04 18:09:59.078: E/AndroidRuntime(10625): at java.util.ArrayList.get(ArrayList.java:311) 04-04 18:09:59.078: E/AndroidRuntime(10625): at com.koders.testvideolisting.MyPerformanceArrayAdapter.getView(MyPerformanceArrayAdapter.java:111) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.widget.AbsListView.obtainView(AbsListView.java:1315) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.widget.ListView.makeAndAddView(ListView.java:1727) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.widget.ListView.fillDown(ListView.java:652) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.widget.ListView.fillFromTop(ListView.java:709) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.widget.ListView.layoutChildren(ListView.java:1580) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.widget.AbsListView.onLayout(AbsListView.java:1147) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.view.View.layout(View.java:7034) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.widget.FrameLayout.onLayout(FrameLayout.java:333) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.view.View.layout(View.java:7034) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1249) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1125) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.widget.LinearLayout.onLayout(LinearLayout.java:1042) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.view.View.layout(View.java:7034) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.widget.FrameLayout.onLayout(FrameLayout.java:333) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.view.View.layout(View.java:7034) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.view.ViewRoot.performTraversals(ViewRoot.java:1049) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.view.ViewRoot.handleMessage(ViewRoot.java:1744) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.os.Handler.dispatchMessage(Handler.java:99) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.os.Looper.loop(Looper.java:144) 04-04 18:09:59.078: E/AndroidRuntime(10625): at android.app.ActivityThread.main(ActivityThread.java:4937) 04-04 18:09:59.078: E/AndroidRuntime(10625): at java.lang.reflect.Method.invokeNative(Native Method) 04-04 18:09:59.078: E/AndroidRuntime(10625): at java.lang.reflect.Method.invoke(Method.java:521) 04-04 18:09:59.078: E/AndroidRuntime(10625): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 04-04 18:09:59.078: E/AndroidRuntime(10625): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 04-04 18:09:59.078: E/AndroidRuntime(10625): at dalvik.system.NativeStart.main(Native Method) ```