Keith
Keith

Reputation: 4204

How can I cache custom views in my ListView Adapter?

In my ImageAdapter (extends BaseAdapter), each View is a custom view I called ImageTapView. It's a separate class that extends RelativeLayout with its own layout file that starts with a <merge>. This class contains all the click listeners, loaders for the images that each ImageTapView downloads and displays from the internet, as well as animations that happen on click.

Here's my ImageAdapter constructor:

public class ImageAdapter extends BaseAdapter {
    private Context context;
    private JSONArray posts;
    private String baseUrl;
    private HashMap views = new HashMap();

    public ImageAdapter(Context _context, JSONArray _posts, String _baseUrl){
        context = _context;
        posts = _posts;
        baseUrl = _baseUrl;            
    }

    ...etc
}

In my ImageAdapter.getView everything works fine if I do something like:

public View getView(int position, View convertView, ViewGroup parent){
    // create new imageTapView
    JSONObject thisPost = posts.getJSONObject(position);
    convertView = new ImageTapView(context, thisPost);
    return convertView;
}

But this means Android is creating a new ImageTapView every time it calls getView instead of just replacing the data in the already inflated view. I think it'd be way harder to go in and replace each field and reset the animations on getView, not to mention, I'd like the user to see where in their interaction with ImageTapView they left off (e.g. zoomed in on an image or in the middle of an animation).

I tried saving each view to a HashMap called views:

public View getView(int position, View convertView, ViewGroup parent){
    if(views.containsKey(position)) return (ImageTapView) views.get(position);
    // create new imageTapView
    JSONObject thisPost = posts.getJSONObject(position);
    convertView = new ImageTapView(context, thisPost);
    views.put(position, convertView);
    return convertView;
}

But I get some very strange behavior. ImageTapViews that are on, say, step 2 of 3 steps of interaction (start state, zoomed state, information overlay shown state), things get really strange. They don't seem to pick up where they left off and they don't respond to clicks the proper way a fresh ImageTapView would.

So is there a standard way of caching objects or custom objects in a ListView? Should I be extending ArrayAdapter instead, or would my problem be the same in the getView function?

Thanks in advance!

Upvotes: 1

Views: 956

Answers (2)

Nooh
Nooh

Reputation: 1546

try this ,you need create extra method setPost() to set post

 public View getView(int position, View convertView, ViewGroup parent){
      // create new imageTapView
      JSONObject thisPost = posts.getJSONObject(position);
      if(convertView==null)
            convertView = new ImageTapView(context, thisPost);
      else{
      ((ImageTapView)convertView).setPost(thisPost); 
      }
     return convertView;
 }

Upvotes: 2

Hareshkumar Chhelana
Hareshkumar Chhelana

Reputation: 24848

Try this way,hope this will help you to solve your problem.

  1. Custom item layout for your adapter.

row.xml

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

    <packageName.ImageTapView>
        android:id="@+id/imageTapView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
    </packageName.ImageTapView>
</LinearLayout>
  1. inflate custom row layout in adapter.

    public class ImageAdapter extends BaseAdapter {

    private Context context;
    private JSONArray posts;
    private String baseUrl;
    private HashMap views = new HashMap();
    
    public ImageAdapter(Context _context, JSONArray _posts, String _baseUrl){
        context = _context;
        posts = _posts;
        baseUrl = _baseUrl;
    }
    
    static class ViewHolder
    {
        ImageTapView imageTapView;
    }
    
    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
        if (convertView == null) {
            viewHolder = new ViewHolder();
            convertView = LayoutInflater.from(_context).inflate(R.layout.row, null);
            viewHolder.imageTapView = (ImageTapView) convertView.findViewById(R.id.imageTapView);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        viewHolder.imageTapView.setPost(posts.getJSONObject(position));
        return convertView;
    }
    
    ...etc
    

    }

Upvotes: 0

Related Questions