Search code examples
androidandroid-cursoradapter

Cursor Adapter Data binding issue


I have used cursor adapter in my app. The adapter is bound to a listfragment. The listview is displaying correct. In my adapter view, I have two textviews and an imageview. Over the imageview, I added onClickListener. The listview is displaying properly. But, when I click on the imageview at any index in the list, instead of getting data for that index, it is getting data for some other index.

For e.g, if I click on imageview in the item 2 of the listview(the item position in the list will be 1), instead of getting data for that position from the cursor, it is getting data for some other position(5, 6, 0, etc.). I searched alot for this issue but couldn't find any relevant answer. Below, is my CursorAdapter's code

public class ClientListAdapter extends CursorAdapter {
    private static final String TAG = "ClientListAdapter";
    private final int PRIMARY_PHOTO_INDEX = 1;
    private final int LAST_NAME_INDEX = 2;
    private final int FIRST_NAME_INDEX = 3;
    private final int CLIENT_GUID_INDEX = 4;
    private NavigateToClientDetailListener mClientDetailListener;

    public ClientListAdapter(Context context, Cursor c, int flags) {
        super(context, c, flags);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        ViewHolder holder = new ViewHolder();
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View v = inflater.inflate(R.layout.client_list_adapter, parent, false);
        holder.imgClientPhoto = (ImageView) v.findViewById(R.id.imgClientPhoto);
        holder.txtFirstName = (TextView) v.findViewById(R.id.txtFirstName);
        holder.txtLastName = (TextView) v.findViewById(R.id.txtLastName);
        holder.navigateNext = (ImageView) v.findViewById(R.id.navigateNext);
        v.setTag(holder);
        return v;
    }

    @Override
    public void bindView(final View view, final Context context,
            final Cursor cursor) {
        ViewHolder holder = (ViewHolder) view.getTag();

        // byte[] imgByteArray = cursor.getBlob(PRIMARY_PHOTO_INDEX);

        holder.txtLastName.setText(cursor.getString(LAST_NAME_INDEX));
        holder.txtFirstName.setText(cursor.getString(FIRST_NAME_INDEX));

        holder.navigateNext.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Log.e(TAG, "btnNext onCLick "+" Client Name: "+cursor.getString(LAST_NAME_INDEX)+" "+cursor.getString(FIRST_NAME_INDEX));
                navigateToClientDetail(cursor.getString(CLIENT_GUID_INDEX));
            }
        });
    }

    static class ViewHolder {
        ImageView imgClientPhoto, navigateNext;
        TextView txtLastName, txtFirstName;
    }

    private void navigateToClientDetail(String clientGuid) {
        mClientDetailListener.gotoClientDetail(clientGuid);
    }

    public void setNavigateToClientDetailListener(
            NavigateToClientDetailListener mClientDetailListener) {
        this.mClientDetailListener = mClientDetailListener;
    }
}

Solution

  • Got the solution. I forgot that bindView gets called for each item. So, in previous case, cursor.getString(CLIENT_GUID_INDEX) was always returning the guid id of last item in the cursor. I changed my code as:

    final String clientGuid = cursor.getString(CLIENT_GUID_INDEX);
    
    holder.navigateNext.setOnClickListener(new View.OnClickListener() {
    
        @Override
        public void onClick(View v) {
           navigateToClientDetailFragment(clientGuid);
        }
    });
    

    I would like to have comments if anyone feels my assumption is wrong and possible reason is something else as I am not very much familiar with cursor adapter:).