Custom BaseAdapter 上的第一项未显示在 Gridview 上,Gridview 上的 ClickListener 不起作用

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

我坐了两天就是为了搜索我的fragment的gridview和adapter的代码有什么问题。第一项没有显示在我的网格视图中。

这是我的片段代码

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;
        }
    }
}

如果您注意到了,我将布局的 onclickListener 放置在适配器中的 getView 内,因为我无法在 GridView 上使用 onItemClickListener。它不工作。无论我在互联网上看到什么解决方案,它都不起作用。

gridview 仍然会跳过适配器上的第一项。我使用信息日志来确保数据库和 arraylist 工作正常。它工作正常。只是griview我觉得有问题

问题: 使用 cursor.moveToFirst() 光标移动到第一项,然后在捕获第一个 item/row 之前调用 cursor.moveToNext()在下面的 while 块中。这让您在有机会将第一个添加到适配器之前转到第二个 item/row。

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");
}

解法:

调用cursor.moveToNext()

前需要执行while块内的代码

使用do/while而不是while以便迭代代码在检查while条件

之前运行
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");
}