简体   繁体   中英

how to make a search in a list view android which is populated from SQLite database

Hi to everyone I am new to android just a beginner. I am developing an app which shows a list of medicine with the brand name and generic name. I am using ListView for displaying data and this data is coming from SQLite database. What I want when a user enters a name of a medicine in a editText it should show the search result from the ListView like for example my List has a medicine name NICOX a brand name. And user wants to search this name and Enters N in the edit text then this name should be shown in the list view and all other names which start form the letter which the user enters in the edit text I added all my code here is my Main Activity code.

           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);
                }
        
            }
        
           
        
        }

and here is my AddItemActivity which is adding a new item into a database

                      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();
                }
        
            }
        
        
        }

here is my 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);
                
                    }
                
                }

this is my Add New Prodct Contract

                             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";
                }
            }

and here is my database helper class

                            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);
            }
        }

here is my list view xml file

                         <?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>

and here is my list item layout 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>

please help to solve this issue

I try this code and it works now I am able to filter the list but when I click on filter result the app crashed and give me a error

         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)

here is code which I try

     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) {

        }
    });

here I work for another code this is working code it can filter the data but data not shown only empty list but when I click on a item it shows me correct data

        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();

}

and I use this function in my mSearchEditText like this

             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) {

        }
    });
  

this code is working and filtring the data as I type a word but it shows empty list and when I click on this list it show me the data of that list item.

As I am already displaying list of data using my DisplayDataAdpaterView so I user this method and excecated this method in my editText search's method

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            String search = s.toString();
             showSearch(search);
        }

this method to search result from database and bind the views and show them as listview

  public void showSearch(String search){

    String searchQuery = (" SELECT * FROM " +
            AddNewProductEntry.TABLE_NAME + " WHERE " +
            AddNewProductEntry.COLUMN_PRODUCT_NAME + " LIKE '%" + search + "%'");

    cursor = database.rawQuery(searchQuery, null);

    // so this is the DisplayAdpater which already displaying data
    // so we use this adapter to show search in a list view
    adapter = new DispalyDataAdapterView(this,cursor);
    listView.setAdapter(adapter);
    adapter.notifyDataSetChanged();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM