Search code examples
androidgridviewandroid-sqlitebaseadapterandroid-cursor

First item on Custom BaseAdapter doesn't show up at Gridview and ClickListener on Gridview doesn't work


I have been sitting for two days just to search and find what is wrong with the code of my fragment's gridview and adapter. the first item doesn't show up on my grid view.

This is my fragment code

public class FragmentConsumerHomeCanteen extends Fragment {

    private final String TAG = "ConsumerHomeCanteen";
    private GridView fchCanGrid;
    private ArrayList<CanteenRecordDetails> canteenRecordDetailsArrayList;
    private CanteenAdapter canteenAdapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_consumer_home_canteen, container, false);

        resourceVariables(view);

        canteenRecordDetailsArrayList = new ArrayList<>();
        canteenRecordDetailsArrayList.clear();
        CafeTreydDatabase cafeTreydDatabase = new CafeTreydDatabase(getActivity());
        Cursor cursor = cafeTreydDatabase.getCanteenForConsumerHomeCanteen(TAG);
        if (cursor.moveToFirst()) {
            while (cursor.moveToNext()) {
                int id = cursor.getInt(0);
                String name = cursor.getString(1);
                String open = cursor.getString(2);
                String close = cursor.getString(3);
                byte[] image = cursor.getBlob(4);

                canteenRecordDetailsArrayList.add(new CanteenRecordDetails(id, name, open, close, image));
                canteenAdapter = new CanteenAdapter(getActivity(), canteenRecordDetailsArrayList);
                canteenAdapter.notifyDataSetChanged();
            }
            fchCanGrid.setAdapter(canteenAdapter);
            Log.i(TAG, "Setting adapter to GridView Successful");
        } else {
            Log.i(TAG, "Cursor returns null");
        }

        return view;
    }

    private void resourceVariables(View view) {
        fchCanGrid = view.findViewById(R.id.fchCanGrid);
        Log.i(TAG, "Resourcing Successful");
    }

    private static class CanteenRecordDetails {

        private int id;
        private String name;
        private String open;
        private String close;
        private byte[] image;

        private CanteenRecordDetails(int id, String name, String open, String close, byte[] image) {
            this.id = id;
            this.name = name;
            this.open = open;
            this.close = close;
            this.image = image;
        }

        private int getId() {
            return id;
        }

        private String getName() {
            return name;
        }

        private String getOpen() {
            return open;
        }

        private String getClose() {
            return close;
        }

        private byte[] getImage() {
            return image;
        }

    }

    private static class CanteenAdapter extends BaseAdapter{

        private final Context context;
        private final ArrayList<CanteenRecordDetails> canteenRecordDetailsArrayList;
        private final LayoutInflater layoutInflater;

        private CanteenAdapter(Context context, ArrayList<CanteenRecordDetails> canteenRecordDetailsArrayList) {
            this.context = context;
            this.canteenRecordDetailsArrayList = canteenRecordDetailsArrayList;
            layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        @Override
        public int getCount() {
            return canteenRecordDetailsArrayList.size();
        }

        @Override
        public Object getItem(int position) {
            return canteenRecordDetailsArrayList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = layoutInflater.inflate(R.layout.layout_fragment_consumer_home_canteen, parent, false);
            }
            LinearLayout lfchcLL = convertView.findViewById(R.id.lfchCanLL);
            TextView lfchCanName = convertView.findViewById(R.id.lfchCanName);
            TextView lfchCanOpen = convertView.findViewById(R.id.lfchCanOpen);
            TextView lfchCanClose = convertView.findViewById(R.id.lfchCanClose);
            ImageView lfchCanImage = convertView.findViewById(R.id.lfchCanImage);

            CanteenRecordDetails canteenRecordDetails = canteenRecordDetailsArrayList.get(position);
            lfchCanName.setText(canteenRecordDetails.getName());
            lfchCanOpen.setText(String.format("OPEN: %s", canteenRecordDetails.getOpen()));
            lfchCanClose.setText(String.format("CLOSE: %s", canteenRecordDetails.getClose()));
            byte[] tempImage = canteenRecordDetails.getImage();
            Bitmap bitmap = BitmapFactory.decodeByteArray(tempImage, 0, tempImage.length);
            lfchCanImage.setImageBitmap(bitmap);

            lfchcLL.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(context, lfchCanName.getText(), Toast.LENGTH_SHORT).show();
                    String TAG = "ConsumerHomeCanteen";
                    try {
                        ((ActivityConsumerHome)context).setCanteenId(canteenRecordDetails.getId());
                        ((ActivityConsumerHome)context).setCanteenName(canteenRecordDetails.getName());
                        Navigation.findNavController(parent).navigate(R.id.action_fragmentConsumerHomeCanteen_to_fragmentConsumerHomeCategory);
                        Log.i(TAG, "Navigating to next Fragment");
                    } catch (Exception e) {
                        e.printStackTrace();
                        Log.i(TAG, "Failed to set canteenId");
                    }
                }
            });

            return convertView;
        }
    }
}

If you notice, I placed the onclickListener for the layout inside getView in the adapter because I can't use the onItemClickListener on GridView. it is not working. whatever solution I see on the internet, it doesn't work.

gridview still skips the first item on the adapter. I used info log to make sure that the database and arraylist work fine. It works fine. It's just the griview that has a problem I think.


Solution

  • Problem: The cursor moves to the first item using cursor.moveToFirst(), and then before catching the first item/row, you call cursor.moveToNext() in the while block below. And that makes you to go to the second item/row before having a chance to add the first to the adapter.

    if (cursor.moveToFirst()) {
        while (cursor.moveToNext()) {
            int id = cursor.getInt(0);
            String name = cursor.getString(1);
            String open = cursor.getString(2);
            String close = cursor.getString(3);
            byte[] image = cursor.getBlob(4);
    
            canteenRecordDetailsArrayList.add(new CanteenRecordDetails(id, name, open, close, image));
            canteenAdapter = new CanteenAdapter(getActivity(), canteenRecordDetailsArrayList);
            canteenAdapter.notifyDataSetChanged();
        }
        fchCanGrid.setAdapter(canteenAdapter);
        Log.i(TAG, "Setting adapter to GridView Successful");
    } else {
        Log.i(TAG, "Cursor returns null");
    }
    

    Solution:

    You need to execute the code inside the while block before calling cursor.moveToNext()

    Use do/while instead of while So that the iterated code runs before checking the while condition

    if (cursor.moveToFirst()) {
        do {
            int id = cursor.getInt(0);
            String name = cursor.getString(1);
            String open = cursor.getString(2);
            String close = cursor.getString(3);
            byte[] image = cursor.getBlob(4);
    
            canteenRecordDetailsArrayList.add(new CanteenRecordDetails(id, name, open, close, image));
            canteenAdapter = new CanteenAdapter(getActivity(), canteenRecordDetailsArrayList);
            canteenAdapter.notifyDataSetChanged();
        } while (cursor.moveToNext());
        
        fchCanGrid.setAdapter(canteenAdapter);
        Log.i(TAG, "Setting adapter to GridView Successful");
    } else {
        Log.i(TAG, "Cursor returns null");
    }