Я создаю приложение для Android в Android Studio и пытаюсь найти значение String в Listview, заполненном облачным SQL-сервером. Я использую API 26 для Android 8.0. Пока он работает и находит некоторые значения.
Проблема - при достижении моего последнего (третьего) действия в эмуляторе и вставке строкового значения в поле поиска не находит все и все значение.
Например, у меня есть список, полный значений (Apple, Orange, Red Apple, Grapes и т. Д.). При поиске продукта Apple происходит следующее: после ввода «ap» он находит его и исчезает сразу после ввода «app». Также, пытаясь найти Orange, он ничего не показывает при наборе первой буквы o.
Как будто он не находит все значения на карте.
Я попытался отладить цикл в моем адаптере. Кажется, он правильно понимает ограничение, получает правильное количество для 'i' и находит все результаты, содержащие определенное ограничение.
Мой адаптер:
package com.example.user.sortiment;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* Created by User
*/
public class SortimentAdapter extends BaseAdapter {
LayoutInflater mInflator;
List<Sortiment> map;
List<Sortiment> filterMap;
public void performFiltering(CharSequence constraint) {
String filterString = constraint.toString().toLowerCase();
if (Objects.equals(filterString, "")) {
filterMap.clear();
filterMap.addAll(map);
notifyDataSetChanged();
return;
}
int count = map.size();
filterMap.clear();
for (int i = 0; i < count; i++) {
Sortiment filterableSortiment = map.get(i);
if (filterableSortiment.name.toLowerCase().contains(filterString)) {
filterMap.add(filterableSortiment);
}
}
notifyDataSetChanged();
}
public SortimentAdapter(Context c, List<Sortiment> inputMap) {
mInflator = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
filterMap = new ArrayList<>();
filterMap.addAll(inputMap);
map = new ArrayList<>();
map.addAll(inputMap);
}
@Override
public int getCount() {
return filterMap.size();
}
@Override
public Object getItem(int position) {
return filterMap.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
Sortiment viewObject = filterMap.get(position);
viewHolder.nameTextView.setText(viewObject.name);
viewHolder.priceTextView.setText(viewObject.ean.toString());
return convertView;
}
private class ViewHolder {
TextView nameTextView;
TextView priceTextView;
public ViewHolder(View view) {
nameTextView = (TextView)view.findViewById(R.id.nameTextView);
priceTextView = (TextView) view.findViewById(R.id.priceTextView);
}
}
}
и моя деятельность:
package com.example.user.sortiment;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SearchView;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class SortimentActivity extends AppCompatActivity {
List<Sortiment> sortimentMap = new ArrayList<>();
SortimentAdapter sortimentAdapter;
Context thisContext;
EditText edtSearch;
ListView myListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sortiment);
Integer selectedStoreId = getIntent().getExtras().getInt("store_id");
edtSearch = (EditText)findViewById(R.id.edtSearch);
myListView = (ListView) findViewById(R.id.storesListView);
thisContext = this;
edtSearch.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (sortimentAdapter != null){
sortimentAdapter.performFiltering(charSequence);
}
}
@Override
public void afterTextChanged(Editable editable) {
}
});
GetSortimentForStore retrieveData = new GetSortimentForStore();
retrieveData.execute(selectedStoreId);
}
public void performFiltering(CharSequence constraint) {
List<Sortiment> filteredList = new ArrayList<>();
String filterString = constraint.toString().toLowerCase();
if (Objects.equals(filterString, "")) {
filteredList.addAll(sortimentMap);
sortimentAdapter.notifyDataSetChanged();
return;
}
int count = sortimentMap.size();
filteredList.clear();
for (int i = 0; i < count; i++) {
Sortiment filterableSortiment = sortimentMap.get(i);
if (filterableSortiment.name.toLowerCase().contains(filterString)) {
filteredList.add(filterableSortiment);
}
}
sortimentAdapter = new SortimentAdapter(thisContext, filteredList);
sortimentAdapter.notifyDataSetChanged();
}
private class GetSortimentForStore extends AsyncTask<Integer,String,String> {
String msg = "";
// JDBC Driver name and database URL
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
// Example 10.20.30.40:3306
static final String DB_URL = "jdbc:mysql://" +
DbStrings.DATABASE_URL + "/" +
DbStrings.DATABASE_NAME;
@Override
protected void onPreExecute() {
//progressTextView.setText("Connecting...");
}
@Override
protected String doInBackground(Integer... selectedStores) {
Connection conn = null;
Statement stmt = null;
try {
Integer selectedStore = selectedStores[0];
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL, DbStrings.USERNAME, DbStrings.PASSWORD);
stmt = conn.createStatement();
String sql = "select id, store_id, name, ean, description from myproject.sortiments WHERE store_id = " + selectedStore;
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
Sortiment newSortiment = new Sortiment();
newSortiment.id = rs.getInt("id");
newSortiment.name = rs.getString("name");
newSortiment.store_id = rs.getInt("store_id");
newSortiment.ean = rs.getString("ean");
newSortiment.description = rs.getString("description");
sortimentMap.add(newSortiment);
}
rs.close();
stmt.close();
conn.close();
} catch (SQLException connError) {
msg = "An exception was thrown for JDBC.";
connError.printStackTrace();
} catch (ClassNotFoundException e) {
msg = "A class not found exception was thrown.";
e.printStackTrace();
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onPostExecute(String msg) {
sortimentAdapter = new SortimentAdapter(thisContext, sortimentMap);
myListView.setAdapter(sortimentAdapter);
}
}
}
и часть AndroidManifest:
<activity android:name=".SortimentActivity"
android:windowSoftInputMode="stateHidden">
</activity>
Есть какие-нибудь идеи о том, как можно лучше реализовать эту функцию поиска, чтобы она выполняла поиск по каждой строке?