Пример с некоторыми улучшениями / соображениями (возможно)
Приведенный ниже код может дать вам некоторые идеи / приемы и основан на ответах (я включу весь код, который должен помочь вам обойти приложениесбой при запуске).
Первым улучшением является загрузка ListView при запуске Activity.Это было довольно просто, просто вызовите метод ShowRecords
.Это устраняет необходимость в кнопке «Просмотр» (см. Позже, как она была поднята).
Однако метод ShowRecords
был радикально изменен.Для создания отдельных экземпляров Адаптера и исходного списка клиентов.
В кнопки добавлена логика / интеллект (sic).Те, которые не применимы, выделены серым цветом.- Изначально вы ничего не можете удалить или обновить, вы можете только добавить (добавить, не добавлять, любые данные опущены).- Если вы щелкнете по элементу в списке, эти данные будут загружены в EditTexts, и кнопка «Удалить» - единственная кнопка, которую можно нажать.- Если вы измените значение в EditText, то будет нажата только кнопка «Обновить».
Все действия работают, а также обновляют список (если доступно в соответствии с логикой выше).Таким образом, записи могут быть добавлены, обновлены и удалены.
Кнопка просмотра была нажата, теперь она является кнопкой CLEAR.Это всегда доступно и очищает EditTexts и устанавливает кнопку «Добавить» как доступную (нажатие на элемент списка по-прежнему загружает данные этой записи).
Для облегчения описанного выше были определены некоторые новые переменные класса, а также некоторыебыли перенесены из переменных метода в переменные класса, например, Adapter и Customer List (вы уже объявили da , так что это использовалось).
Подавляющее большинство изменений относится только кCustomerRcrdActivity, хотя в DatabaseHelper были внесены некоторые незначительные изменения ( long для идентификатора, что является правильной практикой, поскольку идентификатор может превышать максимальное значение int ).
В любом случае вот код: -
CustomerRcrdActivity : -
public class CustomerRcrdActivity extends AppCompatActivity {
private EditText FName, LName, CarMake, CarModel, CarCost;
private String F_Name;
private String L_Name;
private String Car_Make;
private String Car_Model;
private double d_Car_Cost;
private DatabaseHandler dh;
private dataAdapter da;
private Customer dataModel;
private ListView lv;
private long mId;
//<<<<<<<<<< new class variables
private String original_FName, original_LName, original_CarMake, original_CarModel, original_CarCost;
private boolean mLoaded = false;
private Button mViewButton, mUpdateButton, mAddButton, mDeleteButton;
private ArrayList<Customer> mCustomers = new ArrayList<>();
private List<EditText> mAlleditTexts = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_customer_rcrd);
// GET Intent THAT STARTED ACTIVITY
Intent intent = getIntent();
// INSTANTIATE DATABASE HANDLER
dh = new DatabaseHandler(this);
FName = (EditText) findViewById(R.id.editText2_FName);
LName = (EditText) findViewById(R.id.editText2_LName);
CarMake = (EditText) findViewById(R.id.editText2_CarMake);
CarModel = (EditText) findViewById(R.id.editText2_CarModel);
CarCost = (EditText) findViewById(R.id.editText2_CarCost);
//<<<<<<<<<<< ADDED
mAlleditTexts.add(FName);
mAlleditTexts.add(LName);
mAlleditTexts.add(CarMake);
mAlleditTexts.add(CarModel);
mAlleditTexts.add(CarCost);
lv = (ListView) findViewById(R.id.lv);
//<<<<<<<<<< END OF ADDED
mViewButton = (Button) findViewById(R.id.button_CR_view);
mAddButton = (Button) findViewById(R.id.button_CR_add);
mUpdateButton = (Button) findViewById(R.id.button_CR_update);
mDeleteButton = (Button) findViewById(R.id.button_CR_delete);
mViewButton.setVisibility(View.GONE); // never Show and free screen space
mViewButton.setText("CLEAR"); // Hijack View Button for clear data
mViewButton.setVisibility(View.VISIBLE); // Show the View (now CLEAR)
mAddButton.setEnabled(false); // Can't click Add as nothing to add
mUpdateButton.setEnabled(false); // Can't click Update nothing to update
mDeleteButton.setEnabled(false); // Can't click Delete as nothing to delete
setOriginalValues();
ShowRecords(); //<<<< Always show the list no need for View button
setEditTextFocusChangedListener(mAlleditTexts);
}
//<<<<<<<<<< NEW METHOD
private void setEditTextFocusChangedListener(List<EditText> edit_texts) {
for (EditText e: edit_texts) {
e.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (areOriginalValuesChanged()) {
if (mLoaded) {
mUpdateButton.setEnabled(true);
mDeleteButton.setEnabled(false);
mAddButton.setEnabled(false);
} else {
}
} else {
if (!mLoaded) {
mAddButton.setEnabled(true);
} else {
mAddButton.setEnabled(false);
}
}
}
});
}
}
//<<<<<<<<<< NEW METHOD
private void setOriginalValues() {
original_FName = FName.getText().toString();
original_LName = LName.getText().toString();
original_CarMake = CarMake.getText().toString();
original_CarModel = CarModel.getText().toString();
original_CarCost = CarCost.getText().toString();
}
//<<<<<<<<<< NEW METHOD
private boolean areOriginalValuesChanged() {
if (original_FName.equals(FName.getText().toString())
&& original_LName.equals(LName.getText().toString())
&& original_CarMake.equals(CarMake.getText().toString())
&& original_CarModel.equals(CarModel.getText().toString())
&& original_CarCost.equals(CarCost.getText().toString())
) {
return false;
}
return true;
}
//<<<<<<<<<< NEW METHOD
private void clearEditTexts(List<EditText> editTexts) {
for (EditText e: editTexts) {
e.setText("");
}
setOriginalValues();
mLoaded = false;
}
public void buttonClicked(View view)
{
int id = view.getId();
switch (id)
{
case R.id.button_CR_update:
// CALL updateCustomer() TO UPDATE CUSTOMER RECORDS
updateCustomer();
mLoaded = false;
break;
case R.id.button_CR_add:
// CALL addCustomer() TO ADD TO DATABASE
addCustomer();
clearEditTexts(mAlleditTexts);
mLoaded = false;
// START NEW ACTIVITY WHEN ADD BUTTON CLICKED
//Intent intent = new Intent(this, DatabaseHandler.class);
//startActivity(intent);
break;
case R.id.button_CR_delete:
// CALL deleteCustomer() TO DELETE CUSTOMER RECORD
deleteCustomer();
break;
case R.id.button_CR_view:
// CALL viewCustomer() TO VIEW CUSTOMER RECORD
// START NEW ACTIVITY WHEN ADD BUTTON CLICKED
//Intent intent2 = new Intent(this, CustomerDBActivity.class);
//startActivity(intent2);
// CALL showRecords() TO VIEW CUSTOMER RECORD VIA ListView
clearEditTexts(mAlleditTexts);
mLoaded = false;
mAddButton.setEnabled(true);
mUpdateButton.setEnabled(false);
mDeleteButton.setEnabled(false);
break;
}
ShowRecords(); // Update the List irrespective of button clicked
}
private void updateCustomer()
{
getValues();
if (dh.updateCustomer(dataModel, mId)>0) {
Toast.makeText(getApplicationContext(), "Customer Updated Successfully", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Customer Not Updated", Toast.LENGTH_LONG).show();
}
}
// INSERT DATA INTO DATABASE
private void addCustomer()
{
boolean ok_to_add = true;
getValues();
if (F_Name == null || F_Name.length() < 1) ok_to_add = false;
if (L_Name == null || L_Name.length() < 1) ok_to_add = false;
if (Car_Make == null || Car_Make.length() < 1) ok_to_add = false;
if (Car_Model == null || Car_Model.length() < 1) ok_to_add = false;
if (ok_to_add) {
dh.addCustomers(new Customer(F_Name, L_Name, Car_Make, Car_Model, d_Car_Cost));
Toast.makeText(getApplicationContext(), "Customer Added Successfully", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Unable To Add - Some Data hasn't been given", Toast.LENGTH_LONG).show();
}
}
private void deleteCustomer()
{
getValues();
if (dh.deleteCustomer(mId)) {
Toast.makeText(getApplicationContext(), "Customer Deleted Successfully", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Customer Not Deleted", Toast.LENGTH_LONG).show();
}
}
// FUNCTION TO GET VALUES FROM EditText
private void getValues()
{
F_Name = FName.getText().toString();
L_Name = LName.getText().toString();
Car_Make = CarMake.getText().toString();
Car_Model = CarModel.getText().toString();
String car_Cost = CarCost.getText().toString();
if (car_Cost.length() < 1) {
car_Cost = "0.00";
}
d_Car_Cost = Double.parseDouble(car_Cost);
}
// RETRIEVE DATA FROM DATABASE & SET TO LIST VIEW
//<<<<<<<<<< CHANGED QUITE A BIT
// Introduced single Customer List with class scope rather than create new list and adapter everytime
// i.e. mCustomers
// Always clear mCustomers and rebuild from database
// if da (the adapter) is null and therefore hasn't been instantiated, instantiate it just once
// otherwsie always notify the adapter that the data (mCustomer) has changed
// Added code to the Listener (added just the once now) to set the edit text's to the values
// of the clicked item in the list (load the data)
// setting flag to say that the data has just been loaded.
// also setting the original values to the new data
private void ShowRecords()
{
mCustomers.clear();
mCustomers.addAll(dh.getAllCustomers());
//final ArrayList<Customer> customers = new ArrayList<>(dh.getAllCustomers());
//final Customer customers = new Customer(dh.getAllCustomers());
if (da == null) {
da = new dataAdapter(this, mCustomers);
//final dataAdapter data = new dataAdapter(this, mCustomers); //<<<< Shouldn't create a new adapter everytime
lv.setAdapter(da);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
dataModel = mCustomers.get(position);
//<<<<<<<<<< Added
FName.setText(dataModel.getFName());
LName.setText(dataModel.getLName());
CarMake.setText(dataModel.get_CarMake());
CarModel.setText(dataModel.get_CarModel());
CarCost.setText(String.valueOf(dataModel.get_CarCost()));
mLoaded = true;
setOriginalValues();
mDeleteButton.setEnabled(true);
mUpdateButton.setEnabled(false);
mAddButton.setEnabled(false);
mId = dataModel.getID();
//<<<<<<<<<< End of Added
Toast.makeText(getApplicationContext(), String.valueOf(dataModel.getID()), Toast.LENGTH_SHORT).show();
}
});
} else {
da.notifyDataSetChanged();
}
}
}
DataBaseHandler
public class DatabaseHandler extends SQLiteOpenHelper
{
// DATABASE VERSION
private static final int DATABASE_VERSION = 1;
// DATABASE NAME
private static final String DATABASE_NAME = "Car Dealer";
// PREFERRED THE NAME "STAR DEALERSHIP CUSTOMER DATABASE"
// CUSTOMER TABLE NAME
public static final String TABLE_CUSTOMERS = "Customers";
// CUSTOMER TABLE COLUMN NAMES
private static final String KEY_ID = "ID";
private static final String KEY_FNAME = "First";
private static final String KEY_LNAME = "Last";
private static final String KEY_CAR_MAKE = "Make";
private static final String KEY_CAR_MODEL = "Model";
private static final String KEY_CAR_COST = "Cost";
DatabaseHandler(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// CREATE TABLES
@Override
public void onCreate(SQLiteDatabase dh)
{
String CREATE_TABLE_CUSTOMERS = "CREATE TABLE " + TABLE_CUSTOMERS + "("
+ KEY_ID +" INTEGER PRIMARY KEY,"
+ KEY_FNAME +" TEXT,"
+ KEY_LNAME +" TEXT,"
+ KEY_CAR_MAKE +" TEXT,"
+ KEY_CAR_MODEL +" TEXT,"
+ KEY_CAR_COST +" NUMERIC" + ")";
dh.execSQL(CREATE_TABLE_CUSTOMERS);
}
// UPGRADING DATABASE
@Override
public void onUpgrade(SQLiteDatabase dh, int oldVersion, int newVersion)
{
// DROP OLDER TABLE IF EXISTED
dh.execSQL("DROP TABLE IF EXISTS " + TABLE_CUSTOMERS);
// CREATE TABLES AGAIN
onCreate(dh);
}
/**
* All CRUD (CREATE, READ, UPDATE, DELETE) OPERATIONS
*/
// INSERT VALUES TO TABLE CUSTOMERS
public void addCustomers(Customer customer)
{
SQLiteDatabase dh = this.getReadableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_FNAME, customer.getFName());
values.put(KEY_LNAME, customer.getLName() );
values.put(KEY_CAR_MAKE, customer.get_CarMake());
values.put(KEY_CAR_MODEL, customer.get_CarModel());
values.put(KEY_CAR_COST, customer.get_CarCost());
dh.insert(TABLE_CUSTOMERS, null, values);
dh.close();
}
/**
*GETTING ALL CUSTOMERS
**/
public List<Customer> getAllCustomers()
{
List<Customer> customerList = new ArrayList<Customer>();
// SELECT ALL QUERY
String selectQuery = "SELECT * FROM " + TABLE_CUSTOMERS;
SQLiteDatabase dh = this.getWritableDatabase();
Cursor cursor = dh.rawQuery(selectQuery, null);
// LOOP THROUGH ALL ROWS & ADD TO LIST
if (cursor.moveToFirst())
{
do {
Customer customer = new Customer();
customer.setID(Integer.parseInt(cursor.getString(0)));
customer.setFName(cursor.getString(1));
customer.setLName(cursor.getString(2));
customer.set_CarMake(cursor.getString(3));
customer.set_CarModel(cursor.getString(4));
customer.set_CarCost(cursor.getDouble(5));
// ADDING CUSTOMER TO LIST
customerList.add(customer);
} while (cursor.moveToNext());
}
// CLOSE OUT RAW QUERY CALL
cursor.close();
// RETURN CUSTOMER LIST
return customerList;
}
/**
*UPDATING SINGLE CUSTOMER
**/
public int updateCustomer(Customer customer, long id)
{
if (customer == null) {
return 0;
}
SQLiteDatabase dh = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_FNAME, customer.getFName());
values.put(KEY_LNAME, customer.getLName());
values.put(KEY_CAR_MAKE, customer.get_CarMake());
values.put(KEY_CAR_MODEL, customer.get_CarModel());
values.put(KEY_CAR_COST, customer.get_CarCost());
// UPDATING ROW
return dh.update(TABLE_CUSTOMERS, values, KEY_ID + " = ?",
new String[] { String.valueOf(id) });
}
/**
*DELETING SINGLE CUSTOMER
**/
public boolean deleteCustomer(long Id)
{
boolean rv = false;
SQLiteDatabase dh = this.getWritableDatabase();
rv = (dh.delete(TABLE_CUSTOMERS, KEY_ID + " = ?",
new String[] { String.valueOf(Id) }) > 0);
dh.close();
return rv;
}
}
Клиент
- Примечание это, возможно, весьма отличается от вашего, хотя, возможно, довольно близко.Главное, что следует отметить, это то, что CustomerId имеет длину long , в противном случае, если рассматривать CustomerRcrdActivity , оно имитирует ваше.
: -
public class Customer {
private long CustomerId;
private String FName;
private String LName;
private String CarMake;
private String CarModel;
private Double CarCost;
public Customer(String first_name, String last_name, String make_of_car, String model, Double cost) {
this.FName = first_name;
this.LName = last_name;
this.CarMake = make_of_car;
this.CarModel = model;
this.CarCost = cost;
}
public Customer() {
}
public void setFName(String FName) {
this.FName = FName;
}
public String getFName() {
return FName;
}
public void setLName(String LName) {
this.LName = LName;
}
public String getLName() {
return LName;
}
public void set_CarMake(String carMake) {
CarMake = carMake;
}
public String get_CarMake() {
return CarMake;
}
public void set_CarCost(Double carCost) {
CarCost = carCost;
}
public Double get_CarCost() {
return CarCost;
}
public void set_CarModel(String carModel) {
CarModel = carModel;
}
public String get_CarModel() {
return CarModel;
}
public void setCustomerId(long customerId) {
CustomerId = customerId;
}
public long getCustomerId() {
return CustomerId;
}
public long getID() {
return this.getCustomerId();
}
public void setID(long id) {
this.setCustomerId(id);
}
}
Макеты Все макеты должны повторять ваши, поэтому нет необходимости их включать (ваши, вероятно, будут намного лучше, чемте, что используются для этого, минимальны).
MainActivity
Это не что иное, как запуск CustomerRcrdActivity
, и, как таковое, очень просто: -
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent i = new Intent(this,CustomerRcrdActivity.class);
startActivity(i);
}
}
- Заметка с помощью возврата из
CustomerRcrdActivity
приведет вас к пустому экрану, и вы больше ничего не сможете сделать.
Макет - это базовый текстовый элемент TextView, генерируемый при создании проекта: -
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
AndroidManiFest.xml
Опять же, это довольно просто, только что в него были внесены изменения, чтобы иметь раздел активности для CustomerRcrdActivity
: -
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".CustomerRcrdActivity">
</activity>
</application>
Примечание имя пакета (3-я строка), скорее всего, будет неправильным, если вы использовали вышеизложенное, поэтому его необходимо изменить.