samedi 30 avril 2016

Android MVC approach with SQLiteDatabase: no such column exception [duplicate]

This question already has an answer here:

Was experimenting with a simple way to implement MVC in Android (no controller yet) with SQLiteDatabase to store the model but when i run my application it throws "android.database.sqlite.SQLiteException: no such column" exception and shuts down.

The main activity:

package nemphys.listitup.activity;

import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;

import nemphys.listitup.R;
import nemphys.listitup.model.OnChangeListener;
import nemphys.listitup.model.ToDoModel;

public class MainActivity extends AppCompatActivity implements
        OnChangeListener<ToDoModel> {

    private static final String TAG = MainActivity.class.getSimpleName();

    private ToDoModel model;
    private ListView listToDo;
    private ArrayAdapter<String> adapter;

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

        model = new ToDoModel(this);
        model.addListener(this);
        listToDo = (ListView) findViewById(R.id.listToDo);
        adapter = new ArrayAdapter<>(this, R.layout.item_todo,
                R.id.txtItemName, model.getToDoList());
        listToDo.setAdapter(adapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.addItem:
                final EditText taskEditText = new EditText(this);
                AlertDialog dialog = new AlertDialog.Builder(this)
                        .setTitle("Neue Aufgabe hinzufügen")
                        .setMessage("Was wollen Sie als nächstes tun?")
                        .setView(taskEditText)
                        .setPositiveButton("Hinzufügen",
                                new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        String task = String.valueOf(taskEditText.getText());
                                        model.addItem(task);
                                    }
                                })
                        .setNegativeButton("Abbrechen", null)
                        .create();
                dialog.show();
                return true;
            default:
                return false;
        }
    }

    public void deleteTask(View view) {
        View parent = (View) view.getParent();
        TextView taskTextView = (TextView) parent.findViewById(R.id.txtItemName);
        String task = String.valueOf(taskTextView.getText());
        model.removeItem(task);
    }

    @Override
    public void onChange(ToDoModel model) {
        adapter.notifyDataSetChanged();
    }
}

The model:

package nemphys.listitup.model;

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

import java.util.ArrayList;

import nemphys.listitup.activity.MainActivity;

public class ToDoModel extends SimpleObservable<ToDoModel> {

    private static final String TAG =
            MainActivity.class.getSimpleName();

    private ToDoDbHelper dbHelper;

    public ToDoModel(Context context) {
        dbHelper = new ToDoDbHelper(context);
    }

    public ArrayList<String> getToDoList() {
        ArrayList<String> toDoList = new ArrayList<>();
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        Cursor cursor = db.query(ToDoContract.ToDoEntry.TABLE_NAME,
                new String[]{ToDoContract.ToDoEntry._ID,
                        ToDoContract.ToDoEntry.COLUMN_TASK_TITLE},
                null, null, null, null, null);
        while (cursor.moveToNext()) {
            int i = cursor.getColumnIndex(ToDoContract.ToDoEntry.COLUMN_TASK_TITLE);
            toDoList.add(cursor.getString(i));
        }
        cursor.close();
        db.close();
        return toDoList;
    }

    public void addItem(String toDoItem) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(ToDoContract.ToDoEntry.COLUMN_TASK_TITLE, toDoItem);
        db.insertWithOnConflict(ToDoContract.ToDoEntry.TABLE_NAME,
                null,
                values,
                SQLiteDatabase.CONFLICT_REPLACE);
        db.close();
        notifyObservers(this);
    }

    public void removeItem(String toDoItem) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        db.delete(ToDoContract.ToDoEntry.TABLE_NAME,
                ToDoContract.ToDoEntry.COLUMN_TASK_TITLE + " = ?",
                new String[]{toDoItem});
        db.close();
        notifyObservers(this);
    }
}

The Observable:

package nemphys.listitup.model;

import java.util.ArrayList;

public class SimpleObservable<T> {

    private final ArrayList<OnChangeListener<T>> listeners = new ArrayList<>();

    public void addListener(OnChangeListener<T> listener) {
        synchronized (listeners) {
            listeners.add(listener);
        }
    }

    public void removeListener(OnChangeListener<T> listener) {
        synchronized (listeners) {
            listeners.remove(listener);
        }
    }

    protected void notifyObservers(final T model) {
        synchronized (listeners) {
            for (OnChangeListener<T> listener : listeners) {
                listener.onChange(model);
            }
        }
    }

}

The SQLiteOpenHelper:

package nemphys.listitup.model;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class ToDoDbHelper extends SQLiteOpenHelper {
    public static final int DATABASE_VERSION = 1;
    public static final String DATABASE_NAME = "ToDo.db";

    private static final String SQL_CREATE_ENTRIES =
            "CREATE TABLE " + ToDoContract.ToDoEntry.TABLE_NAME + " (" +
                    ToDoContract.ToDoEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
                    ToDoContract.ToDoEntry.COLUMN_TASK_TITLE + "TEXT NOT NULL);";

    private static final String SQL_DELETE_ENTRIES =
            "DROP TABLE IF EXISTS " + ToDoContract.ToDoEntry.TABLE_NAME;

    public ToDoDbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    public void onCreate(SQLiteDatabase db) {
        db.execSQL(SQL_CREATE_ENTRIES);
    }

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL(SQL_DELETE_ENTRIES);
        onCreate(db);
    }

    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        onUpgrade(db, oldVersion, newVersion);
    }
}

The Contract:

package nemphys.listitup.model;

import android.provider.BaseColumns;

public final class ToDoContract {
    private ToDoContract() {
    }

    public static class ToDoEntry implements BaseColumns {
        public static final String TABLE_NAME = "tasks";
        public static final String COLUMN_TASK_TITLE = "title";
    }
}

The logcat:

04-30 13:28:37.718 22986-22986/nemphys.listitup E/SQLiteLog: (1) no such column: title
04-30 13:28:37.722 22986-22986/nemphys.listitup D/AndroidRuntime: Shutting down VM
04-30 13:28:37.723 22986-22986/nemphys.listitup E/AndroidRuntime: FATAL EXCEPTION: main
                                                                  Process: nemphys.listitup, PID: 22986
                                                                  java.lang.RuntimeException: Unable to start activity ComponentInfo{nemphys.listitup/nemphys.listitup.activity.MainActivity}: android.database.sqlite.SQLiteException: no such column: title (code 1): , while compiling: SELECT _id, title FROM tasks
                                                                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
                                                                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
                                                                      at android.app.ActivityThread.-wrap11(ActivityThread.java)
                                                                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
                                                                      at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                      at android.os.Looper.loop(Looper.java:148)
                                                                      at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                      at java.lang.reflect.Method.invoke(Native Method)
                                                                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                                                                   Caused by: android.database.sqlite.SQLiteException: no such column: title (code 1): , while compiling: SELECT _id, title FROM tasks
                                                                      at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
                                                                      at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:887)
                                                                      at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:498)
                                                                      at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
                                                                      at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
                                                                      at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
                                                                      at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
                                                                      at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1316)
                                                                      at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1163)
                                                                      at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1034)
                                                                      at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1202)
                                                                      at nemphys.listitup.model.ToDoModel.getToDoList(ToDoModel.java:29)
                                                                      at nemphys.listitup.activity.MainActivity.onCreate(MainActivity.java:36)
                                                                      at android.app.Activity.performCreate(Activity.java:6237)
                                                                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
                                                                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
                                                                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
                                                                      at android.app.ActivityThread.-wrap11(ActivityThread.java) 
                                                                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
                                                                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                      at android.os.Looper.loop(Looper.java:148) 
                                                                      at android.app.ActivityThread.main(ActivityThread.java:5417) 
                                                                      at java.lang.reflect.Method.invoke(Native Method) 
                                                                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

In a previous version of my application I stored the reference to the SQLiteOpenHelper in the main activity and everything went fine. Now that i introduced the model in my application I just can't make it work.

Thanks in advance!

Aucun commentaire:

Enregistrer un commentaire