![](/img/trans.png)
[英]SearchView filter with RecyclerView filtering with wrong results
[英]RecyclerView + onClickListener + searchView showing wrong results
基本上,我的代碼是關於在 recyclerView 上顯示用戶數據,當點擊時,將意圖顯示更多特定用戶數據的活動。
如果我不使用 searchView,onClickListener 可以正常工作。 它意圖正確的數據。
但是,當使用 searchView 時,當單擊第一個結果時,它總是采用在我輸入任何 searchView 查詢之前顯示的 recyclerView 第一項的數據,依此類推,位置為 2、3、4...
適配器 Class
public class OwnerAdapter extends RecyclerView.Adapter<OwnerAdapter.ViewHolder> {
private final RecyclerInterface recyclerInterface;
private ArrayList<Owners> ownerList;
public OwnerAdapter(ArrayList<Owners> ownerList, RecyclerInterface recyclerInterface){
this.recyclerInterface = recyclerInterface;
this.ownerList = ownerList;
}
public void setFilteredList(ArrayList<Owners> filteredList) {
this.ownerList = filteredList;
notifyDataSetChanged();
}
@NonNull
@Override
public OwnerAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.owner_recycler_row, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull OwnerAdapter.ViewHolder holder, int position) {
int resource = R.drawable.ic_baseline_person_24;
String name=ownerList.get(position).getOwner_name();
int owner_num = ownerList.get(position).getOwner_number();
String category = ownerList.get(position).getCategory();
holder.setData(resource,name,owner_num,category);
}
@Override
public int getItemCount() {
return ownerList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private ImageView imageView;
private TextView tvName, tvOwner_num, tvCategory;
public ViewHolder(@NonNull View itemView) {
super(itemView);
imageView=itemView.findViewById(R.id.imageview1);
tvName=itemView.findViewById(R.id.tvName);
tvOwner_num=itemView.findViewById(R.id.tvOwner_num);
tvCategory=itemView.findViewById(R.id.tvCategory);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (recyclerInterface != null) {
int pos = getAdapterPosition();
if (pos != RecyclerView.NO_POSITION){
recyclerInterface.onRecyclerClick(pos);
}
}
}
});
}
public void setData(int resource, String name, int owner_num, String category) {
imageView.setImageResource(resource);
tvName.setText(name);
tvOwner_num.setText(Integer.toString(owner_num));
tvCategory.setText(category);
}
}
}
ViewOwners Class (顯示回收站視圖)
public class ViewOwnerDetails extends AppCompatActivity implements RecyclerInterface {
RecyclerView recyclerView;
LinearLayoutManager layoutManager;
OwnerAdapter ownerAdapter;
ArrayList<Owners> ownerList = new ArrayList<>();
ArrayList<Owners> filteredList = new ArrayList<>();
private SearchView searchView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.owner_recylcer_view);
new ViewOwnerDetails.Async().execute();
searchView = findViewById(R.id.searchView);
searchView.clearFocus();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
filteredList.clear();
filterList(newText);
return true;
}
});
}
class Async extends AsyncTask<Void, Void, Void> {
ProgressDialog pd;
@Override
protected void onPreExecute() { //before completing task
//loading message
super.onPreExecute();
pd = new ProgressDialog(ViewOwnerDetails.this);
pd.setMessage("Loading");
pd.show();
}
@Override
protected Void doInBackground(Void... voids) { //
load(); //load data to userList
return null;
}
@Override
protected void onPostExecute(Void aVoid) { //after completing task
initRecyclerView();
pd.dismiss();
}
}
public void load() {
try {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://0104-acrs.mysql.database.azure.com:3306/azuredb", "VSVP", "VVSP0104!");
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery("SELECT * FROM owner_data O INNER JOIN category C on O.catId = C.cat_id;");
while (rs.next()) {
String category = rs.getString("cat_name"), owner_name = rs.getString("owner_name");
int owner_num = rs.getInt("owner_num");
Boolean enabled = rs.getBoolean("isEnabled");
Owners owner = new Owners(owner_name, category, enabled, owner_num);
ownerList.add(owner);
Log.i("hi", "load: " + ownerList);
}
} catch (Exception e) {
Log.i("hi", "ERROR: " + e.getMessage());
}
}
private void initRecyclerView() {
recyclerView = findViewById(R.id.recyclerView);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
ownerAdapter = new OwnerAdapter(ownerList, this);
recyclerView.setAdapter(ownerAdapter);
ownerAdapter.notifyDataSetChanged();
}
public void onRecyclerClick(int position) {
Intent intent = new Intent(ViewOwnerDetails.this, ViewFullOwnerDetails.class);
if(searchView.toString().isEmpty()) {
intent.putExtra("NAME", ownerList.get(position).getOwner_name());
intent.putExtra("OWNER_NUM", ownerList.get(position).getOwner_number());
intent.putExtra("CATEGORY", ownerList.get(position).getCategory());
intent.putExtra("ENABLED", ownerList.get(position).isEnabled());
} else if(!searchView.toString().isEmpty()){
intent.putExtra("NAME", filteredList.get(position).getOwner_name());
intent.putExtra("OWNER_NUM", filteredList.get(position).getOwner_number());
intent.putExtra("CATEGORY", filteredList.get(position).getCategory());
intent.putExtra("ENABLED", filteredList.get(position).isEnabled());
}
startActivity(intent);
}
private void filterList(String text) {
for(Owners o : ownerList){
if(o.getOwner_name().toLowerCase().contains(text.toLowerCase())){
filteredList.add(o);
}
}
if(filteredList.isEmpty()) {
Toast.makeText(this, "No results found", Toast.LENGTH_SHORT).show();
} else {
ownerAdapter.setFilteredList(filteredList);
}
}
}
ViewFullOwnerInfo Class (點擊recyclerView項目后打算)
public class ViewFullOwnerDetails extends AppCompatActivity {
TextView tvTitle, tvName, tvOwner_num, tvCategory, tvMember;
Button btBack, btEdit, btDeleteOwner, btView;
ArrayList<String> associatedList = new ArrayList<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.full_owner_details);
initComponents();
intentData();
new asyncsetUpAssociatedList().execute();
btBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(ViewFullOwnerDetails.this, ViewOwnerDetails.class);
startActivity(intent);
}
});
btDeleteOwner.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
deleteConfirmationOwner();
}
});
btEdit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(ViewFullOwnerDetails.this, ViewOwnerDetails.class);
startActivity(intent);
}
});
btView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
viewDialog(associatedList);
}
});
}
public void intentData() {
String name = getIntent().getStringExtra("NAME");
int owner_num = getIntent().getIntExtra("OWNER_NUM", 0);
String category = getIntent().getStringExtra("CATEGORY");
Boolean enabled = getIntent().getBooleanExtra("ENABLED", false);
tvTitle.setText("FULL INFORMATION");
tvName.setText(name);
tvOwner_num.setText(String.valueOf(owner_num));
tvCategory.setText(category);
if (enabled.toString() == "false") {
tvMember.setText("Membership Disabled");
} else if (enabled.toString() == "true") {
tvMember.setText("Membership Enabled");
}
}
private void initComponents() {
tvTitle = (TextView) findViewById(R.id.tvTitle);
tvName = (TextView) findViewById(R.id.tvName);
tvOwner_num = (TextView) findViewById(R.id.tvCategory);
tvCategory = (TextView) findViewById(R.id.tvOwner_num);
tvMember = (TextView) findViewById(R.id.tvMember);
btBack = (Button) findViewById(R.id.btBack);
btDeleteOwner = (Button) findViewById(R.id.buttonDeleteOwner);
btEdit = (Button) findViewById(R.id.btResolve);
btView = (Button) findViewById(R.id.btViewVehicles);
}
private void viewDialog(List<String> associatedList) {
String output = "";
if (associatedList.isEmpty()) {
output = "List empty";
} else {
for (int i = 0; i < associatedList.size(); i++) {
String vehicle = associatedList.get(i);
output += vehicle + "\n";
}
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("ASSOCIATED VEHICLES: \n" + output)
.setPositiveButton("Close", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
private void deleteConfirmationOwner() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to delete this Owner? It will delete all related vehicles also")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
new ViewFullOwnerDetails.asyncDeleteOwner().execute();
Intent intent = new Intent(ViewFullOwnerDetails.this, ViewOwnerDetails.class);
startActivity(intent);
Toast.makeText(ViewFullOwnerDetails.this, "Delete Succesful!", Toast.LENGTH_LONG).show();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
class asyncDeleteOwner extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... voids) {
try {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("url", "user", "pass");
String query = String.format("DELETE FROM owner_data WHERE owner_num = '%d'", Integer.parseInt(tvOwner_num.getText().toString()));
PreparedStatement statement = conn.prepareStatement(query);
statement.executeUpdate();
} catch (Exception e) {
}
return null;
}
}
class asyncsetUpAssociatedList extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
try {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("url", "pass", "user");
Statement statement = conn.createStatement();
//String query = String.format("SELECT * FROM vehicle_data V INNER JOIN owner_data O on O.owner_num = V.owner_num WHERE V.owner_num = '%d'", Integer.parseInt(tvOwner_num.getText().toString()));
ResultSet rs = statement.executeQuery("SELECT * FROM owner_data O INNER JOIN category C on O.catId = C.cat_id;");
while (rs.next()) {
String reg_num = rs.getString("reg_num");
associatedList.add(reg_num);
}
} catch (Exception e) {
Log.i("v", "Error: " + e.getMessage());
}
return null;
}
}
}
當我在沒有搜索查詢的情況下單擊 recyclerView 項目時出錯:
2022-08-01 18:13:39.119 26727-26727/? E/.example.acrs3: Unknown bits set in runtime_flags: 0x8000
2022-08-01 18:13:39.828 26727-26727/com.example.acrs30 E/RecyclerView: No adapter attached; skipping layout
2022-08-01 18:13:41.039 26727-26727/com.example.acrs30 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.acrs30, PID: 26727
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:437)
at com.example.acrs30.ViewOwnerDetails.onRecyclerClick(ViewOwnerDetails.java:131)
at com.example.acrs30.OwnerAdapter$ViewHolder$1.onClick(OwnerAdapter.java:73)
at android.view.View.performClick(View.java:7125)
at android.view.View.performClickInternal(View.java:7102)
at android.view.View.access$3500(View.java:801)
at android.view.View$PerformClick.run(View.java:27336)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
在您的OwnerAdapter
您應該將邏輯移出ViewHolder
構造函數。 數據綁定和邏輯實現應該發生在onBindViewHolder
方法中:
@Override
public void onBindViewHolder(@NonNull OwnerAdapter.ViewHolder holder, int position) {
...
holder.itemView.setOnCLickListener(view ->
recyclerInterface.onRecyclerClick(position);
);
}
ViewHolder
構造函數僅由onCreateViewHolder
用於初始化ViewHolder
和與之關聯的Views
。 onBindViewHolder
將ViewHolder
與實際數據相關聯。 在這些數據中,適配器中的ViewHolder
有一個新的position
,它提供了一種從列表中訪問實際項目的方法。
使用 searchView 時,單擊第一個結果時,它總是獲取在我輸入任何 searchView 查詢之前顯示的 recyclerView 第一項的數據,依此類推,位置為 2、3、4 ...
這意味着當您搜索項目時,您的 recyclerView 列表未正確更新。 您在搜索視圖中顯示的列表與單擊時要更改的列表不同。
public void onRecyclerClick(int position) {
Intent intent = new Intent(ViewOwnerDetails.this, ViewFullOwnerDetails.class);
intent.putExtra("NAME", ownerList.get(position).getOwner_name());
intent.putExtra("OWNER_NUM", ownerList.get(position).getOwner_number());
intent.putExtra("CATEGORY", ownerList.get(position).getCategory());
intent.putExtra("ENABLED", ownerList.get(position).isEnabled());
startActivity(intent);
}
因此,這里的問題是您正在訪問與過濾列表不同的 ownerList 的第一項。 因此,為了獲得正確的項目,您應該訪問過濾后的列表而不是 ownerList。 您可以初始化整個活動的過濾列表,然后您可以相應地在點擊時使用 recyclerView。 如果搜索視圖為空,您可以從 ownerList 訪問項目,如果不是,您可以從過濾列表訪問項目。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.