有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Android:使用光标时引发IllegaleException

我正在制作一个应用程序,将个人信息存储在SQLite数据库中,并在活动中以TableLayout的格式显示数据。为了实现这个想法,我已经创建了几个文件,如下所示

(1)增加刺激性。java:该类接受值输入,将其存储到SQLite数据库中,并将一行数据添加到表布局中,该布局将显示在ViewGroupActivity中

(2)ViewGroupActivity。java:这个类显示了一个存储个人信息的表

(3)SQLController。java:这个类定义了打开和关闭SQLite数据库、插入数据和读取条目的方法

(4)SQLiteHandler。java:这个类扩展了SQLiteOpenHelper类并处理创建数据库和表的问题

代码如下

(1)增加刺激性。爪哇

public class AddAPersonActivity extends Activity implements View.OnClickListener, AdapterView.OnItemSelectedListener, RadioGroup.OnCheckedChangeListener {
    private Button btnAdd;
    private EditText etName;
    private TextView tvDob;
    private Spinner spNationality;
    private RadioButton rbMale, rbFemale;
    private Calendar birthday;
    private NameValidator nameValidator;
    private RadioGroup rgGenderGroup;
    private TableLayout tlViewGroup;
    private String gender = "";
    private SQLController sqlController;
    private ProgressDialog progressDialog;
    private Person person;

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

        btnAdd = (Button) findViewById(R.id.btnAdd);
        etName = (EditText) findViewById(R.id.etName);
        tvDob = (TextView) findViewById(R.id.tvDob);
        spNationality = (Spinner) findViewById(R.id.spNationality);
        rbMale = (RadioButton) findViewById(R.id.rbMale);
        rbFemale = (RadioButton) findViewById(R.id.rbFemale);
        rgGenderGroup = (RadioGroup) findViewById(R.id.rgGenderGroup);
        tlViewGroup = (TableLayout) findViewById(R.id.tlViewGroup);

        // Build a table
        sqlController = new SQLController(this);
        buildTable();

        // Initialise the NameValidator
        nameValidator = new NameValidator();

        birthday = Calendar.getInstance();

        // Import countries into spNationality
        Locale[] locales = Locale.getAvailableLocales();
        ArrayList<String> countries = new ArrayList<>();
        for(Locale locale: locales) {
            String country = locale.getDisplayCountry();
            if(country.trim().length() > 0 && !countries.contains(country)) {
                countries.add(country);
            }
        }

        Collections.sort(countries);
        for(String country: countries) {
            System.out.println(country);
        }

        ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, 安卓.R.layout.simple_spinner_item, countries);
        dataAdapter.setDropDownViewResource(安卓.R.layout.simple_spinner_dropdown_item);

        spNationality.setAdapter(dataAdapter);
        spNationality.setSelection(0);

        spNationality.setOnItemSelectedListener(this);
        tvDob.setOnClickListener(this);
        rgGenderGroup.setOnCheckedChangeListener(this);
        btnAdd.setOnClickListener(this);
    }

    void updateLabel() {
        String format = "MM/dd/yy";
        SimpleDateFormat dateFormat = new SimpleDateFormat(format, Locale.US);
        tvDob.setText(dateFormat.format(birthday.getTime()));
    }

    @Override
    public void onClick(View v) {
        switch(v.getId()) {
            case R.id.btnAdd:

                // Create an instance of a person
                person = new Person();

                // set person's name
                String name = etName.getText().toString();
                person.setName(name);

                // set person's age
                Calendar today = Calendar.getInstance();
                int age = today.get(Calendar.YEAR) - today.get(Calendar.YEAR);
                if(today.get(Calendar.MONTH) < birthday.get(Calendar.MONTH)) {
                    age--;
                } else if(today.get(Calendar.MONTH) == birthday.get(Calendar.MONTH) && today.get(Calendar.DAY_OF_MONTH) < birthday.get(Calendar.DAY_OF_MONTH)) {
                    age--;
                }
                person.setAge(age);

                // set person's nationality
                String nationality = spNationality.getSelectedItem().toString();
                person.setNationality(nationality);

                // set person's created time
                DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                java.util.Date currentDate = new java.util.Date();
                Date currentTime = new Date(currentDate.getTime());
                String created_at = dateFormat.format(currentTime);
                person.setCreated_at(created_at);

                if(!(name.length() > 0)) {
                    Toast.makeText(this, "Please don't leave the name empty.", Toast.LENGTH_LONG).show();
                } else if(!(tvDob.getText().toString().length() > 0)) {
                    Toast.makeText(this, "Please set a valid birthday.", Toast.LENGTH_LONG).show();
                } else if(birthday.getTime().compareTo(new java.util.Date()) > 0) {
                    Toast.makeText(this, "Wrong birthday. Please set the valid birthday again.", Toast.LENGTH_LONG).show();
                } else if(!(rbMale.isChecked() || rbFemale.isChecked())) {
                    Toast.makeText(this, "Please choose your gender.", Toast.LENGTH_LONG).show();
                } else if(!nameValidator.validate(etName.getText().toString())) {
                    Toast.makeText(this, "Wrong name. Please enter a proper name.", Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(this, "New person is added to the database!", Toast.LENGTH_LONG).show();
                    new MyAsync().execute();
                }
                break;

            case R.id.tvDob:

                // Create a DatePickerDialog and store date info into the birthday variable.
                DatePickerDialog.OnDateSetListener date = new DatePickerDialog.OnDateSetListener() {

                    @Override
                    public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                        birthday.set(Calendar.YEAR, year);
                        birthday.set(Calendar.MONTH, monthOfYear);
                        birthday.set(Calendar.DAY_OF_MONTH, dayOfMonth);
                        updateLabel();
                    }
                };
                new DatePickerDialog(this, date, birthday.get(Calendar.YEAR), birthday.get(Calendar.MONTH), birthday.get(Calendar.DAY_OF_MONTH)).show();
                break;
        }
    }

    void addDataToRow(Person person) {

    }

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

    }

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

    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        switch(checkedId) {
            case(R.id.rbMale):
                gender = "M";
                break;
            case(R.id.rbFemale):
                gender = "F";
                break;
        }
    }


    void buildTable() {
        sqlController.open();
        Cursor cursor = sqlController.readEntry();
        int rows = cursor.getCount();
        int columns = cursor.getCount();
        cursor.moveToFirst();

        // Outer for loop
        for(int i=1; i<rows; i++) {
            TableRow row = new TableRow(this);
            row.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));

            // Inner for loop
            for(int j=0; j<columns; j++) {
                TextView textView = new TextView(this);
                textView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
                textView.setGravity(Gravity.CENTER);
                textView.setTextSize(10);
                textView.setPadding(0, 5, 0, 5);
                textView.setText(cursor.getString(j));
                row.addView(textView);
            }

            cursor.moveToNext();
            tlViewGroup.addView(row);
        }
        sqlController.close();
    }


    private class MyAsync extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            tlViewGroup.removeAllViews();

            progressDialog = new ProgressDialog(getApplicationContext());
            progressDialog.setTitle("Please wait");
            progressDialog.setMessage("Loading");
            progressDialog.setCancelable(false);
            progressDialog.show();
        }

        @Override
        protected Void doInBackground(Void... params) {
            sqlController.open();
            sqlController.insertData(person);
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPreExecute();
            buildTable();
            progressDialog.dismiss();
        }
    }
}

(2)ViewGroupActivity。爪哇

public class ViewGroupActivity extends Activity implements View.OnClickListener {
    private TableLayout tlViewGroup;
    private TextView tvName, tvAge, tvNationality, tvGender, tvCreatedAt;

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

        tlViewGroup = (TableLayout) findViewById(R.id.tlViewGroup);
        tvName = (TextView) findViewById(R.id.tvName);
        tvAge = (TextView) findViewById(R.id.tvAge);
        tvNationality = (TextView) findViewById(R.id.tvNationality);
        tvGender = (TextView) findViewById(R.id.tvGender);
        tvCreatedAt = (TextView) findViewById(R.id.tvCreatedAt);

        tvName.setOnClickListener(this);
        tvAge.setOnClickListener(this);
        tvNationality.setOnClickListener(this);
        tvGender.setOnClickListener(this);
        tvCreatedAt.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch(v.getId()) {
            case R.id.tvName:
                break;
            case R.id.tvAge:
                break;
            case R.id.tvNationality:
                break;
            case R.id.tvGender:
                break;
            case R.id.tvCreatedAt:
                break;
        }
    }
}

(3)SQLController。爪哇

public class SQLController {
    private SQLiteHandler handler;
    private Context context;
    private SQLiteDatabase db;

    public SQLController(Context context) {
        this.context = context;
    }

    public SQLController open() throws SQLiteException {
        handler = new SQLiteHandler(context);
        db = handler.getWritableDatabase();
        return this;
    }

    public void close() {
        handler.close();
    }

    public void insertData(Person person) {
        ContentValues values = new ContentValues();
        values.put(SQLiteHandler.COLUMN_NAME, person.getName());
        values.put(SQLiteHandler.COLUMN_AGE, person.getAge());
        values.put(SQLiteHandler.COLUMN_NATIONALITY, person.getNationality());
        values.put(SQLiteHandler.COLUMN_GENDER, person.getGender());
        values.put(SQLiteHandler.COLUMN_CREATED_AT, person.getCreated_at());
        db.insert(SQLiteHandler.TABLE_NAME, null, values);
    }

    public Cursor readEntry() {
        String[] allColumns = new String[] {
                SQLiteHandler.COLUMN_NAME, SQLiteHandler.COLUMN_AGE, SQLiteHandler.COLUMN_NATIONALITY, SQLiteHandler.COLUMN_GENDER,
                SQLiteHandler.COLUMN_CREATED_AT
        };

        Cursor cursor = db.query(SQLiteHandler.TABLE_NAME, allColumns, null, null, null, null, null);

        if(cursor != null) {
            cursor.moveToFirst();
        }
        return cursor;
    }
}

(4)SQLiteHandler。爪哇

public class SQLiteHandler extends SQLiteOpenHelper {

    // DB information
    static final int DB_VERSION = 1;
    static final String DB_NAME = "sortingtester.db";

    // Table information
    public static final String TABLE_NAME = "People";
    public static final String COLUMN_NAME = "Name";
    public static final String COLUMN_AGE = "Age";
    public static final String COLUMN_NATIONALITY = "Nationality";
    public static final String COLUMN_GENDER = "Gender";
    public static final String COLUMN_CREATED_AT = "Created_At";

    // Statement to create table
    private final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " ( " +
            COLUMN_NAME + " TEXT NOT NULL, " + COLUMN_AGE + " INT, " + COLUMN_NATIONALITY + " TEXT NOT NULL, " +
            COLUMN_GENDER + " CHAR(1) NOT NULL, " + COLUMN_CREATED_AT + " TEXT NOT NULL);";

    // Statement to drop table
    private final String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLE_NAME;

    public SQLiteHandler(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE);
    }

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

当运行应用程序并尝试启动AddAPersonActivity时,我甚至无法访问活动本身,因为应用程序被强制关闭,并显示以下错误消息

Caused by: java.lang.IllegalStateException: Couldn't read row 0, col 5 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
            at 安卓.database.CursorWindow.nativeGetString(Native Method)
            at 安卓.database.CursorWindow.getString(CursorWindow.java:439)
            at 安卓.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
            at com.marshall.dbtester.AddAPersonActivity.buildTable(AddAPersonActivity.java:221)
            at com.marshall.dbtester.AddAPersonActivity.onCreate(AddAPersonActivity.java:68)
            at 安卓.app.Activity.performCreate(Activity.java:5451)
            at 安卓.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1093)
            at 安卓.app.ActivityThread.performLaunchActivity(ActivityThread.java:2377)
            at 安卓.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2471)
            at 安卓.app.ActivityThread.access$900(ActivityThread.java:175)
            at 安卓.app.ActivityThread$H.handleMessage(ActivityThread.java:1308)
            at 安卓.os.Handler.dispatchMessage(Handler.java:102)
            at 安卓.os.Looper.loop(Looper.java:146)
            at 安卓.app.ActivityThread.main(ActivityThread.java:5602)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.安卓.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
            at com.安卓.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
            at dalvik.system.NativeStart.main(Native Method)

问题似乎发生在光标上,因此我认为它也与ViewGroupActivity的布局有关。因此,我还将附加ViewGroupActivity的xml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:安卓="http://schemas.安卓.com/apk/res/安卓"
    安卓:orientation="vertical" 安卓:layout_width="match_parent"
    安卓:layout_height="match_parent"
    安卓:padding="30dp"
    安卓:weightSum="1"
    安卓:background="@color/default_background">

    <TextView
        安卓:layout_width="match_parent"
        安卓:layout_height="wrap_content"
        安卓:layout_weight="0.05"
        安卓:layout_marginBottom="20dp"
        安卓:text="@string/group"
        安卓:textSize="20dp"
        安卓:textColor="@color/default_text"/>


    <ScrollView
        安卓:layout_width="match_parent"
        安卓:layout_height="match_parent"
        安卓:layout_weight="0.95">

        <TableLayout
            安卓:id="@+id/tlViewGroup"
            安卓:layout_width="match_parent"
            安卓:layout_height="wrap_content"
            安卓:orientation="horizontal"
            安卓:shrinkColumns="*"
            安卓:stretchColumns="*"
            安卓:weightSum="1">

            <TableRow>

                <TextView
                    安卓:id="@+id/tvName"
                    安卓:text="@string/name"
                    安卓:textAlignment="center"
                    安卓:layout_weight="0.2"
                    安卓:textColor="@color/default_text"/>
                <TextView
                    安卓:id="@+id/tvAge"
                    安卓:text="@string/age"
                    安卓:textAlignment="center"
                    安卓:layout_weight="0.2"
                    安卓:textColor="@color/default_text"/>
                <TextView
                    安卓:id="@+id/tvNationality"
                    安卓:text="@string/nationality"
                    安卓:textAlignment="center"
                    安卓:layout_weight="0.2"
                    安卓:textColor="@color/default_text"/>
                <TextView
                    安卓:id="@+id/tvGender"
                    安卓:text="@string/gender"
                    安卓:textAlignment="center"
                    安卓:layout_weight="0.2"
                    安卓:textColor="@color/default_text"/>
                <TextView
                    安卓:id="@+id/tvCreatedAt"
                    安卓:text="@string/created_at"
                    安卓:textAlignment="center"
                    安卓:layout_weight="0.2"
                    安卓:textColor="@color/default_text"/>
            </TableRow>

        </TableLayout>

    </ScrollView>

</LinearLayout>

我已经为这个问题挣扎了很长时间,所以你的建议将非常有用


共 (1) 个答案

  1. # 1 楼答案

    您正在将列计数设置为光标的大小

    int columns = cursor.getCount();

    用户getColumnCount(),它可能应该可以工作