【发布时间】:2021-02-21 15:37:09
【问题描述】:
大家好,我是 android 新手,只是一个初学者。我正在开发一个应用程序,它显示带有品牌名称和通用名称的药物列表。我使用 ListView 来显示数据,这些数据来自 SQLite 数据库。当用户在 editText 中输入药物名称时,我想要的是它应该显示来自 ListView 的搜索结果,例如我的列表有一个药物名称 NICOX 一个品牌名称。并且用户想要搜索此名称并在编辑文本中输入 N 然后此名称应显示在列表视图中,所有其他名称以用户在编辑文本中输入的字母开头我添加的所有代码都是我的主要活动代码。
package com.example.clnicmangmentapp;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.provider.BaseColumns;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SearchView;
import com.example.clnicmangmentapp.data.AddNewProductContract.AddNewProductEntry;
import com.example.clnicmangmentapp.data.AddNewProductDataBaseHelper;
public class MainActivity extends AppCompatActivity {
AddNewProductDataBaseHelper mDataBaseHelper;
SQLiteDatabase database;
Cursor cursor;
SearchView mSearchView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSearchView = findViewById(R.id.search_view);
mDataBaseHelper = new AddNewProductDataBaseHelper(this);
database = mDataBaseHelper.getWritableDatabase();
cursor = database.rawQuery("SELECT * FROM " + AddNewProductEntry.TABLE_NAME, null);
ListView listView = findViewById(R.id.list_view);
DispalyDataAdapterView adapter = new DispalyDataAdapterView(this, cursor);
listView.setAdapter(adapter);
adapter.changeCursor(cursor);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
int brandNameCol =
cursor.getColumnIndex(AddNewProductEntry.COLUMN_PRODUCT_NAME);
int genericNameCol =
cursor.getColumnIndex(AddNewProductEntry.COLUMN_GENERIC_NAME);
int retailPriceCol =
cursor.getColumnIndex(AddNewProductEntry.COLUMN_RETAIL_PRICE);
int packSizeCol = cursor.getColumnIndex(AddNewProductEntry.COLUMN_PACK_SIZE);
int oneUnitPriceCol =
cursor.getColumnIndex(AddNewProductEntry.COLUMN_ONE_UNIT_PRICE);
String brandName = cursor.getString(brandNameCol);
String genericName = cursor.getString(genericNameCol);
Double retailPrice = cursor.getDouble(retailPriceCol);
int packSize = cursor.getInt(packSizeCol);
Double oneUnitPrice = cursor.getDouble(oneUnitPriceCol);
Intent intent = new Intent(MainActivity.this,
DisplayOneProductActivity.class);
intent.putExtra("name", brandName);
intent.putExtra("genericName", genericName);
intent.putExtra("retailPrice", retailPrice);
intent.putExtra("packSize", packSize);
intent.putExtra("oneUnitPrice", oneUnitPrice);
startActivity(intent);
//finish();
}
});
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.add_item:
// Toast.makeText(MainActivity.this, "Item is clicked",
Toast.LENGTH_LONG).show();
Intent intent = new Intent(this, AddItemActivity.class);
startActivity(intent);
return true;
case R.id.view_cart_menu:
Intent cartIntent = new Intent(this, ViewCartActivity.class);
startActivity(cartIntent);
default:
return super.onOptionsItemSelected(item);
}
}
}
这是我的AddItemActivity,它正在向数据库中添加一个新项目
package com.example.clnicmangmentapp;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ContentValues;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.example.clnicmangmentapp.data.AddNewProductContract.AddNewProductEntry;
import com.example.clnicmangmentapp.data.AddNewProductDataBaseHelper;
import java.text.DecimalFormat;
public class AddItemActivity extends AppCompatActivity {
private static DecimalFormat df = new DecimalFormat("0.00");
AddNewProductDataBaseHelper mDataBaseHelper;
private Button mAddDataBtn;
private Button mCancleBtn;
private EditText mBrandName;
private EditText mGenericName;
private EditText mCompanyName;
private EditText mRetailPrice;
private EditText mPackSize;
private TextView mOneUnitPrice;
private Spinner typeSpinner;
private int mSpinnerType = AddNewProductEntry.CAP;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_item);
mDataBaseHelper = new AddNewProductDataBaseHelper(this);
mAddDataBtn = findViewById(R.id.add_data_btn);
mCancleBtn = findViewById(R.id.clear_data_btn);
mBrandName = findViewById(R.id.product_name);
mGenericName = findViewById(R.id.genric_name);
mCompanyName = findViewById(R.id.company_name);
mRetailPrice = findViewById(R.id.retail_price);
mPackSize = findViewById(R.id.pack_size);
typeSpinner = (Spinner) findViewById(R.id.medicine_type);
// for setting spinner to take the value drop down menu
setSpinner();
mAddDataBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
insertData();
clearInputs();
}
});
mCancleBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(AddItemActivity.this, MainActivity.class);
startActivity(intent);
}
});
}
private void setSpinner(){
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.medicine_array, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
typeSpinner.setAdapter(adapter);
typeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long
id) {
String selectedItem = (String) parent.getItemAtPosition(position);
if(!TextUtils.isEmpty(selectedItem)){
if(selectedItem.equals(getString(R.string.cap))){
Toast.makeText(AddItemActivity.this, "Cap is clicked",
Toast.LENGTH_LONG).show();
mSpinnerType = AddNewProductEntry.CAP;
}else if(selectedItem.equals(getString(R.string.tab))){
Toast.makeText(AddItemActivity.this, "Tab is clicked",
Toast.LENGTH_LONG).show();
mSpinnerType = AddNewProductEntry.TAB;
}else if(selectedItem.equals(getString(R.string.syp))){
Toast.makeText(AddItemActivity.this, "Syp is clicked",
Toast.LENGTH_LONG).show();
mSpinnerType = AddNewProductEntry.SYP;
}else{
Toast.makeText(AddItemActivity.this, "Inj is clicked",
Toast.LENGTH_LONG).show();
mSpinnerType = AddNewProductEntry.INJ;
}
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
// this method clear all edit text after inter data to database as add button is pressed
private void clearInputs(){
mBrandName.getText().clear();
mGenericName.getText().clear();
mCompanyName.getText().clear();
mRetailPrice.getText().clear();
mPackSize.getText().clear();
}
private void insertData(){
String brand_name = mBrandName.getText().toString().toUpperCase().trim();
String generic_name = mGenericName.getText().toString().toUpperCase().trim();
String company_name = mCompanyName.getText().toString().toUpperCase().trim();
String retail_price = mRetailPrice.getText().toString().trim();
Double retailPrice = Double.parseDouble(retail_price);
String pack_size = mPackSize.getText().toString().trim();
int packSize = Integer.parseInt(pack_size);
Double oneUnitPrice = retailPrice/packSize;
// in this line of code we limiting out put to decimal places like 33.33
String convertedPrice = df.format(oneUnitPrice);
SQLiteDatabase sqLiteDatabase = mDataBaseHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(AddNewProductEntry.COLUMN_PRODUCT_NAME, brand_name);
contentValues.put(AddNewProductEntry.COLUMN_GENERIC_NAME, generic_name);
contentValues.put(AddNewProductEntry.COLUMN_COMPANY_NAME, company_name);
contentValues.put(AddNewProductEntry.COLUMN_RETAIL_PRICE, retail_price);
contentValues.put(AddNewProductEntry.COLUMN_PACK_SIZE, packSize);
contentValues.put(AddNewProductEntry.COLUMN_TYPE_OF_PRODUCT, mSpinnerType);
contentValues.put(AddNewProductEntry.COLUMN_ONE_UNIT_PRICE, convertedPrice);
long newRowId = sqLiteDatabase.insert(AddNewProductEntry.TABLE_NAME,null,
contentValues);
if(newRowId == -1){
Toast.makeText(AddItemActivity.this,"Error Inserting Data",
Toast.LENGTH_LONG).show();
}else{
Toast.makeText(AddItemActivity.this,"Data is Inserted Successfully",
Toast.LENGTH_LONG).show();
}
}
}
这是我的 DisplayDataAdapterView
package com.example.clnicmangmentapp;
import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.TextView;
import com.example.clnicmangmentapp.data.AddNewProductContract.AddNewProductEntry;
public class DispalyDataAdapterView extends CursorAdapter {
public DispalyDataAdapterView(Context context, Cursor cursor) {
super(context, cursor, 0);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.item_view, parent,
false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView brandNameTextView = view.findViewById(R.id.brand_name_view);
TextView genericNameTextView = view.findViewById(R.id.generic_name_view);
int brandNameCol =
cursor.getColumnIndex(AddNewProductEntry.COLUMN_PRODUCT_NAME);
int genericNameCol =
cursor.getColumnIndex(AddNewProductEntry.COLUMN_GENERIC_NAME);
String brandName = cursor.getString(brandNameCol);
String genericName = cursor.getString(genericNameCol);
brandNameTextView.setText(brandName);
genericNameTextView.setText(genericName);
}
}
这是我的添加新产品合同
package com.example.clnicmangmentapp.data;
import android.provider.BaseColumns;
public class AddNewProductContract {
private AddNewProductContract(){}
public static class AddNewProductEntry implements BaseColumns{
public static final String TABLE_NAME = "add_new_product";
public static final String _ID = BaseColumns._ID;
public static final String COLUMN_PRODUCT_NAME = "product_name";
public static final String COLUMN_GENERIC_NAME = "generic_name";
public static final String COLUMN_COMPANY_NAME = "company_name";
public static final String COLUMN_RETAIL_PRICE = "retail_price";
public static final String COLUMN_PACK_SIZE = "pack_size";
public static final String COLUMN_TYPE_OF_PRODUCT = "product_type";
public static final String COLUMN_ONE_UNIT_PRICE = "one_unit_price";
public static final int CAP = 100;
public static final int TAB = 101;
public static final int SYP = 102;
public static final int INJ = 103;
}
public static class AddItemToCart implements BaseColumns{
public static final String TABLE_CART = "add_to_cart";
public static final String _CART_ID = BaseColumns._ID;
public static final String COLUMN_CART_PRODUCT_NAME = "cart_product_name";
public static final String COLUMN_CART_QUANTITY = "cart_product_quantity";
public static final String COLUMN_CART_PRICE = "cart_product_price";
public static final String COLUMN_CART_TOTAL_PRICE = "cart_total_price";
}
}
这是我的数据库助手类
package com.example.clnicmangmentapp.data;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.example.clnicmangmentapp.data.AddNewProductContract.AddNewProductEntry;
import com.example.clnicmangmentapp.data.AddNewProductContract.AddItemToCart;
import androidx.annotation.Nullable;
public class AddNewProductDataBaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "products";
private static final int DATABASE_VERSION = 1;
public AddNewProductDataBaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String CREATE_TABLE_ENTITIES = "CREATE TABLE " + AddNewProductEntry.TABLE_NAME + "("
+ AddNewProductEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ AddNewProductEntry.COLUMN_PRODUCT_NAME + " TEXT, "
+ AddNewProductEntry.COLUMN_GENERIC_NAME + " TEXT, "
+ AddNewProductEntry.COLUMN_COMPANY_NAME + " TEXT, "
+ AddNewProductEntry.COLUMN_RETAIL_PRICE + " REAL, "
+ AddNewProductEntry.COLUMN_PACK_SIZE + " INTEGER, "
+ AddNewProductEntry.COLUMN_TYPE_OF_PRODUCT + " INTEGER, "
+ AddNewProductEntry.COLUMN_ONE_UNIT_PRICE + " REAL )" ;
String CREATE_CART_TABLE = "CREATE TABLE " + AddItemToCart.TABLE_CART + "("
+ AddItemToCart._CART_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ AddItemToCart.COLUMN_CART_PRODUCT_NAME + " TEXT, "
+ AddItemToCart.COLUMN_CART_QUANTITY + " INTEGER, "
+ AddItemToCart.COLUMN_CART_PRICE + " REAL, "
+ AddItemToCart.COLUMN_CART_TOTAL_PRICE + " REAL )";
db.execSQL(CREATE_TABLE_ENTITIES);
db.execSQL(CREATE_CART_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
String DROP_TABLE_PRODUCTS = " DROP TABLE IF EXISTS " +
AddNewProductEntry.TABLE_NAME;
String DROP_TABLE_ADD_TO_CART = " DROP TABLE IF EXISTS " +
AddItemToCart.TABLE_CART;
db.execSQL(DROP_TABLE_PRODUCTS);
db.execSQL(DROP_TABLE_ADD_TO_CART);
onCreate(db);
}
}
这是我的列表视图 xml 文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
tools:context=".MainActivity">
<EditText
android:id="@+id/search_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter Your Search"
android:padding="8dp"
android:layout_marginBottom="4dp">
</EditText>
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
这是我的列表项布局 xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/brand_name_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:text="@string/brand_name"
android:textSize="18sp"/>
<TextView
android:id="@+id/generic_name_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:text="Generic Name"
android:paddingLeft="8dp"/>
</LinearLayout>
请帮忙解决这个问题
我尝试了这段代码,现在它可以工作了
android.database.StaleDataException: Attempting to access a closed
CursorWindow.Most probable cause: cursor is deactivated prior to
calling this method.
at
android.database.AbstractWindowedCursor.
checkPosition(AbstractWindowedCursor.java :141)
at
android.database.AbstractWindowedCursor.
getString(AbstractWindowedCursor.java:52)
at
com.example.clnicmangmentapp.MainActivity$3.
onItemClick(MainActivity.java:97)
这是我尝试的代码
adapter.setFilterQueryProvider(new FilterQueryProvider() {
@Override
public Cursor runQuery(CharSequence constraint) {
String search = constraint.toString();
String searchResult = (" SELECT * FROM " +
AddNewProductEntry.TABLE_NAME + " WHERE " +
AddNewProductEntry.COLUMN_PRODUCT_NAME + " LIKE '%" + search +
"%'");
return database.rawQuery(searchResult, null);
}
});
mSearchEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int
count) {
adapter.getFilter().filter(s);
// Don't forget to notify the adapter
adapter.notifyDataSetChanged();
}
@Override
public void afterTextChanged(Editable s) {
}
});
我在这里为另一个代码工作,这是工作代码 它可以过滤数据,但数据不只显示空列表,但是当我点击一个项目时,它会显示正确的数据
public void showSearch(String search){
String searchQuery = (" SELECT * FROM " +
AddNewProductEntry.TABLE_NAME + " WHERE " +
AddNewProductEntry.COLUMN_PRODUCT_NAME + " LIKE '%" + search +
"%'");
cursor = database.rawQuery(searchQuery, null);
SimpleCursorAdapter adapterSimple = new
SimpleCursorAdapter(MainActivity.this,
android.R.layout.simple_list_item_2, cursor,
new String[] {AddNewProductEntry.COLUMN_PRODUCT_NAME,
AddNewProductEntry.COLUMN_GENERIC_NAME},
new int[] {R.id.brand_name_view, R.id.generic_name_view},
0);
listView.setAdapter(adapterSimple);
adapterSimple.notifyDataSetChanged();
}
我像这样在我的 mSearchEditText 中使用这个函数
mSearchEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int
count) {
String search = s.toString();
showSearch(search);
}
@Override
public void afterTextChanged(Editable s) {
}
});
当我键入一个单词时,此代码正在工作并过滤数据,但它显示空列表,当我单击此列表时,它会显示该列表项的数据。
【问题讨论】:
-
所以您的数据显示正确并且一切正常,但是您需要一种使用 SearchView 过滤数据的方法吗?
-
尝试使用
RecyclerView而不是ListView,因为 RV 是更高级的列表视图 -
阿里开斋节你是对的,我的数据显示正确,一切都很好,只是想知道如何过滤这些数据