【问题标题】:First element pops up at the end of list in GridView adapter第一个元素在 GridView 适配器的列表末尾弹出
【发布时间】:2020-05-03 17:48:52
【问题描述】:

所以我有 DashboardFragment 带有项目的网格视图,当按下网格中的最后一个项目时,它会打开 新活动 以在将新类别添加到数据库后将其添加到数据库该活动 关闭,DashboardFragment 中的网格应在网格末尾更新为新元素。这是我想出的代码,它的问题是每当我添加新类别时,网格都会更新,但列表的第一个元素位于网格的末尾。当我重新启动应用程序时,新元素在最后,一切都按原样显示,因此它正确地将元素添加到数据库中。在调试器中,两个列表(一个在适配器中,一个在主类中)是相同的,并且最后带有新元素。我花了半天时间寻找解决方案,但我找不到导致此问题的原因。


public class DashboardFragment extends Fragment {

    private DashboardViewModel dashboardViewModel;
    List<Category> categories = new ArrayList<>();
    PieChart chart;

    CategoryAdapter adapter;

    DBHelper dbHelper;
    SQLiteDatabase database;


    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        dashboardViewModel = ViewModelProviders.of(this).get(DashboardViewModel.class);
        View root = inflater.inflate(R.layout.fragment_dashboard, container, false);
        setHasOptionsMenu(true);

        //-----Database
        dbHelper = new DBHelper(super.getContext());
        //-----Categories
        ParseCategories();
        final ExpandableHeightGridView gridView = (ExpandableHeightGridView) root.findViewById(R.id.category_grid);
        adapter = new CategoryAdapter(root.getContext(), categories);
        gridView.setAdapter(adapter);
        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (position == categories.size() - 1) {
                    startActivityForResult(new Intent(DashboardFragment.super.getContext(), CategoryCreation.class),1);

                }
            }
        });
        gridView.setExpanded(true);
        //-----Chart
        chart = (PieChart) root.findViewById(R.id.chart);
        setupPieChart();
        return root;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode==1){
            ParseCategories();
            adapter.updateCategoryList(categories);
        }
    }

    public void ParseCategories() {
        categories.clear();
        database = dbHelper.getWritableDatabase();
        Cursor c = database.rawQuery("select * from categories", null);
        c.moveToFirst();
        for (int i = 0; i < c.getCount(); i++) {
            int id = c.getInt(c.getColumnIndex("_id"));
            String name = c.getString(c.getColumnIndex("name"));
            double amount = c.getDouble(c.getColumnIndex("amount"));
            int imageId = c.getInt(c.getColumnIndex("iconId"));
            categories.add(new Category(id, name, amount, imageId));
            c.moveToNext();
        }
        categories.add(new Category(-1, "Add", -1, R.drawable.add_category_icon));
        c.close();
        database.close();
    }

    public class CategoryAdapter extends BaseAdapter {
        private Context context;
        private List<Category> categories;

        public CategoryAdapter(Context context, List<Category> cats) {
            this.context = context;
            this.categories = cats;
        }

        public View getView(int position, View convertView, ViewGroup parent) {

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

            View gridView;

            if (convertView == null) {

                gridView = new View(context);

                gridView = inflater.inflate(R.layout.dashboard_category_item, null);

                TextView nameView = (TextView) gridView.findViewById(R.id.category_name);
                ImageView imageView = (ImageView) gridView.findViewById(R.id.grid_item_image);
                TextView amountView = (TextView) gridView.findViewById(R.id.category_amount);

                nameView.setText(categories.get(position).getName());
                imageView.setImageResource(categories.get(position).getIconId());
                if (categories.get(position).getAmount() >= 0) {
                    amountView.setText("$" + categories.get(position).getAmount());
                } else {
                    amountView.setText("");
                }

            } else {
                gridView = (View) convertView;
            }

            return gridView;
        }

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

        @Override
        public Object getItem(int position) {
            return null;
        }

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

        public void updateCategoryList(List<Category> newlist) {
            this.notifyDataSetChanged();
        }
    }
}

【问题讨论】:

    标签: android android-fragments gridview adapter baseadapter


    【解决方案1】:

    试试这个:

        public View getView(int position, View convertView, ViewGroup parent) {
    
            View gridView;
            if (convertView == null) {
                gridView = new View(context);
                LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                gridView = inflater.inflate(R.layout.dashboard_category_item, null);
            } else {
                gridView = (View) convertView;
            }
    
            TextView nameView = (TextView) gridView.findViewById(R.id.category_name);
            ImageView imageView = (ImageView) gridView.findViewById(R.id.grid_item_image);
            TextView amountView = (TextView) gridView.findViewById(R.id.category_amount);
    
            nameView.setText(categories.get(position).getName());
            imageView.setImageResource(categories.get(position).getIconId());
            if (categories.get(position).getAmount() >= 0) {
                amountView.setText("$" + categories.get(position).getAmount());
            } else {
                amountView.setText("");
            }
    
            return gridView;
        }
    

    说明: 为了更好地使用内存和提高效率,adpater 旨在重用/回收项目视图。一种情况是滚动,一些项目消失,适配器从参数 convertView 获取消失的视图,可用于新项目。但是这些 convertViews 包含旧数据,因此需要用新数据填充它们。 notifyDataSetChanged() 上也有类似的情况。因此,在项目视图中填充数据的代码应该在 if (convertView == null) {...}else{...} 之后。

    【讨论】:

    • 谢谢!有效。但我真的不明白为什么。非常感谢您的解释,因为我仍在学习并想知道我的错误在哪里。
    猜你喜欢
    • 1970-01-01
    • 2023-04-05
    • 2015-02-10
    • 2011-12-19
    • 1970-01-01
    • 2020-05-28
    • 2020-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多