ListView 中的 SQLite 数据库 Android

SQLite Database in ListView Android

在 android studio 的列表视图中显示来自 SQLite 数据库的一些记录时出现问题。显示列表视图的代码是:

import android.app.DatePickerDialog;
import android.content.Intent;
import android.database.Cursor;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.Toast;

import java.util.Calendar;

public class PreviousHunts extends AppCompatActivity implements View.OnClickListener
{
    public TextView txtDate;
    public String strDate = "";
    public ListView lstView;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_previous_hunts);

        Button btnDateGet = findViewById(R.id.btnGetHunts);
        btnDateGet.setOnClickListener(this);

        Button btnHome = findViewById(R.id.btnHuntsHome);
        btnHome.setOnClickListener(this);

        txtDate = findViewById(R.id.txtDateThing);
        lstView = findViewById(R.id.lstView);
    }

    @Override
    public void onClick(View v)
    {
        switch (v.getId())
        {
            case R.id.btnGetHunts:
                getDate();
                break;
            case R.id.btnHuntsHome:
                goHome();
                break;
        }
    }

    private void getDate()
    {
        final Calendar c = Calendar.getInstance();
        final int Year = c.get(Calendar.YEAR);
        final int Month = c.get(Calendar.MONTH);
        final int Day = c.get(Calendar.DAY_OF_MONTH);

        DatePickerDialog datePickerDialog = new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener()
        {
            @Override
            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth)
            {
                String day = String.valueOf(dayOfMonth);
                String Smonth = String.valueOf(month + 1);
                String sYear = String.valueOf(year);

                txtDate.setText(day + "/" + Smonth + "/" + sYear);
                strDate = day + "/" + Smonth + "/" + sYear;
            }
        },Year, Month, Day);
        datePickerDialog.show();

        DatabaseHelper dbHelp = new DatabaseHelper(this);
        int huntID = dbHelp.getHuntIDforPastHunts(strDate);

        if (huntID == 0)
        {
            Toast.makeText(getApplicationContext(), "No Hunts on that day.", Toast.LENGTH_LONG).show();
        }
        else
        {
            LastPart(huntID);
        }
    }

    private void LastPart(int huntID)
    {
        DatabaseHelper dbHelp = new DatabaseHelper(this);
        Cursor cursor = dbHelp.getPastHuntLogs(huntID);

        cursor.moveToFirst();

        //SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, lstView, cursor, new String[] {"BirdName", "SeenORShot", "BirdAge", "NumSeenORShot",
                //"OtherAnimalShotORClayShoot", "AnimalShotNameORTypeClaysShot"}, new int[] {100}, 0);

        //lstView.setAdapter(adapter);

        SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
                R.layout.activity_previous_hunts,
                cursor,
                new String[]{"BirdName", "SeenORShot", "BirdAge", "NumSeenORShot", "OtherAnimalShotORClayShoot", "AnimalShotNameORTypeClaysShot"},
                new int[]{1, 2, 3, 4, 5, 6}
                ,0);

        lstView.setAdapter(adapter);
    }

    private void goHome()
    {
        Intent intent = new Intent(PreviousHunts.this, Home_Screen.class);
        startActivity(intent);
        finish();
    }
}

The database helper code is:

    public Cursor getPastHuntLogs(int huntID)
        {
            String query = "SELECT HuntID AS _id, BirdName, SeenORShot, BirdAge, NumSeenORShot, OtherAnimalShotORClayShoot, " +
                    "AnimalShotNameORTypeClaysShot FROM Log WHERE HuntID = " + "'huntID'";
            Cursor cursor = db.rawQuery(query, null);
            return cursor;
        }

XML 对于列表视图等,是:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".PreviousHunts">

    <Button
        android:id="@+id/btnGetHunts"
        android:layout_width="150dp"
        android:layout_height="75dp"
        android:layout_marginStart="15dp"
        android:layout_marginTop="15dp"
        android:text="Select Date you wish to see hunts from"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/txtDateThing"
        android:layout_width="wrap_content"
        android:layout_height="25dp"
        android:layout_marginEnd="100dp"
        android:layout_marginTop="45dp"
        android:text="Date"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btnHuntsHome"
        android:layout_width="88dp"
        android:layout_height="50dp"
        android:layout_marginBottom="10dp"
        android:layout_marginEnd="100dp"
        android:layout_marginStart="100dp"
        android:text="Home"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <ListView
        android:id="@+id/lstView"
        android:layout_width="362dp"
        android:layout_height="342dp"
        android:layout_marginEnd="15dp"
        android:layout_marginStart="15dp"
        android:layout_marginTop="10dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnGetHunts" />
</android.support.constraint.ConstraintLayout>

问题是没有任何反应。 运行 日志中没有错误,也没有显示任何内容。非常感谢您的帮助。

尝试在选择日期后添加数据库代码。

像这样

private void getDate() {
    final Calendar c = Calendar.getInstance();
    final int Year = c.get(Calendar.YEAR);
    final int Month = c.get(Calendar.MONTH);
    final int Day = c.get(Calendar.DAY_OF_MONTH);

    DatePickerDialog datePickerDialog = new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener()
    {
        @Override
        public void onDateSet(DatePicker view, int year, int month, int dayOfMonth)
        {
            String day = String.valueOf(dayOfMonth);
            String Smonth = String.valueOf(month + 1);
            String sYear = String.valueOf(year);

            txtDate.setText(day + "/" + Smonth + "/" + sYear);
            strDate = day + "/" + Smonth + "/" + sYear;

            // Try database code here
            DatabaseHelper dbHelp = new DatabaseHelper(this);
            int huntID = dbHelp.getHuntIDforPastHunts(strDate);

            if (huntID == 0)
            {
                Toast.makeText(getApplicationContext(), "No Hunts on that day.", Toast.LENGTH_LONG).show();
            }
            else
            {
                LastPart(huntID);
            }

        }
    },Year, Month, Day);
    datePickerDialog.show();
}

您遇到的主要问题是您在检索日期后没有调用列表的填充。而是在检索日期之前填充列表视图。

也就是代码:-

    DatabaseHelper dbHelp = new DatabaseHelper(this);
    int huntID = dbHelp.getHuntIDforPastHunts(strDate);

    if (huntID == 0)
    {
        Toast.makeText(getApplicationContext(), "No Hunts on that day.", Toast.LENGTH_LONG).show();
    }
    else
    {
        LastPart(huntID);
    }

将在您获得日期之前执行,因此没有日期没有提取数据。

还有其他问题,例如每次点击按钮都会创建一个新的适配器,何时应该使用一个并刷新列表。

以下是我建议的做法,它是工作代码并且已经过测试。但是,对于测试,我不得不猜测 DatabaseHelper 的大部分内容,因为所有可用的方法都是 getPastHuntLogs 方法。

DatabaseHelper.java 使用的是:-

public class DatabaseHelper extends SQLiteOpenHelper {

    /**
     * Suggest using 1 definitaion of table and column names and to ALWAYS use the constants
     */
    public static final String DBNAME = "hunter";
    public static final int DBVERSION = 1;
    public static final String TABLE_LOG = "Log";
    public static final String COL_TIMESTAMP = "timestamp";
    public static final String COl_LOG_HUNTID = "HuntID";
    public static final String COL_LOG_BIRDNAME = "BirdName";
    public static final String COL_LOG_SEENORSHOT = "SeenOrShot";
    public static final String COL_LOG_BIRDAGE = "BirdAge";
    public static final String COL_LOG_NUMSEENORSHOT = "NumSeenOrShot";
    public static final String COL_LOG_OTHERANIMALSSHOTORCLAYSHOOT = "OtherAnimalShotORClayShoot";
    public static final String COL_LOG_ANIMALSHORORTYPECLAYSHOOT = "AnimalShotNameORTypeClaysShot";

    SQLiteDatabase db;
    public DatabaseHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
        db = this.getWritableDatabase();
    }

    /**
     * Guestimate
     * @param db
     */
    @Override
    public void onCreate(SQLiteDatabase db) {

        String crt_log_tbl_sql = "CREATE TABLE IF NOT EXISTS " + TABLE_LOG + "(" +
                COl_LOG_HUNTID + " INTEGER PRIMARY KEY, " +
                COL_TIMESTAMP + " TEXT DEFAULT CURRENT_TIMESTAMP, " +
                COL_LOG_BIRDNAME + " TEXT, " +
                COL_LOG_SEENORSHOT + " TEXT, " +
                COL_LOG_BIRDAGE + " REAL," +
                COL_LOG_NUMSEENORSHOT + " INTEGER, " +
                COL_LOG_OTHERANIMALSSHOTORCLAYSHOOT + " TEXT," +
                COL_LOG_ANIMALSHORORTYPECLAYSHOOT + " TEXT " +
                ")";
        db.execSQL(crt_log_tbl_sql);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }

    /**
     * Added so I could see the rows in the log
     */
    public void dumpLogTable() {
        Cursor csr = db.query(TABLE_LOG,null,null,null,null,null,null);
        DatabaseUtils.dumpCursor(csr);
        csr.close();
    }

    /**
     *  Guestimate. (note converts dates to YYYY-MM-DD format as stored )
     * @param strDate
     * @return
     */
    public int getHuntIDforPastHunts(String strDate) {
        int rv = 0;
        String[] datevalues = strDate.split("/");
        String srchdate = datevalues[2] + "-" + datevalues[1] + "-" + datevalues[0];
        String whereclause = "date(" + COL_TIMESTAMP + ")=?";
        String[] whereargs = new String[]{srchdate};
        Cursor csr = db.query(TABLE_LOG,null,whereclause,whereargs,null,null,null);
        if (csr.moveToFirst()) {
            rv = csr.getInt(csr.getColumnIndex(COl_LOG_HUNTID));
        }
        return rv;
    }

    /**
     *  ALlows some testing data to be added
     * @param birdname
     * @param seenorshot
     * @param birdage
     * @param numseenorshot
     * @param otheranimalshotorclayshoot
     * @param animalshotortypeclayshoot
     * @return
     */
    public long insertLog(String birdname, String seenorshot,double birdage, int numseenorshot, String otheranimalshotorclayshoot, String animalshotortypeclayshoot) {
        ContentValues cv = new ContentValues();
        cv.put(COL_LOG_BIRDNAME,birdname);
        cv.put(COL_LOG_SEENORSHOT,seenorshot);
        cv.put(COL_LOG_BIRDAGE,birdage);
        cv.put(COL_LOG_NUMSEENORSHOT,numseenorshot);
        cv.put(COL_LOG_OTHERANIMALSSHOTORCLAYSHOOT,otheranimalshotorclayshoot);
        cv.put(COL_LOG_ANIMALSHORORTYPECLAYSHOOT,animalshotortypeclayshoot);
        return db.insert(TABLE_LOG,null,cv);
    }

    /**
     * Very much as was
     * @param huntID
     * @return
     */
    public Cursor getPastHuntLogs(int huntID)
    {
        String query = "SELECT HuntID AS _id, BirdName, SeenORShot, BirdAge, NumSeenORShot, OtherAnimalShotORClayShoot, " +
                "AnimalShotNameORTypeClaysShot FROM Log " +
                "WHERE HuntID = " + String.valueOf(huntID) + //<<<<<<<<<< Changed
                ""; //<<<<<<<<<< ADDED so that WHERE...... can be commented out so select all
        return db.rawQuery(query, null); //<<<<<<<< returns cursor directly
    }
}
  • 参考评论

PreviousHunts.java

public class PreviousHunts extends AppCompatActivity implements View.OnClickListener {

    public TextView txtDate;
    public String strDate = "";
    public ListView lstView;
    SimpleCursorAdapter adapter; //<<<<<<<<<< ADDED
    DatabaseHelper dbHelp; //<<<<<<<<<< ADDED
    Cursor cursor; //<<<<<<<<<< ADDED

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_previous_hunts);

        Button btnDateGet = findViewById(R.id.btnGetHunts);
        btnDateGet.setOnClickListener(this);

        Button btnHome = findViewById(R.id.btnHuntsHome);
        btnHome.setOnClickListener(this);

        txtDate = findViewById(R.id.txtDateThing);
        lstView = findViewById(R.id.lstView);
        dbHelp = new DatabaseHelper(this); //<<<<<<<<<< ADDED
        addSomeTestData(); //<<<<<<<<<< ADDDED

    }

    @Override
    public void onClick(View v)
    {
        switch (v.getId())
        {
            case R.id.btnGetHunts:
                getDate();
                break;
            case R.id.btnHuntsHome:
                goHome();
                break;
        }
    }

    private void getDate()
    {
        final Calendar c = Calendar.getInstance();
        final int Year = c.get(Calendar.YEAR);
        final int Month = c.get(Calendar.MONTH);
        final int Day = c.get(Calendar.DAY_OF_MONTH);

        DatePickerDialog datePickerDialog = new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener()
        {
            @Override
            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth)
            {
                String day = String.valueOf(dayOfMonth);
                String Smonth = String.valueOf(month + 1);
                String sYear = String.valueOf(year);

                txtDate.setText(day + "/" + Smonth + "/" + sYear);
                strDate = day + "/" + Smonth + "/" + sYear;
                displayHuntList(strDate); //<<<<<<<<<< CHANGED calls displayHuntList
            }
        },Year, Month, Day);
        datePickerDialog.show();
    }


    //<<<<<<<<<< NEW replaces last_hunt code

    public void displayHuntList(String strDate) {
        int huntID = dbHelp.getHuntIDforPastHunts(strDate);
        if (huntID < 1) {
            Toast.makeText(getApplicationContext(), "No Hunts on that day.", Toast.LENGTH_LONG).show();
        }
        cursor = dbHelp.getPastHuntLogs(huntID);
        //<<<<<<<<<< Only create a SimpleCursorAdapter instance once and reuse
        //<<<<<<<<<< NOTE!! Stock layout used for convenience >>>>>>>>>>
        if (adapter == null) {
            adapter = new SimpleCursorAdapter(this,
                    android.R.layout.simple_list_item_2,
                    cursor,
                    new String[]{DatabaseHelper.COL_LOG_BIRDNAME,
                            DatabaseHelper.COL_LOG_SEENORSHOT},
                    new int[]{android.R.id.text1,android.R.id.text2},
                    0
            );
            lstView.setAdapter(adapter);
        } else {
            // if called after the initial call just swap the cursor to refresh the list
            adapter.swapCursor(cursor);
        }
    }

    private void goHome()
    {
        //<<<<<<<<<< Commented body out so hitting HOME does nothing >>>>>>>>>>
        /*
        Intent intent = new Intent(PreviousHunts.this, Home_Screen.class);
        startActivity(intent);
        finish();
        */
    }

    /**
     * Added so some testing data is added (note 2 rows added each time App is run)
     * All rows have a timestamp as per the day the App is run (ok for testing)
     */
    private void  addSomeTestData() {
        dbHelp.insertLog("Pheasant","Seen",1.75,100,"N/A","N/A");
        dbHelp.insertLog("Grouse","SHOT",2.3,10,"NO","MAYBE");
        dbHelp.dumpLogTable();
    }
}
  • 希望大部分代码都很熟悉,评论应该有所帮助
  • 注意列表只显示 1,因为选择是通过 huntID(也许这是来自另一个 table,我猜是)(注释掉 WHERE 行在 getPastHuntLogs 方法中 DatabaseHelper.java 将列出所有行)。

结果 1

启动时(注意我设置了 ListView 的背景所以很容易看到):-

结果 2

点击按钮并选择当前日期后:-

实际上在这之后走了一条不那么复杂但更容易的路线。简单地制作了一个长字符串,它实际上帮助了长 运行 中的代码的后面部分。感谢大家的帮助。