如何在片段内的 recylerview 列表中显示 SQLite 数据库数据?

Posted

技术标签:

【中文标题】如何在片段内的 recylerview 列表中显示 SQLite 数据库数据?【英文标题】:How to show SQLite database data in a recylerview list which is inside a fragment? 【发布时间】:2018-04-24 15:35:54 【问题描述】:

我是一名业余 android 开发人员,我想从数据库中获取用户输入的项目,然后将其显示在片段中的 recyclerview 列表(不是 ListView)中。

到目前为止,我已经创建了将数据保存到其中的 SQLite 数据库,我只想知道我可以在 recyclerview 中显示所有这些信息。下面显示的 Java 代码显示了我想要制作的内容,但它位于 listview 而不是 recyclerview 中。

数据库助手

public class DatabaseHelper extends SQLiteOpenHelper 
    private static final String TAG = "DatabaseHelper";

    public static final String DATABASE_NAME = "budget10.db";
    public static final String TABLE_NAME = "expense_table";
    public static final String TABLE_NAME2 = "income_table";
    public static final String COL_1 = "_id";
    public static final String COL_2 = "_id";
    public static final String EXPENSE_AMOUNT = "EXPENSE_AMOUNT";
    public static final String EXPENSE_DATE = "DATE";
    public static final String EXPENSE_NOTES = "NOTES";
    public static final String INCOME_AMOUNT = "INCOME_AMOUNT";
    public static final String INCOME_DATE = "DATE";
    public static final String INCOME_NOTES = "NOTES";
    public static final String INCOME_CATEGORY = "INCOME_CATEGORY";
    public static final String EXPENSE_CATEGORY = "EXPENSE_CATEGORY";
    public static final String EXPENSE_ACCOUNT = "EXPENSE_ACCOUNT";
    public static final String INCOME_ACCOUNT = "INCOME_ACCOUNT";

    public DatabaseHelper(Context context) 
        super(context, DATABASE_NAME, null, 3);
    

    @Override
    public void onCreate(SQLiteDatabase db) 
        db.execSQL("create table " + TABLE_NAME + " (_id INTEGER PRIMARY KEY AUTOINCREMENT, EXPENSE_AMOUNT DOUBLE,DATE INTEGER,NOTES TEXT, EXPENSE_CATEGORY TEXT, EXPENSE_ACCOUNT TEXT)");
        db.execSQL("create table " + TABLE_NAME2 + " (_id INTEGER PRIMARY KEY AUTOINCREMENT,INCOME_AMOUNT DOUBLE,DATE INTEGER,NOTES TEXT, INCOME_CATEGORY TEXT, INCOME_ACCOUNT TEXT)");

    

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME2);
        onCreate(db);
    

    public boolean insertexpenseData(Double amount_expense, String date_expense, String notes_expense, String category_expense, String expense_account) 
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(EXPENSE_AMOUNT, amount_expense);
        contentValues.put(EXPENSE_DATE, date_expense);
        contentValues.put(EXPENSE_NOTES, notes_expense);
        contentValues.put(EXPENSE_CATEGORY, category_expense);
        contentValues.put(EXPENSE_ACCOUNT, expense_account);
        long result = db.insert(TABLE_NAME, null, contentValues);
        if (result == -1)
            return false;
        else
            return true;
    

    public boolean insertincomeData(Double amount_income, String date_income, String notes_income, String category_income, String income_account) 
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(INCOME_AMOUNT, amount_income);
        contentValues.put(INCOME_DATE, date_income);
        contentValues.put(INCOME_NOTES, notes_income);
        contentValues.put(INCOME_CATEGORY, category_income);
        contentValues.put(INCOME_ACCOUNT, income_account);
        long result = db.insert(TABLE_NAME2, null, contentValues);
        if (result == -1)
            return false;
        else
            return true;
    

    public Cursor getexpenseData() 
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor res = db.rawQuery("select * from " + TABLE_NAME, null);
        return res;
    

    public Cursor getincomeData() 
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor res = db.rawQuery("select * from " + TABLE_NAME2, null);
        return res;
    



    public boolean updateexpenseData(String id, String amount, String date, String notes, String catagory_income) 
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(COL_1, id);
        contentValues.put(EXPENSE_AMOUNT, amount);
        contentValues.put(EXPENSE_DATE, date);
        contentValues.put(EXPENSE_NOTES, notes);
        contentValues.put(EXPENSE_CATEGORY, catagory_income);
        db.update(TABLE_NAME, contentValues, "_id = ?", new String[]id);
        return true;
    

    public boolean updateincomeData(String id, String amount, String date, String notes, String catagory_income) 
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(COL_2, id);
        contentValues.put(INCOME_AMOUNT, amount);
        contentValues.put(INCOME_DATE, date);
        contentValues.put(INCOME_NOTES, notes);
        contentValues.put(INCOME_CATEGORY, catagory_income);
        db.update(TABLE_NAME2, contentValues, "_id = ?", new String[]id);
        return true;
    

    public Integer deleteexpenseData(String _id) 
        SQLiteDatabase db = this.getWritableDatabase();
        return db.delete(TABLE_NAME, "_id = ?", new String[]_id);
    

    public Integer deleteincomeData(String _id) 
        SQLiteDatabase db = this.getWritableDatabase();
        return db.delete(TABLE_NAME2, "_id = ?", new String[]_id);
    

    public double getNetBudget() 
        SQLiteDatabase db = this.getWritableDatabase();
        String selectQuery = "SELECT TOTAL(INCOME_AMOUNT) - (SELECT TOTAL(EXPENSE_AMOUNT) FROM expense_table) FROM income_table";
        Cursor cursor = db.rawQuery(selectQuery, null);
        double netBudget = 0.00; // if there is no row, this will mean 0 is returned. You could also set it to -1, or throw an Exception if no record is returned
        if (cursor.moveToFirst()) 
            netBudget = cursor.getDouble(0);
        
        cursor.close();
        return netBudget;
    

    public double getTotalExpense() 
        SQLiteDatabase db = this.getWritableDatabase();
        String selectQuery = "SELECT TOTAL(EXPENSE_AMOUNT) FROM expense_table";
        Cursor cursor = db.rawQuery(selectQuery, null);
        double netExpense = 0.00; // if there is no row, this will mean 0 is returned. You could also set it to -1, or throw an Exception if no record is returned
        if (cursor.moveToFirst()) 
            netExpense = cursor.getDouble(0);
        
        cursor.close();
        return netExpense;
    

    public double getTotalIncome() 
        SQLiteDatabase db = this.getWritableDatabase();
        String selectQuery = "SELECT TOTAL(INCOME_AMOUNT) FROM income_table";
        Cursor cursor = db.rawQuery(selectQuery, null);
        double netIncome = 0.00; // if there is no row, this will mean 0 is returned. You could also set it to -1, or throw an Exception if no record is returned
        if (cursor.moveToFirst()) 
            netIncome = cursor.getDouble(0);
        
        cursor.close();
        return netIncome;
    

    public void deleteAllIncome() 
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(TABLE_NAME2, null, null);
        db.execSQL("delete from " + TABLE_NAME2);
        db.close();
    

    public void deleteAllExpense() 
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(TABLE_NAME, null, null);
        db.execSQL("delete from " + TABLE_NAME);
        db.close();
    


我想变成recyclerview的Fragment ListView

public class tab2income extends Fragment 

    private static final String TAG = "tab2income";
    DatabaseHelper mDatabaseHelper;
    private ListView mListView;
    View rootView;
    Cursor incomedata;
    SimpleCursorAdapter sca;
    DecimalFormat formatter = new DecimalFormat("0.00");


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 
        rootView = inflater.inflate(R.layout.tab2income, container, false);
        return rootView;
    

    @Override
    public void onActivityCreated( Bundle savedInstanceState) 
        super.onActivityCreated(savedInstanceState);
        mListView = (ListView) rootView.findViewById(R.id.listViewincome);
        mListView.setEmptyView(rootView.findViewById(R.id.empty));
        mDatabaseHelper = new DatabaseHelper(getActivity());

        populateListView();
    

    private void populateListView() 
        Log.d(TAG, "populateListView: Displaying data in the ListView.");
        incomedata = mDatabaseHelper.getincomeData();
        sca = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_1, incomedata, new String[]DatabaseHelper.INCOME_AMOUNT, new int[]android.R.id.text1, 0);
        mListView.setAdapter(sca);

        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() 
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) 
                int csrpos = incomedata.getPosition();
                incomedata.moveToPosition(i);
                displayNoteDate(
                        incomedata.getString(incomedata.getColumnIndex(DatabaseHelper.INCOME_NOTES)),
                        incomedata.getString(incomedata.getColumnIndex(DatabaseHelper.INCOME_DATE)),
                        incomedata.getString(incomedata.getColumnIndex(DatabaseHelper.INCOME_CATEGORY)),
                        l,
                        incomedata.getString(incomedata.getColumnIndex(DatabaseHelper.INCOME_ACCOUNT)));
                incomedata.moveToPosition(csrpos);
            
        );
    


    @Override
    public void onDestroy() 
        super.onDestroy();
        incomedata.close();
    

    public void displayNoteDate(String noteContent, String dateValue,String category, final long noteID,String account) 
        MaterialDialog.Builder builder= new MaterialDialog.Builder(getActivity())
                .title("Income Information")
                .content("Date: "+ dateValue+
                        "\nCategory: "+category+
                        "\nAccount: "+account+
                        "\nNote: "+noteContent)
                .positiveText("close")
                .negativeText("delete")
                .onPositive(new MaterialDialog.SingleButtonCallback() 
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) 
                    
                )
                .onNegative(new MaterialDialog.SingleButtonCallback() 
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) 
                        mDatabaseHelper.deleteincomeData(Long.toString(noteID));
                        incomedata = mDatabaseHelper.getincomeData();
                        sca.swapCursor(incomedata);
                    
                );
        builder.show();
    

编辑

这是我到目前为止对 Saurov Bagchi 答案中的代码所做的事情,我的 xml 文件中有 recyclerview,单击项目时没有任何反应:

片段

public class tab2income extends Fragment implements ItemClickListener 

    private static final String TAG = "tab2income";
    DatabaseHelper mDatabaseHelper;
    private RecyclerView mListView;
    View rootView;
    Cursor incomedata;
    SimpleCursorAdapter sca;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 
        rootView = inflater.inflate(R.layout.tab2income, container, false);
        return rootView;
    

    @Override
    public void onActivityCreated(Bundle savedInstanceState) 
        super.onActivityCreated(savedInstanceState);
        mListView = rootView.findViewById(R.id.ListViewincome);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
        mListView.setLayoutManager(layoutManager);
        mDatabaseHelper = new DatabaseHelper(getActivity());

        populateListView();
    

    private void populateListView() 
        Log.d(TAG, "populateListView: Displaying data in the ListView.");
        ArrayList<String> arrayList = new ArrayList<>();
        MyAdapter myAdapter = new MyAdapter(arrayList);
        mListView.setAdapter(myAdapter);

        incomedata = mDatabaseHelper.getincomeData();
        if(incomedata.moveToFirst())
            do 
                arrayList.add(incomedata.getString(incomedata.getColumnIndex(DatabaseHelper.INCOME_AMOUNT)));
             while (incomedata.moveToNext());
        
        myAdapter.notifyDataSetChanged();
    


    @Override
    public void onDestroy() 
        super.onDestroy();
        incomedata.close();
    


    @Override
    public void onClick(View view, int i) 
        int csrpos = incomedata.getPosition();
        incomedata.moveToPosition(i);
        displayNoteDate(
                incomedata.getString(incomedata.getColumnIndex(DatabaseHelper.INCOME_NOTES)),
                incomedata.getString(incomedata.getColumnIndex(DatabaseHelper.INCOME_DATE)),
                incomedata.getString(incomedata.getColumnIndex(DatabaseHelper.INCOME_CATEGORY)),
                incomedata.getString(incomedata.getColumnIndex(DatabaseHelper.INCOME_ACCOUNT)));
        incomedata.moveToPosition(csrpos);
    

    public void displayNoteDate(String noteContent, String dateValue,String category,String account) 
        MaterialDialog.Builder builder= new MaterialDialog.Builder(getActivity())
                .title("Income Information")
                .content("Date: "+ dateValue+
                        "\nCategory: "+category+
                        "\nAccount: "+account+
                        "\nNote: "+noteContent)
                .positiveText("close")
                .negativeText("delete")
                .onPositive(new MaterialDialog.SingleButtonCallback() 
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) 
                    
                )
                .onNegative(new MaterialDialog.SingleButtonCallback() 
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) 
                    
                );
        builder.show();
    


适配器

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> 
    private final ArrayList<String> dataSet;
    private ItemClickListener clickListener;

    public MyAdapter(ArrayList<String> myDataset) 
        dataSet = myDataset;
    

    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
        //layout of the list item
        View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);
        return new ViewHolder(view);
    

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) 
        holder.mTextView.setText(dataSet.get(position));
    

    @Override
    public int getItemCount() 
        return dataSet.size();
    

    public void setClickListener(ItemClickListener itemClickListener) 
        this.clickListener = itemClickListener;
    

    class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener 
        final TextView mTextView;

        ViewHolder(View v) 
            super(v);
            //textview for showing results
            mTextView = v.findViewById(android.R.id.text1);
            v.setOnClickListener(this);
        

        //for click
        @Override
        public void onClick(View view) 
            if (clickListener != null) clickListener.onClick(view, getAdapterPosition());

        
    

【问题讨论】:

我建议你使用新的 Android 架构组件。这很容易,并且需要更少的代码。 developer.android.com/topic/libraries/architecture/index.html 【参考方案1】:

对于 RecyclerView,您需要创建自己的自定义适配器。

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> 
    private final ArrayList<String> dataSet;
    private ItemClickListener clickListener;

    public MyAdapter(ArrayList<String> myDataset) 
        dataSet = myDataset;
    

    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
        //layout of the list item
        View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);
        return new ViewHolder(view);
    

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) 
        holder.mTextView.setText(dataSet.get(position));
    

    @Override
    public int getItemCount() 
        return dataSet.size();
    

    public void setClickListener(ItemClickListener itemClickListener) 
        this.clickListener = itemClickListener;
    

    class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener 
        final TextView mTextView;

        ViewHolder(View v) 
            super(v);
            //textview for showing results
            mTextView = v.findViewById(android.R.id.text1);
            v.setOnClickListener(this);
        

        //for click
        @Override
        public void onClick(View view) 
            if (clickListener != null) clickListener.onClick(view, getAdapterPosition());
        
    

那我只是重写populateListView()方法

private void populateListView() 
    Log.d(TAG, "populateListView: Displaying data in the ListView.");
    ArrayList<String> arrayList = new ArrayList<>();
    MyAdapter myAdapter = new MyAdapter(arrayList);
    mListView.setAdapter(myAdapter);

    incomedata = mDatabaseHelper.getincomeData();
    if(incomedata.moveToFirst())
        do 
            arrayList.add(incomedata.getString(incomedata.getColumnIndex(DatabaseHelper.INCOME_AMOUNT)));
         while (incomedata.moveToNext());
    
    myAdapter.notifyDataSetChanged();

您还需要为每个项目点击创建一个界面。

public interface ItemClickListener 
    void onClick (View view, int position);

并在你的 Fragment 中实现这个接口。

public class tab2income extends Fragment implements ItemClickListener

    //All of your codes

    @Override
    public void onClick (View view, int i) 
        int csrpos = incomedata.getPosition();
            incomedata.moveToPosition(i);
            displayNoteDate(
                    incomedata.getString(incomedata.getColumnIndex(DatabaseHelper.INCOME_NOTES)),
                    incomedata.getString(incomedata.getColumnIndex(DatabaseHelper.INCOME_DATE)),
                    incomedata.getString(incomedata.getColumnIndex(DatabaseHelper.INCOME_CATEGORY)),
                    l,
                    incomedata.getString(incomedata.getColumnIndex(DatabaseHelper.INCOME_ACCOUNT)));
            incomedata.moveToPosition(csrpos);
    

【讨论】:

我只是想问一下如何在片段中使用它? note ID 怎么样,它不起作用,并且约束布局 cardview 也会引发错误 另外,我尝试修复异常然后运行应用程序,但片段没有显示 recyclerview ViewHolder 仍然保持红色 我在打开片段时收到此错误“未附加布局管理器;跳过布局”

以上是关于如何在片段内的 recylerview 列表中显示 SQLite 数据库数据?的主要内容,如果未能解决你的问题,请参考以下文章

片段内的自定义列表不起作用

如何拖放 recyclerView 元素?

Android:NullPointerException 无法将数据库加载到片段内的列表视图中

使用CustomLists数组显示recylerview数据

Android-RecylerView控件

如何使用导航组件处理片段内的向上按钮