简体   繁体   中英

Will be selected wrong item position in the ListView?

I'm trying to implement a search function to search in the SQLite database by a keyword by following this example . Here are my codes:

AndroidManifest.xml

<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"/>

                <action android:name="android.intent.action.SEARCH"/>
            </intent-filter>

            <meta-data
                    android:name="android.app.searchable"
                    android:resource="@xml/searchable"/>
        </activity>
        <activity android:name=".AddCarActivity">
        </activity>
        <activity android:name=".ViewActivity">
        </activity>
    </application>

MainActivity.kt

class MainActivity : AppCompatActivity() {

    lateinit var cars: ListView
    lateinit var car_adapter: CarAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        cars = findViewById(R.id.cars)
        val add: FloatingActionButton = findViewById(R.id.add)
        add.setOnClickListener {
            startActivityForResult(Intent(this, AddCarActivity::class.java), 1000)
        }
        cars.onItemClickListener = AdapterView.OnItemClickListener { _, _, i, _ ->
            val cursor = CarDatabase(this).getCarList()
            cursor.moveToPosition(i)
            val intent = Intent(this, ViewActivity::class.java)
            intent.putExtra("car", cursor.getString(1))
            startActivity(intent)
        }

        getCars()
    }

    fun getCars() {
        car_adapter = CarAdapter(this, CarDatabase(this).getCarList())
        cars.adapter = car_adapter
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.menu, menu)
        val manager: SearchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
        val search = menu!!.findItem(R.id.search).actionView as SearchView
        search.setSearchableInfo(manager.getSearchableInfo(componentName))
        val context: Context = this
        search.setOnQueryTextListener(object : SearchView.OnQueryTextListener {

            override fun onQueryTextSubmit(query: String?): Boolean {
                if (query!!.isNotEmpty()) {
                    val cursor: Cursor = CarDatabase(context).getCarListByKeyword(query)!!
                    Toast.makeText(context, "${cursor.count} record(s) found!", Toast.LENGTH_LONG).show()
                    car_adapter.swapCursor(cursor)
                }
                return false
            }

            override fun onQueryTextChange(newText: String?): Boolean {
                if (newText!!.isNotEmpty()) {
                    val cursor: Cursor = CarDatabase(context).getCarListByKeyword(newText)!!
                    car_adapter.swapCursor(cursor)
                } else
                    getCars()
                return false
            }
        })
        return true
    }
}

AddCarActivity.kt

class AddCarActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_add_car)

        val add: ImageButton = findViewById(R.id.add_car)
        add.setOnClickListener {
            val car: EditText = findViewById(R.id.car_et)

            if (CarDatabase(this).addCar(car.text.toString())) {
                Toast.makeText(this, "Car added!", Toast.LENGTH_SHORT).show()
                setResult(1000)
                finish()
            } else
                Toast.makeText(this, "Please try again!", Toast.LENGTH_SHORT).show()
        }
    }
}

ViewActivity.kt

class ViewActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_view)

        val car: TextView = findViewById(R.id.car_v)
        car.text = intent.getStringExtra("car")
    }
}

CarAdapter.kt

class CarAdapter(context: Context, cursor: Cursor?) :
    CursorAdapter(context, cursor, 0) {

    private var mInflater: LayoutInflater? = null

    override fun newView(context: Context, cursor: Cursor, parent: ViewGroup): View {
        val view = mInflater!!.inflate(R.layout.cars_list, parent, false)
        val holder = ViewHolder()
        holder.car = view.findViewById(R.id.car)
        view.tag = holder
        return view
    }

    override fun bindView(view: View, context: Context, cursor: Cursor) {
        val holder = view.tag as ViewHolder
        holder.car!!.text = cursor.getString(cursor.getColumnIndex(CarDatabase.CAR))
    }

    internal class ViewHolder {
        var car: TextView? = null
    }

    init {
        mInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater?
    }
}

CarDatabase.kt

class CarDatabase(context: Context) : SQLiteOpenHelper(context, NAME, null, VERSION) {

    companion object {
        const val NAME = "Cars.db"
        const val VERSION = 1
        const val TABLE = "Cars"
        const val ID = "_id"
        const val CAR = "Car"
    }

    private var db: SQLiteDatabase = this.writableDatabase

    override fun onCreate(db: SQLiteDatabase) {
        db.execSQL("CREATE TABLE $TABLE ($ID INTEGER PRIMARY KEY AUTOINCREMENT, $CAR TEXT);")
    }

    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        db.execSQL("DROP TABLE IF EXISTS $TABLE")
        onCreate(db)
    }

    fun getCarList(): Cursor {
        val cursor = db.rawQuery("SELECT * FROM $TABLE", null)
        if (!cursor.moveToFirst())
            cursor.close()
        return cursor
    }

    fun addCar(car: String): Boolean {
        val values = ContentValues()
        values.put(CAR, car)
        return db.insert(TABLE, null, values) > 0
    }

    fun getCarListByKeyword(search: String): Cursor? {
        val cursor = db.rawQuery("SELECT rowid as $ID, $CAR FROM $TABLE WHERE $CAR LIKE '%$search%'", null)
        if (cursor == null) {
            return null
        } else if (!cursor.moveToFirst()) {
            cursor.close()
            return null
        }
        return cursor
    }
}

Here is my example list I created after the app execution on a test device like this . This sample app does the following: By clicking an item opens the View activity and appears the selected item like this . For example, by selecting Audi you will see Audi.

The Problem is in the search function. For example, if I search for Mercedes Benz and then click on it, in the ViewActivity appears Audi like this . Or Toyota -> Mercedes Benz or Audi Q5 -> Lexus , etc. It seems, after searching there will be selected wrong positions in the ListView . How can I solve this problem? Please let me know if I could not explain something understandably.

It seems that even though you swapping the DB cursor for the search view in your adapter, you don't use it to actually get the item from your database: ( in your onItemClickListener )

val cursor = CarDatabase(this).getCarList()
cursor.moveToPosition(i)

You should get the current cursor from the adapter instead of CarDatabase(this).getCarList() and then use it, ie

val cursor = car_adapter.cursor
cursor.moveToPosition(i)

Hope it helps. Cheers.

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