簡體   English   中英

RecyclerView + onClickListener + searchView 顯示錯誤結果

[英]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 onBindViewHolderViewHolder與實際數據相關聯。 在這些數據中,適配器中的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM