我正在开发一个在 Android Studio 中使用 Java 的大学课程项目。这是作业:创建一个包含两个表单的活动应用程序。主窗体应该有一个列表视图、一个添加按钮、一个编辑按钮、一个查看按钮和一个删除按钮。单击任何按钮时,您应该将用户导航到第二个表单,该表单将使用使用意图对象传递的数据为按钮操作正确填充。您的第二个表单应该是输入姓名和地址的布局。您将需要一个“确定”、“取消”和“清除”按钮。如果用户单击“清除”按钮,您需要清除所有条目。如果用户单击“确定”或“取消”按钮,您应该使用意图对象将按钮选择和表单数据返回到主表单。主要活动应处理响应并添加、更新或删除记录。
当我尝试保存地址时,出现以下错误: Attempt to invoke virtual method android.database.sqlite.SQLiteDatabase Com.example.program5.AddressDatabaseHelper.getWritableDatabse() on an null object reference
我是编程新手和右脑,所以我可能遗漏了一些明显的东西,但希望能得到任何帮助。谢谢你。这是我的代码:地址收集类
package com.example.program4;
import android.content.Context;
import java.util.ArrayList;
public class AddressCollection {
ArrayList<AddressAttributeGroup> addressList = new ArrayList<AddressAttributeGroup>();
final int MAXIMUM_ADDRESS_COUNT = 10;
public AddressAttributeGroup address;
//boolean that checks if amount of records in arrayList equal to or greater than limit
public boolean isAddressLimitReached()
{
return (addressList.size() >= MAXIMUM_ADDRESS_COUNT);
}
public int addAddress(AddressAttributeGroup address) throws Exception {
this.address = address;
//if arrayList is full
if (isAddressLimitReached())
{
throw (new Exception("Maximum Address Reached."));
}
//adds new address to the arraylist addressList
addressList.add(address);
//returns the index of address
return addressList.indexOf(address);
}
public void setAddress(int addressIndex, AddressAttributeGroup address) {
addressList.set(addressIndex, address);
}
public void removeAddress(int addressIndex) {
//removes address at the index addressIndex
addressList.remove(addressIndex);
}
public AddressAttributeGroup getAddress(int addressIndex) {
return addressList.get(addressIndex);
}
static class AddressCollectionDB extends AddressCollection
{public static AddressDataSource addressData;
public static AddressCollection AddressCollectionFactory(Context context)
{
AddressCollection rCode = new AddressCollection();
addressData = new AddressDataSource(context);
try {
addressData.open();
rCode = addressData.getAllAddresses();
addressData.close();
}
catch (Exception e) {
e.printStackTrace();
}
return rCode;
}
public int addAddress (AddressAttributeGroup address) throws Exception
{
if (isAddressLimitReached())
throw (new Exception("Maximum Address Reached."));
addressData.open();
address.id = addressData.createAddress(address);
addressData.close();
return super.addAddress(address);
}
public void setAddress ( int addressIndex, AddressAttributeGroup address)
{
addressData.open();
addressData.deleteAddress(getAddress(addressIndex));
address.id = addressData.createAddress(address);
addressData.close();
super.setAddress(addressIndex, address);
}
public void removeAddress ( int addressIndex)
{
addressData.open();
addressData.deleteAddress(getAddress(addressIndex));
addressData.close();
super.removeAddress(addressIndex);
}
}
地址控制台类
package com.example.program4;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.program4.StrongIntent.TypeOfAction;
import com.example.program4.AddressCollection.AddressCollectionDB;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class AddressConsole extends Activity implements View.OnClickListener,
ListView.OnItemClickListener, ListView.OnItemSelectedListener {
Button cmdAdd;
Button cmdDelete;
Button cmdView;
Button cmdEdit;
TextView textAddressMessage;
EditText editRecordNumber;
ListView listOfAddresses;
final int ADDRESS_ENTRY = 1001;
AddressCollectionDB addresses;
AddressDataSource addressData;
//AddressCollection addresses = new AddressCollection();
AddressArrayAdapter addressAdapter;
int recordNumber = -1;
@Override
protected void onCreate(Bundle saveInstanceState)
{
super.onCreate(saveInstanceState);
setContentView(R.layout.address_console);
textAddressMessage = findViewById(R.id.textAddressMessage);
editRecordNumber = findViewById(R.id.editRecordNumber);
cmdAdd = findViewById(R.id.cmdAdd);
cmdAdd.setOnClickListener(this);
cmdEdit = findViewById(R.id.cmdEdit);
cmdEdit.setOnClickListener(this);
cmdDelete = findViewById(R.id.cmdDelete);
cmdDelete.setOnClickListener(this);
cmdView = findViewById(R.id.cmdView);
cmdView.setOnClickListener(this);
listOfAddresses = findViewById(R.id.listOfAddresses);
listOfAddresses.setOnItemClickListener (this);
listOfAddresses.setOnItemSelectedListener( this);
addresses = (AddressCollectionDB) AddressCollectionDB.AddressCollectionFactory(this);
addressAdapter = new AddressArrayAdapter(this, android.R.layout.simple_list_item_1,
android.R.id.text1,
addresses);
listOfAddresses.setAdapter(addressAdapter);
}
void displayError(Exception message) {
Toast.makeText(this,message.getMessage(),Toast.LENGTH_LONG).show();
}
void displayError(String message){
Toast.makeText(this,message,Toast.LENGTH_LONG).show();
}
void displayInfo(String message)
{
Toast.makeText(this, message,Toast.LENGTH_SHORT).show();
}
void displayAddressMessage(AddressAttributeGroup address)
{
textAddressMessage.setText("Address: " + address.firstName + " " + address.lastName + " " + address.streetAddress +
" "+ address.town + " " + address.state + " " + address.zip);
}
void clearAddressMessage()
{
textAddressMessage.setText("");
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_address_message,menu);
return true;
}
@Override
protected void onStart()
{
super.onStart();
}
@Override
public void onClick(View view) {
StrongIntent intent;
//if user clicks add button
if(cmdAdd.getId() == view.getId())
{
//if address limit has not been reached
if(!addresses.isAddressLimitReached())
{
//intent equals new Strong Intent
intent = new StrongIntent();
//intent action is equal to ADD
intent.action = TypeOfAction.ADD;
startActivityForResult(intent.getIntent(this, AddressEntry.class),ADDRESS_ENTRY);
}
//else
else
//calls display error message
displayError("Maximum Number Of Addresses Reached!");
}
else
{
try {
{
AddressAttributeGroup address = addresses.getAddress(recordNumber);
//if user clicks edit
if(cmdEdit.getId() == view.getId())
{
//intent equals new StrongIntent passing address, typeOfAction and record number as arguments
intent = new StrongIntent(address,TypeOfAction.EDIT,recordNumber);
startActivityForResult(intent.getIntent(this,AddressEntry.class),ADDRESS_ENTRY);
}
//if user clicks delete button
if(cmdDelete.getId()==view.getId())
{
//intent equals StrongIntent passing address DELETE and record number as arguments
intent = new StrongIntent(address, TypeOfAction.DELETE,recordNumber);
startActivityForResult(intent.getIntent(this,AddressEntry.class),ADDRESS_ENTRY);
}
//if user clicks view
if(cmdView.getId() == view.getId())
{
//calls displayAddressMessage and passes address as an argument
displayAddressMessage(address);
}
}
//catch block
} catch (Exception ex) {
displayError(ex);
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
StrongIntent addressIntent = new StrongIntent(data);
if (requestCode == ADDRESS_ENTRY) {
try {
//switch statement passes resultCode as argument
switch (resultCode) {
case RESULT_OK:
AddressAttributeGroup address = new AddressAttributeGroup(addressIntent.addressIndex,addressIntent.firstName, addressIntent.lastName,
addressIntent.streetAddress, addressIntent.town, addressIntent.state, addressIntent.zip);
switch (addressIntent.action) {
case ADD:
addresses.addAddress(address);
displayAddressMessage(address);
displayInfo("Added" //+ address.firstName + " " + address.lastName + " " +address.streetAddress
// + " " + address.town + " " + address.state + " "+ address.zip
);
break;
case DELETE:
addresses.removeAddress(addressIntent.addressIndex);
displayInfo("Address Deleted");
clearAddressMessage();
editRecordNumber.setText("");
recordNumber = -1;
break;
case EDIT:
addresses.setAddress(addressIntent.addressIndex,address);
displayAddressMessage(address);
displayInfo("Address Updated");
break;
}
addressAdapter.notifyDataSetChanged();
break;
case RESULT_CANCELED:
displayInfo("Cancelled");
break;
}
}
//catch block
catch(Exception ex)
{
displayError(ex);
}
}
super.onActivityResult(requestCode,resultCode,data);
}
// @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
onItemSelected(parent, view, position,id);
AddressAttributeGroup address = addresses.getAddress(recordNumber);
displayAddressMessage(address);
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
recordNumber = position;
editRecordNumber.setText(String.valueOf(recordNumber));
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
class AddressArrayAdapter extends ArrayAdapter<AddressAttributeGroup> {
private final Context context;
private final AddressCollection addresses;
public AddressArrayAdapter(Context context, int resource,int textViewResourceId, AddressCollection addresses) {
super(context, resource, textViewResourceId, addresses.addressList);
this.context = context;
this.addresses = addresses;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
AddressAttributeGroup address = addresses.getAddress(position);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.row_layout, parent, false);
TextView firstNameTextView = rowView.findViewById(R.id.editFirstName);
TextView lastNameTextView = rowView.findViewById(R.id.editLastName);
TextView addressTextView = rowView.findViewById(R.id.editStreetAddress);
TextView townTextView = rowView.findViewById(R.id.editTown);
TextView stateTextView = rowView.findViewById(R.id.editState);
TextView zipTextView = rowView.findViewById(R.id.editZip);
firstNameTextView.setText(address.firstName);
lastNameTextView.setText(address.lastName);
addressTextView.setText(address.streetAddress);
townTextView.setText(address.town);
stateTextView.setText(address.state);
zipTextView.setText(address.zip);
return rowView;
}
}
}
地址数据库助手类
package com.example.program4;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.*;
import com.example.program4.AddressCollection.AddressCollectionDB;
public class AddressDatabaseHelper extends SQLiteOpenHelper
{
//declares table, columns, and database
public static final String TABLE_ADDRESS = "address";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_FIRSTNAME = "firstName";
public static final String COLUMN_LASTNAME ="lastName";
public static final String COLUMN_STREET_ADDRESS = "streetAddress";
public static final String COLUMN_TOWN = "town";
public static final String COLUMN_STATE = "state";
public static final String COLUMN_ZIP ="zip";
private static final String DATABASE_NAME = "address.db";
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_CREATE_SQL = "create table "
+ TABLE_ADDRESS + "("
+ COLUMN_ID + " integer primary key autoincrement, "
+COLUMN_FIRSTNAME + " text not null, "
+COLUMN_LASTNAME + "text not null, "
+COLUMN_STREET_ADDRESS + "text not null, "
+COLUMN_TOWN + "text not null, "
+COLUMN_STATE + "text not null, "
+COLUMN_ZIP + "text not null);";
public AddressDatabaseHelper(Context c)
{
//pass database name, null and the database version
super(c, DATABASE_NAME,null, DATABASE_VERSION);
}
//onCreate method creates table
@Override
public void onCreate(SQLiteDatabase database)
{
//directly executes SQl statement create table
database.execSQL(DATABASE_CREATE_SQL);
}
//onUpgrade method upgrades the table
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
//drops table if it exists
db.execSQL("DROP TABLE IF EXISTS " + TABLE_ADDRESS);
//calls onCreate method and passes db as an argument
onCreate(db);
}
}
class AddressDataSource
{ // declares SQLDatabase
private SQLiteDatabase database;
//declares AddressDatabaseHelper dbHelper
private AddressDatabaseHelper dbHelper;
//declares String array allColumns
private String[] allColumns = { AddressDatabaseHelper.COLUMN_ID,
AddressDatabaseHelper.COLUMN_FIRSTNAME, AddressDatabaseHelper.COLUMN_LASTNAME,
AddressDatabaseHelper.COLUMN_STREET_ADDRESS, AddressDatabaseHelper.COLUMN_TOWN,
AddressDatabaseHelper.COLUMN_STATE, AddressDatabaseHelper.COLUMN_ZIP };
//AddressDataSource passes c as argument
public AddressDataSource(Context c)
{
dbHelper = new AddressDatabaseHelper(c);
}
//open method
public void open() throws SQLException {
//sets database equal to dbHelper.getWritableDatabase
database = dbHelper.getWritableDatabase();
}
//close method
public void close()
{
//closes dbHelper
dbHelper.close();
}
//createAddress method passes address as argument
public long createAddress(AddressAttributeGroup address)
{
//creates new ContentValues object called values
ContentValues values = new ContentValues();
//puts values of firstname and lastname into COLUMN_NAME
values.put(AddressDatabaseHelper.COLUMN_FIRSTNAME, address.firstName );
values.put(AddressDatabaseHelper.COLUMN_LASTNAME, address.lastName );
values.put(AddressDatabaseHelper.COLUMN_STREET_ADDRESS, address.streetAddress);
values.put(AddressDatabaseHelper.COLUMN_TOWN, address.town);
values.put(AddressDatabaseHelper.COLUMN_STATE,address.state);
values.put(AddressDatabaseHelper.COLUMN_ZIP,address.zip);
long insertId = database.insert(AddressDatabaseHelper.TABLE_ADDRESS,null,values);
//returns insertId
return insertId;
}
//deleteAddress method passes address as argument
public void deleteAddress(AddressAttributeGroup address)
{ //sets id equal to address.id
long id = address.id;
//deletes the entry stored at address.id in the TABLE_ADDRESS table
database.delete(AddressDatabaseHelper.TABLE_ADDRESS,
AddressDatabaseHelper.COLUMN_ID + " = " + id, null);
}
//getAllAddresses method
public AddressCollectionDB getAllAddresses() throws Exception
{
AddressCollectionDB addresses = new AddressCollectionDB();
Cursor cursor = database.query(AddressDatabaseHelper.TABLE_ADDRESS,
allColumns, null, null, null, null, null);
//move cursor to first column in database
cursor.moveToFirst();
//while the cursor is not after the last entry
while (!cursor.isAfterLast())
{
//adds address to addresses
addresses.addAddress(cursorToAddressAttributeGroup(cursor));
//and moves cursor to next entry
cursor.moveToNext();
}
//closes the cursor
cursor.close();
//returns addresses
return addresses;
}
private AddressAttributeGroup cursorToAddressAttributeGroup(Cursor cursor) {
/* int idCOLUMN_ID = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_ID);
int idCOLUMN_FIRSTNAME = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_FIRSTNAME);
int idCOLUMN_LASTNAME = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_LASTNAME);
int idCOLUMN_STREET_ADDRESS = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_STREET_ADDRESS);
int idCOLUMN_TOWN = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_TOWN);
int idCOLUMN_STATE = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_STATE);
int idCOLUMN_ZIP = cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_ZIP);
if (idCOLUMN_ID >= 0 && idCOLUMN_FIRSTNAME >= 0 && idCOLUMN_LASTNAME >= 0 &&
idCOLUMN_STREET_ADDRESS >= 0 && idCOLUMN_TOWN >= 0 && idCOLUMN_STATE >= 0 && idCOLUMN_ZIP >= 0) {*/
//creates new AddressAttributeGroup called address
//returns address
// return new AddressAttributeGroup
AddressAttributeGroup address = new AddressAttributeGroup
(cursor.getInt(cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_ID)),
cursor.getString(cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_FIRSTNAME)),
cursor.getString(cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_LASTNAME)),
cursor.getString(cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_STREET_ADDRESS)),
cursor.getString(cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_TOWN)),
cursor.getString(cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_STATE)),
cursor.getString(cursor.getColumnIndex(AddressDatabaseHelper.COLUMN_ZIP)));
return address;
}
}
地址入口类
package com.example.program4;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class AddressEntry extends Activity implements View.OnClickListener{
Button cmdSave;
Button cmdClear;
Button cmdCancel;
EditText editFirstName;
EditText editLastName;
EditText editStreetAddress;
EditText editTown;
EditText editState;
EditText editZip;
int result;
StrongIntent stIntent;
@Override
public void onCreate(Bundle savedInstanceState)
{ super.onCreate(savedInstanceState);
setContentView(R.layout.address_entry);
editFirstName = findViewById(R.id.editFirstName);
editLastName = findViewById(R.id.editLastName);
editStreetAddress = findViewById(R.id.editStreetAddress) ;
editTown = findViewById(R.id.editTown);
editState = findViewById(R.id.editState);
editZip = findViewById(R.id.editZip);
cmdSave = findViewById(R.id.cmdSave);
cmdSave.setOnClickListener(this);
cmdClear = findViewById(R.id.cmdClear);
cmdClear.setOnClickListener(this);
cmdCancel = findViewById(R.id.cmdCancel);
cmdCancel.setOnClickListener(this);
stIntent = new StrongIntent(getIntent());
editFirstName.setText(stIntent.firstName);
editLastName.setText(stIntent.lastName);
editStreetAddress.setText(stIntent.streetAddress);
editTown.setText(stIntent.town);
editState.setText(stIntent.state);
editZip.setText(stIntent.zip);
//if the type of action is equal to DELETE
if (stIntent.action ==StrongIntent.TypeOfAction.DELETE)
//if user clicks Save sets text to Delete
cmdSave.setText(R.string.deleteString);
//enables action when delete is not selected
editFirstName.setEnabled(stIntent.action!=StrongIntent.TypeOfAction.DELETE);
editLastName.setEnabled(stIntent.action!=StrongIntent.TypeOfAction.DELETE);
editStreetAddress.setEnabled(stIntent.action != StrongIntent.TypeOfAction.DELETE);
editTown.setEnabled(stIntent.action != StrongIntent.TypeOfAction.DELETE);
editState.setEnabled(stIntent.action != StrongIntent.TypeOfAction.DELETE);
editZip.setEnabled(stIntent.action != StrongIntent.TypeOfAction.DELETE);
cmdClear.setEnabled(stIntent.action!=StrongIntent.TypeOfAction.DELETE);
}
@Override
public void finish()
{ //clears intent
stIntent.clearIntent();
//sets firstName equal to editFirstName
stIntent.firstName= editFirstName.getText().toString();
//sets lastName equal to editLastName
stIntent.lastName = editLastName.getText().toString();
//sets streetAddress equal to editStreetAddress
stIntent.streetAddress =editStreetAddress.getText().toString();
//sets town equal to editTown
stIntent.town = editTown.getText().toString();
//sets state equal to editState
stIntent.state = editState.getText().toString();
//sets zip equal to editZip
stIntent.zip = editZip.getText().toString();
//sets result passing result and the intent as arguments
setResult(result, stIntent.getIntent());
//calls super.finish method
super.finish();
}
@Override
public void onClick(View view)
{
//if Save is clicked
if(cmdSave.getId() == view.getId())
{
//result equals RESULT_OK
result = RESULT_OK;
//calls the finish method
finish();
}
//if Clear is clicked
if(cmdClear.getId() == view.getId())
//clears all values entered
{ editFirstName.setText("");
editLastName.setText("");
editStreetAddress.setText("");
editTown.setText("");
editState.setText("");
editZip.setText("");
}//if Cancel is clicked
if(cmdCancel.getId() == view.getId())
{ //result is equal to RESULT_CANCELED
result = RESULT_CANCELED;
//calls finish method
finish();
}
}
}