简体   繁体   English

将数据库记录加载到微调器中时出错

[英]Error Loading Database Records into Spinner

I'm working on an application for my A2 Level Computer Science coursework, and have run into an error when attempting to load data from a database table into a spinner. 我正在为我的A2级计算机科学课程编写应用程序,并且在尝试将数据从数据库表加载到微调器时遇到错误。 I'm looking to include the ids, forenames and surnames of all leaders in the spinner, however I've run into an error. 我希望在微调器中包含所有领导者的ID,姓名和姓氏,但是我遇到了一个错误。 Here is the code I wrote for the database handler: 这是我为数据库处理程序编写的代码:

    private static final String CREATE_TABLE_EVENTS=("CREATE TABLE " + TABLE_EVENTS + "("
        + COLUMN_SEID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_SNAME + " TEXT,"
        + COLUMN_STYPE + " TEXT,"+ COLUMN_SDATE + " TEXT," + COLUMN_EDATE + " TEXT,"
        + COLUMN_STIME + " TEXT," + COLUMN_ETIME + " TEXT," + COLUMN_VENUE + " TEXT,"
        + COLUMN_DESC + " TEXT," + COLUMN_SCID + " INTEGER," + COLUMN_EMAIL + " TEXT,"
        + COLUMN_ACOST + " REAL," + COLUMN_INV + " INTEGER," + COLUMN_PCOST + " REAL,"
        + COLUMN_FOOD + " TEXT," + COLUMN_TINC + " TEXT," + COLUMN_DIST + " INTEGER,"
        + COLUMN_TCOST + " REAL )"); //The columns had been defined earlier
...
//Search for leaders for spinner for purpose of creating an event
public String[][] eventLeadersSearch() {
    int CursorPosition;
    String[][] leadersList =new String[3][];
    String ScoutSection = "Leaders";
    String query = "SELECT " + COLUMN_SCID + ", " + COLUMN_FNAME + ", " + COLUMN_LNAME +" FROM " + TABLE_SCOUTS + " WHERE " + COLUMN_SECTION + " LIKE '" + ScoutSection + "'";
    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.rawQuery(query, null);
    int rowsFound=cursor.getCount();
    int x=0;
    if (rowsFound>0) {
        cursor.moveToFirst();
        do {
            CursorPosition = cursor.getPosition();
            leadersList[0][x] = Integer.toString((cursor.getInt(0)));//DEFINITELY SOMETHING WRONG HERE
            leadersList[1][x] = cursor.getString(1);
            leadersList[2][x] = cursor.getString(2);
            x = x + 1;
            cursor.moveToNext();
        }
        while (!cursor.isAfterLast());
    }
    else {
        Log.e("Database Error", "No Leaders Found");
    }

    cursor.close();
    db.close();
    return leadersList;
}

The reason for me using a 2d array is that later, I want to be able to go back and retrieve more details on that leader - however this will be on a different screen and thus in a different class. 我之所以使用2d数组,是因为稍后,我希望能够返回并检索有关该领导者的更多详细信息-但是,这将在不同的屏幕上,因此在不同的类中。 Therefore, I wanted to be able to retain all details individually as well. 因此,我也希望能够单独保留所有细节。

Here is the code I wrote to put all of the values into the spinner: 这是我编写的将所有值放入微调器的代码:

    private void loadSpinnerData(){
        databaseHandler db=new databaseHandler(getApplicationContext());
        String[][] Leaders=db.eventLeadersSearch(); //Error here
        List<String> LeadersInOne=new ArrayList<>();
        for (int i=0; i<Leaders.length; i++)
        {
            for (int j=0; j<Leaders[i].length; j++)
            {
                LeadersInOne.add(Leaders[i][j]);
            }
        }
        ArrayAdapter<String> dataAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, LeadersInOne);
        dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        leadersSpinner.setAdapter(dataAdapter);
}

These are the error details that appear in the LogCat: 这些是出现在LogCat中的错误详细信息:

01-20 18:41:02.712 16113-16113/com.example.atomi.scoutmanagerprototype E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.atomi.scoutmanagerprototype, PID: 16113
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.atomi.scoutmanagerprototype/com.example.atomi.scoutmanagerprototype.frmCreateEvent1}: java.lang.NullPointerException: Attempt to get length of null array
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2314)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2386)
    at android.app.ActivityThread.access$800(ActivityThread.java:148)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1292)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5310)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
 Caused by: java.lang.NullPointerException: Attempt to get length of null array
    at com.example.atomi.scoutmanagerprototype.frmCreateEvent1.loadSpinnerData(frmCreateEvent1.java:44)
    at com.example.atomi.scoutmanagerprototype.frmCreateEvent1.onCreate(frmCreateEvent1.java:33)
    at android.app.Activity.performCreate(Activity.java:5953)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1128)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2267)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2386) 
    at android.app.ActivityThread.access$800(ActivityThread.java:148) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1292) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:135) 
    at android.app.ActivityThread.main(ActivityThread.java:5310) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696) 

Does anyone have any idea what may have gone wrong? 有谁知道可能出了什么问题? It is my first time working in Android Studio, Java or XML and I am having to teach myself all of them, so any help would be much appreciated. 这是我第一次在Android Studio,Java或XML中工作,而且我必须自学所有这些内容,因此对您的帮助将不胜感激。 Thanks. 谢谢。

I believe that you would have fewer issues using a Cursor Adapter , such as SimpleCursorAdapter . 我相信使用Cursor适配器 (例如SimpleCursorAdapter)会遇到的问题更少。 Cursor Adpaters are designed to handle cursors so there is no need to create an intermediate Array for an Array adapter. Cursor Adpaters设计用于处理游标,因此无需为Array适配器创建中间Array。 They also pass the ID to the onItemSelected method. 他们还将ID传递给onItemSelected方法。 However, they do require a column named _id that is the id column (the example below shows how this can be done even if the id column is named something else). 但是,它们确实需要一个名为_id的列作为id列(下面的示例显示了即使id列使用其他名称也可以做到这一点)。

Example

The following example is based upon your code. 以下示例基于您的代码。 It selects Scouts who have Leaders in the section column to populate the spinner. 它选择在部分列中具有“ 领导者”的侦察员来填充微调器。 It also includes an onItemSelected listener that results in the details of the Scout being displayed via a toast when a scout is selected. 它还包括一个onItemSelected侦听器,当选择侦察员时,该侦听器将通过吐司显示侦察员的详细信息。

  • For convenience/explanation/demonstration of using multiple columns the layout simple_list_item_2 has been used. 为了方便/解释/演示使用多列,已使用布局simple_list_item_2。

Databasehelper.java Databasehelper.java

public class DatabaseHelper extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "mydatabase";
    private static final int DATABASE_VERSION = 1;
    private static final String TABLE_EVENTS = "events";
    private static final String COLUMN_SEID = BaseColumns._ID; //<<<<<<<<<< suits Cursor Adaptor
    private static final String COLUMN_SNAME = "sname";
    private static final String COLUMN_STYPE = "stype";
    private static final String COLUMN_SDATE = "sdate";
    private static final String COLUMN_EDATE = "edate";
    private static final String COLUMN_STIME = "stime";
    private static final String COLUMN_ETIME = "etime";
    private static final String COLUMN_VENUE = "venue";
    private static final String COLUMN_DESC = "desccription";
    private static final String COLUMN_SCID = "scid";
    private static final String COLUMN_EMAIL = "email";
    private static final String COLUMN_ACOST = "acost";
    private static final String COLUMN_INV = "inv";
    private static final String COLUMN_PCOST = "pcost";
    private static final String COLUMN_FOOD = "food";
    private static final String COLUMN_TINC = "tinc";
    private static final String COLUMN_DIST = "dist";
    private static final String COLUMN_TCOST = "tcost";

    public static final String TABLE_SCOUTS = "scouts"; //<<<<<<<<<<< public so the can be used elsewhere
    public static final String COLUMN_FNAME = "fname";
    public static final String COLUMN_LNAME = "lname";
    public static final String COLUMN_SECTION = "section";

    SQLiteDatabase mDB;

    private static final String CREATE_TABLE_EVENTS=("CREATE TABLE " + TABLE_EVENTS + "("
            + COLUMN_SEID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_SNAME + " TEXT,"
            + COLUMN_STYPE + " TEXT,"+ COLUMN_SDATE + " TEXT," + COLUMN_EDATE + " TEXT,"
            + COLUMN_STIME + " TEXT," + COLUMN_ETIME + " TEXT," + COLUMN_VENUE + " TEXT,"
            + COLUMN_DESC + " TEXT," + COLUMN_SCID + " INTEGER," + COLUMN_EMAIL + " TEXT,"
            + COLUMN_ACOST + " REAL," + COLUMN_INV + " INTEGER," + COLUMN_PCOST + " REAL,"
            + COLUMN_FOOD + " TEXT," + COLUMN_TINC + " TEXT," + COLUMN_DIST + " INTEGER,"
            + COLUMN_TCOST + " REAL )");

    private static final String CREATE_TABLE_SCOUTS = "CREATE TABLE " + TABLE_SCOUTS + "(" +
            COLUMN_SCID + " INTEGER PRIMARY KEY," +
            COLUMN_FNAME + " TEXT," +
            COLUMN_LNAME + " TEXT," +
            COLUMN_SECTION + " TEXT" +
            ")";

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        mDB = this.getWritableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE_EVENTS);
        db.execSQL(CREATE_TABLE_SCOUTS);
    }

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

    }

    public long addScout(String fname, String lname, String section) {
        ContentValues cv = new ContentValues();
        cv.put(COLUMN_FNAME,fname);
        cv.put(COLUMN_LNAME,lname);
        cv.put(COLUMN_SECTION,section);
        return mDB.insert(TABLE_SCOUTS,null,cv);
    }

    public Cursor getLeaders() {
        String where_clause = COLUMN_SECTION + "=?";
        String[] where_args =  new String[]{"Leaders"};
        //<<<<<<<<<< NOTE SELECT scid AS _id, fname, lname, section so that the id column in the cursor is _id
        String[] columns = new String[]{COLUMN_SCID + " AS " + BaseColumns._ID,COLUMN_FNAME, COLUMN_LNAME,COLUMN_SECTION};
        return mDB.query(TABLE_SCOUTS,columns,where_clause,where_args,null,null,null);
    }
}

MainActivity.java MainActivity.java

public class MainActivity extends AppCompatActivity {

    DatabaseHelper databaseHelper;
    Spinner leadersSpinner;
    SimpleCursorAdapter leaderAdapter;
    Cursor leaders;
    Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this;
        databaseHelper = new DatabaseHelper(this); //<<<<<<<<<< prepre to use Database
        leadersSpinner = this.findViewById(R.id.leaders_spinner); //<<<<<<<<<< get the Spinner
        addSomeScoutsForTesting(); //<<<<<<<<<< Add some data for testing
        setOrRefreshSpinner(); //<<<<<<<<<< prepare the spinner
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        leaders.close(); //<<<<<<<<<< Close the Cursor when the activity is done with
    }

    private void setOrRefreshSpinner() {
        leaders = databaseHelper.getLeaders();
        if (leaderAdapter == null) {
            String[] columns = new String[]{DatabaseHelper.COLUMN_FNAME, DatabaseHelper.COLUMN_LNAME};
            leaderAdapter = new SimpleCursorAdapter(this,android.R.layout.simple_list_item_2,leaders,columns,new int[]{android.R.id.text1,android.R.id.text2},0);
            leadersSpinner.setAdapter(leaderAdapter);
            leadersSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                    String fname = leaders.getString(leaders.getColumnIndex(DatabaseHelper.COLUMN_FNAME));
                    String lname = leaders.getString(leaders.getColumnIndex(DatabaseHelper.COLUMN_LNAME));
                    Toast.makeText(
                            context,
                            "You clicked the Scout " +
                                    fname + " " + lname +
                                    " whoose ID is " + String.valueOf(l) +
                                    " at position " + String.valueOf(i) +
                                    " in the Spinner.",
                            Toast.LENGTH_SHORT
                    ).show();
                }

                @Override
                public void onNothingSelected(AdapterView<?> adapterView) {

                }
            });
        } else {
            leaderAdapter.swapCursor(leaders);
        }
    }

    private void addSomeScoutsForTesting() {

        // Only add if there are none
        if (DatabaseUtils.queryNumEntries(databaseHelper.getWritableDatabase(),databaseHelper.TABLE_SCOUTS) > 0) return;

        databaseHelper.addScout("Tony","Smith","Leaders");
        databaseHelper.addScout("Anne","Taylor","Something else");
        databaseHelper.addScout("Mary","Bloggs","Leaders");
        databaseHelper.addScout("Sue","Franks","Leaders");
        databaseHelper.addScout("Alan","Jones","Cubs Scouts");
        databaseHelper.addScout("Belinda","Forrestor","Venturers");
    }
}
  • Note some comments have been added 请注意,已添加一些注释

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM