- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正在开发一个使用 SQLite 数据库的 Android Studio 应用程序,该数据库可以存储汽车购买的客户记录,一旦单击“添加”按钮,该应用程序就会停止。显然,有一个空对象引用。该应用程序有一个 MainActivity,它有一个添加按钮,允许用户添加客户数据库条目。单击时,应用程序应转到 CustomerRcrdActivity 以允许数据库条目,从那里用户应该能够添加、查看、更新或删除条目所有条目应显示在屏幕上的原因。
我正在学习如何为 Android 创建应用程序,所以请多关照。我不是要你为我做任何事,但请指点我正确的方向。我到处搜索输入但担心我忽略了逻辑错误,我可以使用第二只眼睛。
如有任何意见或提示,我们将不胜感激。
非常感谢,
下面是我怀疑可能有问题的代码(我将包含 XML 以防万一我做了一些奇怪的事情)。
content_main.xml(它包括我想在添加条目时更新的 ListView )如果有更简单的方法,我不会一成不变。
<?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"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="@layout/activity_main">
<TextView
android:id="@+id/ContentMain_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-smallcaps"
android:text="@string/content_main_title"
android:textAlignment="center"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.027" />
<Button
android:id="@+id/button_CR_add"
android:layout_width="112dp"
android:layout_height="wrap_content"
android:layout_marginBottom="416dp"
android:layout_marginEnd="8dp"
android:layout_marginTop="7dp"
android:onClick="buttonClicked"
android:text="@string/ContentMain_button_CD_add"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.054"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ContentMain_title"
app:layout_constraintVertical_bias="0.022" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="486dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button_CR_add">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>
CustomerRcrdActivity 的 XML 被省略
CustomerRcrdActivity.java
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 mUpdateButton;
private Button mAddButton;
private Button 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 = findViewById(R.id.editText2_FName);
LName = findViewById(R.id.editText2_LName);
CarMake = findViewById(R.id.editText2_CarMake);
CarModel = findViewById(R.id.editText2_CarModel);
CarCost = findViewById(R.id.editText2_CarCost);
lv = findViewById(R.id.listView);
//<<<<<<<<<<< ADDED
mAlleditTexts.add(FName);
mAlleditTexts.add(LName);
mAlleditTexts.add(CarMake);
mAlleditTexts.add(CarModel);
mAlleditTexts.add(CarCost);
//<<<<<<<<<< END OF ADDED
Button mViewButton = findViewById(R.id.button_CR_view);
mAddButton = findViewById(R.id.button_CR_add);
mUpdateButton = findViewById(R.id.button_CR_update);
mDeleteButton = findViewById(R.id.button_CR_delete);
mViewButton.setVisibility(View.GONE); // never Show and free screen space
mViewButton.setText(R.string.mViewButton_setText); // 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;*/
return !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());
}
//<<<<<<<<<< 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();
// CLEAR FIELDS
clearEditTexts(mAlleditTexts);
mLoaded = false;
break;
case R.id.button_CR_delete:
// CALL deleteCustomer() TO DELETE CUSTOMER RECORD
deleteCustomer();
break;
case R.id.button_CR_view:
// CLEAR FIELDS
clearEditTexts(mAlleditTexts);
mLoaded = false;
mAddButton.setEnabled(true);
mUpdateButton.setEnabled(false);
mDeleteButton.setEnabled(false);
break;
}
// UPDATE LIST IRRESPECTIVE OF BUTTON CLICKED
ShowRecords();
}
// UPDATE CUSTOMER RECORD
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;
// GET VALUES FROM EditText
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();
}
}
// DELETE CUSTOMER RECORD
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 every time
// 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
// otherwise 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());
if (da == null)
{
da = new dataAdapter(this, mCustomers);
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();
}
}
}
数据库处理器.java
public class DatabaseHandler extends SQLiteOpenHelper
{
// DATABASE VERSION
private static final int DATABASE_VERSION = 1;
// DATABASE NAME
private static final String DATABASE_NAME = "CARDEALER.db";
// 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;
}
}
数据适配器.java
public class dataAdapter extends ArrayAdapter<Customer>
{
public dataAdapter(Context context, ArrayList<Customer> customers)
{
super(context, R.layout.list_customers, customers);
Context context1 = context;
ArrayList<Customer> mcustomer = customers;
}
public class Holder
{
TextView idV;
TextView nameFV;
TextView nameLV;
TextView carmakeV;
TextView carmodelV;
TextView carcostV;
}
@NonNull
@Override
public View getView(int position, View convertView, @NonNull ViewGroup parent)
{
// GET DATA ITEM FOR THIS POSITION
Customer data = getItem(position);
// CHECK IF EXISTING VIEW IS BEING REUSED, OTHERWISE INFLATE VIEW
// VIEW LOOKUP CACHE STORED IN TAG
Holder viewHolder;
if (convertView == null)
{
viewHolder = new Holder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.list_customers, parent, false);
viewHolder.idV = (TextView) convertView.findViewById(R.id.textView3_CustomerID);
viewHolder.nameFV = (TextView) convertView.findViewById(R.id.textView3_FName);
viewHolder.nameLV = (TextView) convertView.findViewById(R.id.textView3_LName);
viewHolder.carmakeV = (TextView) convertView.findViewById(R.id.textView3_CarMake);
viewHolder.carmodelV = (TextView) convertView.findViewById(R.id.textView3_CarModel);
viewHolder.carcostV = (TextView) convertView.findViewById(R.id.textView3_CarCost);
convertView.setTag(viewHolder);
} else
{
viewHolder = (Holder) convertView.getTag();
}
viewHolder.nameFV.setText("First Name: " + data.getFName());
viewHolder.nameLV.setText("Last Name: " + data.getLName());
viewHolder.carmakeV.setText("Car Make: " + data.get_CarMake());
viewHolder.carmodelV.setText("Car Model: " + data.get_CarModel());
viewHolder.carcostV.setText("Car Cost: " + data.get_CarCost());
// RETURN COMPLETED VIEW TO RENDER ON SCREEN
return convertView;
}
}
我包括了 MainActivity 以防我在那里遗漏了什么。这是 MainActivity.java
public class MainActivity extends AppCompatActivity
{
//public ListView lv;
@Override
protected void onCreate(Bundle savedInstanceState)
{
// even tried ListView here (R.id.listView....)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view)
{
Snackbar.make(view, "Please, click ADD button to begin! ", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_about)
{
// possibly go to another page
Toast.makeText(MainActivity.this,
"SQLite Database App", Toast.LENGTH_LONG).show();
return true;
}
return super.onOptionsItemSelected(item);
}
public void buttonClicked(View view)
{
// START NEW ACTIVITY WHEN ADD BUTTON CLICKED
Intent intent = new Intent(this, CustomerRcrdActivity.class);
startActivity(intent);
}
}
这是 Logcat 日志:
05-30 09:02:03.253 30145-30145/edu.phoenix.mbl402.week4apppp1943_rev1 E/AndroidRuntime: FATAL EXCEPTION: main
Process: edu.phoenix.mbl402.week4apppp1943_rev1, PID: 30145
java.lang.RuntimeException: Unable to start activity ComponentInfo{edu.phoenix.mbl402.week4apppp1943_rev1/edu.phoenix.mbl402.week4apppp1943_rev1.CustomerRcrdActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
at edu.phoenix.mbl402.week4apppp1943_rev1.CustomerRcrdActivity.ShowRecords(CustomerRcrdActivity.java:276)
at edu.phoenix.mbl402.week4apppp1943_rev1.CustomerRcrdActivity.onCreate(CustomerRcrdActivity.java:79)
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
此外,我已经包含了建议的修改,再次感谢您!
最佳答案
下面的代码可能会为您提供一些想法/技术,并且是基于答案(我将包含所有代码,这些代码可以帮助您解决应用程序在启动时崩溃的问题)。
第一个改进是在 Activity 启动时加载 ListView。这非常简单,只需调用 ShowRecords
方法即可。这消除了对“查看”按钮的需要(稍后会看到它已被劫持)。
但是,ShowRecords
方法已经发生了巨大的变化。合并适配器的单个实例和源客户列表。
按钮中添加了一些逻辑/智能(原文如此)。那些不适用的是灰色的。- 最初你不能删除或更新任何东西,你只能添加(添加不添加任何数据被省略)。- 如果您单击列表中的一个项目,则该数据将加载到 EditTexts 中,并且删除按钮是唯一可以单击的按钮。- 如果您更改 EditText 中的值,则只能单击“更新”按钮。
所有操作都有效并更新列表(根据上述逻辑可用时)。因此可以添加、更新和删除记录。
“查看”按钮已被劫持为“清除”按钮。这始终可用,并将清除 EditTexts 并将添加按钮设置为可用(单击列表项仍会加载该记录的数据)。
为了方便上面的操作,一些新的类变量已经被定义,还有一些已经从方法变量转移到类变量,例如Adapater 和客户列表(您已经声明了 da,因此使用了它)。
尽管对 DatabaseHelper 进行了一些小改动(long 用于 id,这是正确的做法,因为 id 可以超过最大值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();
}
}
}
数据库处理器
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;
}
}
客户
:-
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);
}
}
布局所有布局都应模仿您的布局,因此无需包含它们(您的布局可能会好得多,因为用于此的布局很少)。
这除了启动 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
的 Activity 部分:-
<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 行)可能不正确,因此需要更改。
关于java - 我的数据库应用程序已停止工作且无法打开,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50578923/
我在Windows 10中使用一些简单的Powershell代码遇到了这个奇怪的问题,我认为这可能是我做错了,但我不是Powershell的天才。 我有这个: $ix = [System.Net.Dn
var urlsearch = "http://192.168.10.113:8080/collective-intellegence/StoreClicks?userid=" + userId +
我有一个非常奇怪的问题,过去两天一直让我抓狂。 我有一个我试图控制的串行设备(LS 100 光度计)。使用设置了正确参数的终端(白蚁),我可以发送命令(“MES”),然后是定界符(CR LF),然后我
我目前正试图让无需注册的 COM 使用 Excel 作为客户端,使用 .NET dll 作为服务器。目前,我只是试图让概念验证工作,但遇到了麻烦。 显然,当我使用 Excel 时,我不能简单地使用与可
我开发了简单的 REST API - https://github.com/pavelpetrcz/MandaysFigu - 我的问题是在本地主机上,WildFly 16 服务器的应用程序运行正常。
我遇到了奇怪的情况 - 从 Django shell 创建一些 Mongoengine 对象是成功的,但是从 Django View 创建相同的对象看起来成功,但 MongoDB 中没有出现任何数据。
我是 flask 的新手,只编写了一个相当简单的网络应用程序——没有数据库,只是一个航类搜索 API 的前端。一切正常,但为了提高我的技能,我正在尝试使用应用程序工厂和蓝图重构我的代码。让它与 pus
我的谷歌分析 JavaScript 事件在开发者控制台中运行得很好。 但是当从外部 js 文件包含在页面上时,它们根本不起作用。由于某种原因。 例如; 下面的内容将在包含在控制台中时运行。但当包含在单
这是一本名为“Node.js 8 the Right Way”的书中的任务。你可以在下面看到它: 这是我的解决方案: 'use strict'; const zmq = require('zeromq
我正在阅读文本行,并创建其独特单词的列表(在将它们小写之后)。我可以使它与 flatMap 一起工作,但不能使它与 map 的“子”流一起工作。 flatMap 看起来更简洁和“更好”,但为什么 di
我正在编写一些 PowerShell 脚本来进行一些构建自动化。我发现 here echo $? 根据前面的语句返回真或假。我刚刚发现 echo 是 Write-Output 的别名。 写主机 $?
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 4年前关闭。 Improve thi
我将一个工作 View Controller 类从另一个项目复制到一个新项目中。我无法在新项目中加载 View 。在旧项目中我使用了presentModalViewController。在新版本中,我
我对 javascript 很陌生,所以很难看出我哪里出错了。由于某种原因,我的功能无法正常工作。任何帮助,将不胜感激。我尝试在外部 js 文件、头部/主体中使用它们,但似乎没有任何效果。错误要么出在
我正在尝试学习Flutter中的复选框。 问题是,当我想在Scaffold(body :)中使用复选框时,它正在工作。但我想在不同的地方使用它,例如ListView中的项目。 return Cente
我们当前使用的是 sleuth 2.2.3.RELEASE,我们看不到在 http header 中传递的 userId 字段没有传播。下面是我们的代码。 BaggageField REQUEST_I
我有一个组合框,其中包含一个项目,比如“a”。我想调用该组合框的 Action 监听器,仅在手动选择项目“a”完成时才调用。我也尝试过 ItemStateChanged,但它的工作原理与 Action
你能看一下照片吗?现在,一步前我执行了 this.interrupt()。您可以看到 this.isInterrupted() 为 false。我仔细观察——“这个”没有改变。它具有相同的 ID (1
我们当前使用的是 sleuth 2.2.3.RELEASE,我们看不到在 http header 中传递的 userId 字段没有传播。下面是我们的代码。 BaggageField REQUEST_I
我正在尝试在我的网站上设置一个联系表单,当有人点击发送时,就会运行一个作业,并在该作业中向所有管理员用户发送通知。不过,我在失败的工作表中不断收到此错误: Illuminate\Database\El
我是一名优秀的程序员,十分优秀!