【问题标题】:Application keeps crashing when trying to save appointment information?尝试保存约会信息时应用程序不断崩溃?
【发布时间】:2018-04-19 04:33:05
【问题描述】:

我正在为理发店构建一个应用程序,我现在正在创建一个约会并保存该约会的数据,但是当我点击添加以创建约会时,应用程序崩溃并且我留下这个错误;

E/CursorWindow: Failed to read row 0, column -1 from a CursorWindow which has 2 rows, 3 columns.
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: ie.app.barbershop, PID: 31270
                  java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
                      at android.database.CursorWindow.nativeGetString(Native Method)
                      at android.database.CursorWindow.getString(CursorWindow.java:438)
                      at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
                      at ie.app.barbershop.TableControllerAppointments.read(TableControllerAppointments.java:46)
                      at ie.app.barbershop.Landing.readRecords(Landing.java:47)
                      at ie.app.barbershop.OnClickListenerCreateAppointment$1.onClick(OnClickListenerCreateAppointment.java:38)
                      at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:162)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:135)
                      at android.app.ActivityThread.main(ActivityThread.java:5254)
                      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:903)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
I/Process: Sending signal. PID: 31270 SIG: 9
Application terminated.

这是我的 TableControllerAppointments.java

课程
package ie.app.barbershop;

import android.content.Context;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.util.ArrayList;
import java.util.List;

public class TableControllerAppointments extends DatabaseHandler {

    public TableControllerAppointments(Context context) {
        super(context);
    }

    public boolean create(ObjectAppointment objectAppointments) {

        ContentValues values = new ContentValues();

        values.put("fullname", objectAppointments.fullName);
        values.put("contactno", objectAppointments.contactNumber);

        SQLiteDatabase db = this.getWritableDatabase();

        boolean createSuccessful = db.insert("appointments", null, values) > 0;
        db.close();

        return createSuccessful;
    }



    public List<ObjectAppointment> read() {

        List<ObjectAppointment> recordsList = new ArrayList<>();

        String sql = "SELECT * FROM Appointments ORDER BY id DESC";

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(sql, null);

        if (cursor.moveToFirst()) {
            do {

                String fullName = cursor.getString(cursor.getColumnIndex("firstname"));
                int contactNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex("contactno")));

                ObjectAppointment objectAppointment = new ObjectAppointment();
                objectAppointment.fullName = fullName;
                objectAppointment.contactNumber = contactNumber;

                recordsList.add(objectAppointment);

            } while (cursor.moveToNext());
        }

        cursor.close();
        db.close();

        return recordsList;
    }

    public int count() {

        SQLiteDatabase db = this.getWritableDatabase();

        String sql = "SELECT * FROM appointments";
        int recordCount = db.rawQuery(sql, null).getCount();
        db.close();

        return recordCount;
    }
}

这是我的 OnClickListenerCreateAppointment.java

课程
package ie.app.barbershop;

import android.view.View;
import android.content.Context;
import android.view.LayoutInflater;
import android.widget.EditText;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.widget.Toast;

public class OnClickListenerCreateAppointment implements View.OnClickListener {

    public ObjectAppointment objectAppointment;

    @Override
    public void onClick(View view){

        final Context context = view.getRootView().getContext();
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        final View formElementsView = inflater.inflate(R.layout.appointment_input_form, null, false);
        final EditText editTextFullName = formElementsView.findViewById(R.id.editTextFullName);
        final EditText editTextContactNumber = formElementsView.findViewById(R.id.editTextContactNumber);

        ObjectAppointment objectAppointment = new ObjectAppointment();


        new AlertDialog.Builder(context)




                .setView(formElementsView)
                .setTitle("Create Appointment")
                .setPositiveButton("Add",
                        new DialogInterface.OnClickListener() {

                            public void onClick(DialogInterface dialog, int id) {


                                String fullname = editTextFullName.getText().toString();
                                String contactno = editTextContactNumber.getText().toString();

                                ((Landing) context).countRecords();
                                ((Landing) context).readRecords();

                                dialog.cancel();
                            }

                        }).show();

            boolean createSuccessful = new TableControllerAppointments(context).create(objectAppointment);

                if(createSuccessful){
                    Toast.makeText(context, "Appointment Information was saved.", Toast.LENGTH_SHORT).show();
                }else{
                    Toast.makeText(context, "Unable to save appointment information", Toast.LENGTH_SHORT).show();
        }


    }
}

这是我的 Landing.java 类

package ie.app.barbershop;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;

import java.util.List;


public class Landing extends AppCompatActivity{

    public Button buttonProducts;

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

        countRecords();

        buttonProducts = findViewById(R.id.buttonProducts);

        Button buttonCreateAppointment = findViewById(R.id.buttonCreateAppointment);
        buttonCreateAppointment.setOnClickListener(new OnClickListenerCreateAppointment());

        buttonProducts.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(Landing.this, Products.class));
            }
        });


    }

    public void readRecords() {

        LinearLayout linearLayoutRecords = findViewById(R.id.linearLayoutRecords);
        linearLayoutRecords.removeAllViews();

        List<ObjectAppointment> appointments = new TableControllerAppointments(this).read();

        if (appointments.size() > 0) {

            for (ObjectAppointment obj : appointments) {


                String fullName = obj.fullName;
                int contactNumber = obj.contactNumber;

                String textViewContents = fullName + " - " + contactNumber;

                TextView textViewAppointmentItem= new TextView(this);
                textViewAppointmentItem.setPadding(0, 10, 0, 10);
                textViewAppointmentItem.setText(textViewContents);
                textViewAppointmentItem.setTag(Integer.toString(contactNumber));

                linearLayoutRecords.addView(textViewAppointmentItem);
            }

        }

        else {

            TextView locationItem = new TextView(this);
            locationItem.setPadding(8, 8, 8, 8);
            locationItem.setText("No records yet.");

            linearLayoutRecords.addView(locationItem);
        }

    }

    public void countRecords(){

        int recordCount = new TableControllerAppointments(this).count();

        TextView textViewRecordCount = findViewById(R.id.textViewRecordCount);
        textViewRecordCount.setText(recordCount + " records found.");

    }
}

数据库处理程序类

   package ie.app.barbershop;

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



public class DatabaseHandler extends SQLiteOpenHelper {
    private static final int DATABASE_VERSION = 1;
    protected static final String DATABASE_NAME = "AppointmentDatabase";

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

    @Override
    public void onCreate(SQLiteDatabase db) {

        String sql = "CREATE TABLE appointments " +
                "( id INTEGER PRIMARY KEY AUTOINCREMENT, " +
                "fullname TEXT, " +
                "contactno NUMBER ) ";

        db.execSQL(sql);

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        String sql = "DROP TABLE IF EXISTS students";
        db.execSQL(sql);

        onCreate(db);
    }
}

【问题讨论】:

  • TableControllerAppointments 类的方法read 中调用getString 说“列-1”:该方法中只有一个这样的调用,这意味着cursor.getColumnIndex("firstname") 返回-1,而@987654321 @ 表示:“返回给定列名的从零开始的列索引,如果列名不存在,则返回 -1”。 --- 因此,Appointments 没有名为 firstname 的列。弄清楚这一点有什么难的?
  • 请为表Appointments发布CREATE TABLE声明
  • 错误是不言自明的光标没有列firstname
  • 抱歉添加了数据库处理程序
  • @AaronBratSmith 这不是 DatabaseHandler,你已经发布了两次 Landing

标签: java android android-sqlite android-cursor


【解决方案1】:

从 getColumnIndex 返回的 -1 表示列 firstname 下一行的光标中不存在。

 String fullName = cursor.getString(cursor.getColumnIndex("firstname"));

您使用以下方法创建表:-

String sql = "CREATE TABLE appointments " +
                "( id INTEGER PRIMARY KEY AUTOINCREMENT, " +
                "fullname TEXT, " +
                "contactno NUMBER ) ";

其中的列是 id fullname 和 contactno。

--

修复

要修复此更改以使用:-

String fullName = cursor.getString(cursor.getColumnIndex("fullname"));

附加

最好还是将列名和表名定义为常量并始终引用它们。

例如

public class DatabaseHandler extends SQLiteOpenHelper {
    private static final int DATABASE_VERSION = 1;
    protected static final String DATABASE_NAME = "AppointmentDatabase";

    public static final String TABLE_NAME = "appointments";
    public static final String COL_ID = "id";
    public static final String COl_FULLNAME = "fullname";
    public static final String COL_CONTACTNO = "contactno";

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

    @Override
    public void onCreate(SQLiteDatabase db) {

        String sql = "CREATE TABLE " + TABLE_NAME +
                "( " + COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COL_FULLNAME + " TEXT, " +
                COL_CONTACTNO + " NUMBER ) ";

        db.execSQL(sql);

    }
    .... and so on

稍后作为一个例子:-

    String fullName = cursor.getString(cursor.getColumnIndex(DatabaseHandler.COL_FULLNAME));

【讨论】:

    猜你喜欢
    • 2018-10-06
    • 1970-01-01
    • 2015-10-11
    • 1970-01-01
    • 2018-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多