2

I am programming a VR Android application and using a custom listview to display images to the user. The listview, for whatever reason, is incredibly laggy when scrolling. I've looked over many tutorials on how to speed up the listview but I can't seem to figure out what I'm doing wrong. I've tried decreasing the size of the imagebuttons, disabled the scroll cache, and many other things. Note: I don't think the problem is the picasso call, because when I comment it out, it is still slow when scrolling.

My XML for the custom layout is:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="170dp"
android:padding="10dp">
<ImageButton
    android:layout_width="fill_parent"
    android:layout_height="150dp"
    android:id="@+id/redirect_btn"
    android:longClickable="false"
 />


</LinearLayout>

The code for the custom listview is here:

public class MyCustomAdapter extends BaseAdapter
{
private Activity activity;
private String[] listOfVideoNames;
private String[] listOfVideoTileImageURLs;
private VrVideoInfo[] listOfVrVideoInfo;
private Context context;

private static LayoutInflater inflater = null;

public MyCustomAdapter(String[] listOfVideoNames, String[] listOfVideoTileImages, VrVideoInfo[] vrList, Activity activity, Context context) {
    this.listOfVideoNames = listOfVideoNames;
    listOfVideoTileImageURLs = listOfVideoTileImages;
    this.context = context;
    this.activity = activity;
    listOfVrVideoInfo = vrList;

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

@Override
public int getCount() {
    return listOfVideoNames.length;
}

@Override
public Object getItem (int pos) {
    return listOfVideoNames[pos];
}

@Override
public long getItemId(int pos) {
    return 0;
    // return 0 if your list items do not have an Id variable
}
public class Holder {
    ImageButton imageButton;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    final Holder holder;
    if(convertView == null)
    {
        holder = new Holder();
        convertView = inflater.inflate(R.layout.custom_list_layout, parent, false);
        holder.imageButton = (ImageButton) convertView.findViewById(R.id.redirect_btn);

        convertView.setTag(holder);

    }
    else
    {
        holder = (Holder)convertView.getTag();
    }

    Picasso.with(context).load(listOfVideoTileImageURLs[position])
    .into(holder.imageButton);
    holder.imageButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            Intent intent = new Intent(activity, VideoViewer.class);
            intent.putExtra("video_title", listOfVideoNames[position]);
            activity.startActivity(intent);
        }
    });
    return convertView;
}

and just in case it is relevant, here is what calls the custom listview:

public class MenuActivity extends Activity {

// string adapter that will handle the data of the list view
MyCustomAdapter adapter;
String[] vrVideoTitles = null;

String[] videoTileImageListURLs = null;
ArrayList<VrVideoInfo> videoInfo;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.menu_activity);


    videoInfo = getIntent().getParcelableArrayListExtra("rData");
    vrVideoTitles = new String[videoInfo.size()];
    videoTileImageListURLs = new String[videoInfo.size()];




    for (int i = 0; i < videoInfo.size(); i++) {
        vrVideoTitles[i] = videoInfo.get(i).GetTitle();
    }

    for(int i = 0; i < videoInfo.size(); i++)
    {
        videoTileImageListURLs[i] = videoInfo.get(i).GetImageURl();
    }

    VrVideoInfo[] info = videoInfo.toArray(new VrVideoInfo[videoInfo.size()]);

    //instantiate custom adapter
    adapter = new MyCustomAdapter(vrVideoTitles,    
    videoTileImageListURLs,info, this, this);

    //handle listview and assign adapter
    ListView lView = (ListView) findViewById(R.id.list_container);
    lView.setOverScrollMode(View.OVER_SCROLL_NEVER);
    lView.setScrollingCacheEnabled(false);
    lView.setDrawingCacheEnabled(false);
    lView.setAdapter(adapter);
}



}

Any information or tips would be very helpful and appreciated.

2 Answers2

0

make your viewholder static, non-static inner classes also have reference to their containing class and it is not a memory efficient implementation.

NIPHIN
  • 1,071
  • 1
  • 8
  • 16
  • :D, nice please add a comment specifying the reason for downvote. reference http://stackoverflow.com/questions/10864853/when-exactly-is-it-leak-safe-to-use-anonymous-inner-classes https://developer.android.com/training/improving-layouts/smooth-scrolling.html – NIPHIN Jun 19 '16 at 04:43
  • it will not improve the performance at all. how many `Holder` objects do you expect to be created? do you know what is the size in bytes of each `Holder` instance? making it "static" just removes one reference per each `Holder` instance, BTW the OP should not use that "holder" stuff at all as in 99% cases it just make the code more complex and has no performance impact – pskink Jun 19 '16 at 05:37
  • Viewholder pattern is used to avoid expensive findviewbyid() operation, so using holder pattern definitely improves performance – NIPHIN Jun 19 '16 at 05:47
  • [here](https://developer.android.com/reference/android/widget/BaseAdapter.html) you have all google's adapters extending `BaseAdapter`, please show me at least one that uses holder pattern, if you do that i will agree the holder pattern is usefull, also when we are talking about `findViewById` see [this](http://daniel-codes.blogspot.com/2013/11/is-findviewbyid-slow.html) – pskink Jun 19 '16 at 05:51
  • please refer to https://developer.android.com/training/improving-layouts/smooth-scrolling.html . In fact the new listing solution Recyclerview have incorporated this technique in its architecture.https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html . – NIPHIN Jun 19 '16 at 05:58
  • again, is there any google's `BaseAdapter` that uses it? no, there is not, some time ago i made some measurements and when using holder pattern i saved 1ms or so when scrolling 1000 items list view from the top to the bottom, **ONE millisecond**, does it pay off? definitely no, at least in majority of cases – pskink Jun 19 '16 at 06:16
  • do a fast scrolling and see the difference it causes with your own eye, when such operation are performed findviewbyid are really a bottle neck especially if the list item viewgroup has multiple child elements. – NIPHIN Jun 19 '16 at 06:19
  • i did the measurements of `findviewbyid`, and as i said i saved **0.001 second**, what my eye can do in 1ms? just call findviewbyid 1000 times (not in a loop but side by side) and measure the time spent and you will see, did you see the results [here](http://daniel-codes.blogspot.com/2013/11/is-findviewbyid-slow.html)? – pskink Jun 19 '16 at 06:26
  • I made the viewholder static but I don't see an increase in speed unfortunately :/ – Brandan Jablonski Jun 19 '16 at 17:02
0

I figured it out after awhile. Apparently, another intern where I'm working put an image view on top of the list view and I didn't see it because he set it to be transparent. So in other words, don't put image views on top of list views.