使用光标从SQLITE数据库读取数据时应用程序崩溃 - Android

时间:2013-11-30 21:11:41

标签: java android xml sqlite cursor

我正在尝试使用ListView将数据库中的数据显示为SimpleCursorProvider,但是当我立即在崩溃中运行我的应用时。经过数小时的编辑后,我发现问题来自于getAllData()方法中的光标。即使我无法修复代码!!

那么你能看看我的代码并告诉我它有什么问题。问题可能是数据库是空的,还是我填充ListView的方式。

这是我的代码:

package com.xtreem.gpstracker;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class GPSDatabase {
    private DbHelper dbHelper;
    private static final String TAG = "GPSDatabase";
    public final static String DBNAME="gpstracker.db";
    public final static int DBVERSION=1;
    private SQLiteDatabase db;
    public static final String TABLE_NAME="location";
    public static final String COLUMN_ID = "_id";
    public static final String COLUMN_DATE = "date";
    public static final String COLUMN_TIME = "time";
    public static final String COLUMN_LAT = "latitude";
    public static final String COLUMN_LON = "longitude";
    public static final String COLUMN_ALT = "altitude";
    public static final String COLUMN_SPEED = "speed";
    public static final String COLUMN_DIR = "direction";
    public static final String COLUMN_ACC = "accuracy";
    public static final String[] ALL_COLUMNS = new String[]{COLUMN_ID,COLUMN_DATE,COLUMN_TIME,COLUMN_LAT,COLUMN_LON,COLUMN_ALT,COLUMN_SPEED,COLUMN_DIR,COLUMN_ACC};
    public final static String CREATERDB="create table "
              + TABLE_NAME + "(" + COLUMN_ID
              + " integer primary key autoincrement, "
              + COLUMN_DATE + " text not null, " 
              + COLUMN_TIME + " text not null, "
              + COLUMN_LAT + " text not null, "
              + COLUMN_LON + " text not null, "
              + COLUMN_ALT + " text not null, "
              + COLUMN_SPEED + " text not null, "
              + COLUMN_DIR + " text not null, "
              + COLUMN_ACC + " text not null);";
    private final Context context;

    //const
    public GPSDatabase(Context ctx){
        this.context = ctx;
        dbHelper=new DbHelper(context);
    }   

    public long insertRows(String column2, String column3, String column4, String column5, String column6, String column7, String column8, String column9){
        ContentValues value=new ContentValues();
        value.put(COLUMN_DATE, column2);
        value.put(COLUMN_TIME, column3);
        value.put(COLUMN_LAT, column4);
        value.put(COLUMN_LON, column5);
        value.put(COLUMN_ALT, column6);
        value.put(COLUMN_SPEED, column7);
        value.put(COLUMN_DIR, column8);
        value.put(COLUMN_ACC, column9);
        return db.insert(TABLE_NAME,null,value);
    }
    public Cursor getAllRows(){
        Cursor c =db.query(TABLE_NAME,ALL_COLUMNS, null,null, null, null, null); /*COLUMN_ID+" DESC"*/
        if (c != null) {
            c.moveToFirst();
        }
        return c;
    }
    public GPSDatabase open() {
        db = dbHelper.getWritableDatabase();
        return this;
    }
    public void close(){
        dbHelper.close();
        //return true;
    }





    public static class DbHelper extends SQLiteOpenHelper{
        public DbHelper(Context context){
            super(context, DBNAME, null, DBVERSION);
        }
        @Override
        public void onCreate(SQLiteDatabase _db) {
            // TODO Auto-generated method stub
            _db.execSQL(CREATERDB);
        }
        @Override
        public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) {
            // TODO Auto-generated method stub

            Log.w(TAG, "Upgrading application's database from version " + oldVersion
                    + " to " + newVersion + ", which will destroy all old data!");

            // Destroy old database:
            _db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);

            // Recreate new database:
            onCreate(_db);
        }
    }
}

MainActivity

package com.xtreem.gpstracker;


import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;

public class MainActivity extends Activity {

    GPSDatabase myDb;

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

        startService(new Intent(getBaseContext(), gpsLogger.class));
        openDB();
        populateListViewFromDB();

    }



    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.start_menu_option: 
            startService(new Intent(getBaseContext(), gpsLogger.class));
            return true;
        case R.id.stop_menu_option:
            stopService(new Intent(getBaseContext(), gpsLogger.class));
            return true;
        case R.id.quit_menu_option:
            Toast.makeText(this, "quit", Toast.LENGTH_SHORT).show();
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    private void openDB() {
        myDb = new GPSDatabase(this);
        myDb.open();
    }
    private void closeDB() {
        myDb.close();
    }

    protected void onDestroy() {
        super.onDestroy();  
        closeDB();
    }

    private void populateListViewFromDB() {
        GPSDatabase DB = new GPSDatabase(this); 
        Cursor cursor = DB.getAllRows();

        startManagingCursor(cursor);

        String[] fromFieldNames = new String[]
                {GPSDatabase.COLUMN_LAT}; //I'm using only one column for tesing
        int[] toViewIDs = new int[]
                {R.id.latTextView};

        SimpleCursorAdapter myCursorAdapter = new SimpleCursorAdapter(
                this,                       
                R.layout.item_layout,       
                cursor,                     
                fromFieldNames,             
                toViewIDs                   
                );


        ListView myList = (ListView) findViewById(R.id.list);
        myList.setAdapter(myCursorAdapter);
    }

}

activity_main.xml中

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" >

    </ListView>

</RelativeLayout>

item_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<TextView
    android:id="@+id/textView2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_toRightOf="@+id/latTextView"
    android:text=", "
    android:textAppearance="?android:attr/textAppearanceLarge" />

<TextView
    android:id="@+id/longTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_toRightOf="@+id/textView2"
    android:text="Large Text"
    android:textAppearance="?android:attr/textAppearanceLarge" />

<TextView
    android:id="@+id/textView5"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/latTextView"
    android:layout_toRightOf="@+id/dateTextView"
    android:text=", "
    android:textColor="#878787" />

<TextView
    android:id="@+id/timeTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBaseline="@+id/textView5"
    android:layout_alignBottom="@+id/textView5"
    android:layout_toRightOf="@+id/textView5"
    android:text="Medium Text"
    android:textColor="#878787" />

<TextView
    android:id="@+id/latTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_marginLeft="16dp"
    android:text="Large Text"
    android:textAppearance="?android:attr/textAppearanceLarge" />

<TextView
    android:id="@+id/dateTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBaseline="@+id/textView5"
    android:layout_alignBottom="@+id/textView5"
    android:layout_alignLeft="@+id/textView"
    android:text="Medium Text"
    android:textColor="#878787" />

</RelativeLayout>

logcat的

12-01 00:03:19.824: E/AndroidRuntime(830): FATAL EXCEPTION: main
12-01 00:03:19.824: E/AndroidRuntime(830): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xtreem.gpstracker/com.xtreem.gpstracker.MainActivity}: java.lang.NullPointerException
12-01 00:03:19.824: E/AndroidRuntime(830):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1955)
12-01 00:03:19.824: E/AndroidRuntime(830):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980)
12-01 00:03:19.824: E/AndroidRuntime(830):  at android.app.ActivityThread.access$600(ActivityThread.java:122)
12-01 00:03:19.824: E/AndroidRuntime(830):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1146)
12-01 00:03:19.824: E/AndroidRuntime(830):  at android.os.Handler.dispatchMessage(Handler.java:99)
12-01 00:03:19.824: E/AndroidRuntime(830):  at android.os.Looper.loop(Looper.java:137)
12-01 00:03:19.824: E/AndroidRuntime(830):  at android.app.ActivityThread.main(ActivityThread.java:4340)
12-01 00:03:19.824: E/AndroidRuntime(830):  at java.lang.reflect.Method.invokeNative(Native Method)
12-01 00:03:19.824: E/AndroidRuntime(830):  at java.lang.reflect.Method.invoke(Method.java:511)
12-01 00:03:19.824: E/AndroidRuntime(830):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
12-01 00:03:19.824: E/AndroidRuntime(830):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
12-01 00:03:19.824: E/AndroidRuntime(830):  at dalvik.system.NativeStart.main(Native Method)
12-01 00:03:19.824: E/AndroidRuntime(830): Caused by: java.lang.NullPointerException
12-01 00:03:19.824: E/AndroidRuntime(830):  at com.xtreem.gpstracker.GPSDatabase.getAllRows(GPSDatabase.java:59)
12-01 00:03:19.824: E/AndroidRuntime(830):  at com.xtreem.gpstracker.MainActivity.populateListViewFromDB(MainActivity.java:118)
12-01 00:03:19.824: E/AndroidRuntime(830):  at com.xtreem.gpstracker.MainActivity.onCreate(MainActivity.java:34)
12-01 00:03:19.824: E/AndroidRuntime(830):  at android.app.Activity.performCreate(Activity.java:4465)
12-01 00:03:19.824: E/AndroidRuntime(830):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
12-01 00:03:19.824: E/AndroidRuntime(830):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1919)
12-01 00:03:19.824: E/AndroidRuntime(830):  ... 11 more

谢谢

2 个答案:

答案 0 :(得分:1)

getAllRows()中有一个NullPointerException。很可能你的db对象是null。

你在那里创建一个新的GPSDatabase对象,但是不要初始化“db”变量,然后用它来查询它。

您可以通过记录变量的状态或使用调试器并单步执行导致错误的方法来检查这一点。在大多数IDE中,您还可以在NullPointerException上设置断点。

我猜insert()是有效的,因为你之前调用了open()。

答案 1 :(得分:1)

尝试将populateListViewFromDB()更改为:

private void populateListViewFromDB() {

    Cursor cursor = myDb.getAllRows();

    startManagingCursor(cursor);

    String[] fromFieldNames = new String[]
            {GPSDatabase.COLUMN_LAT}; //I'm using only one column for tesing
    int[] toViewIDs = new int[]
            {R.id.latTextView};

    SimpleCursorAdapter myCursorAdapter = new SimpleCursorAdapter(
            this,                       
            R.layout.item_layout,       
            cursor,                     
            fromFieldNames,             
            toViewIDs                   
            );


    ListView myList = (ListView) findViewById(R.id.list);
    myList.setAdapter(myCursorAdapter);
}