将过滤器应用于列表后,TextWatcher 和 ListView 元素的位置出现问题

Problem with TextWatcher and position of ListView element after applying the filter to the list

我正在开发一个 android 应用程序,它显示一个列表视图,其中包含来自 SQL 数据库的数据。

单击列表视图元素后,会打开一个新的 Activity,其中包含有关它的信息。

我已经实施了 Textwatcher 来在列表中进行搜索,并且列表已按预期更新。

问题是,当我单击更新列表的列表元素时,它会打开一个 activity,其中包含旧位置的数据,例如通过单击 Zinn ID:939。它会打开一个新的 Activity 与 Altbach ID:940 数据。 TextWatcher 工作后更新元素位置并将其传递给 onItemClick 方法的最佳方法是什么?或者如何在 TextWatcher 工作后获取更新列表? 提前致谢!

那是我的 class.

    public class LibraryActivity extends AppCompatActivity implements View.OnClickListener {

    static String db_name = "test_stolpersteine_db.sqlite";
    StolpersteineDAO stolpersteinedao;
    List<Stolpersteine> stolpersteine_list;
    ListView list_view;
    private ArrayAdapter<CharSequence> adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_library);

        ////////////////////////////// Database ////////////////////////////////////////////////////
        final File dbFile = this.getDatabasePath(db_name); // we create a database path

        if (!dbFile.exists()) {     // we checking if the directory is existing
            try {
                copyDatabaseFile(dbFile.getAbsolutePath());  // method to copy the database
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        ////// Database
        startDatabase();
        stolpersteine_list = stolpersteinedao.getAllStolpersteine();
        list_view = findViewById(R.id.list);
        adapter = createAdapterHtml(stolpersteine_list);
        list_view.setAdapter(adapter);
        ////////////////////////////// Database ////////////////////////////////////////////////////

        //////////////////////////// Buttons ///////////////////////////////////////////////////////
        Button button_home = findViewById(R.id.button_home);
        Button button_map = findViewById(R.id.button_map);
        Button button_library = findViewById(R.id.button_library);

        button_home.setOnClickListener(this);
        button_map.setOnClickListener(this);
        button_library.setOnClickListener(this);

        button_library.setEnabled(false);
        /////////////////////////// Buttons ////////////////////////////////////////////////////////

        EditText theFilter = findViewById(R.id.edit_text);

        theFilter.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
            }
            @Override
            public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
                (LibraryActivity.this).adapter.getFilter().filter(charSequence);
            }
            @Override
            public void afterTextChanged(Editable charSequence) {
            }
        });

        //// OnClickListener
        list_view.setOnItemClickListener(new AdapterView.OnItemClickListener() {


            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                String url = stolpersteine_list.get(position).getURL();
                Intent i = new Intent(getApplicationContext(), RecordActivity.class);

                i.putExtra("url", url);
                i.putExtra("first_name", stolpersteine_list.get(position).getFirst_Name());
                i.putExtra("name", stolpersteine_list.get(position).getName());
                startActivity(i);


            }  // end of listener

        });

    } // end of onCreate method
    

    ////////////////////////////// Database ////////////////////////////////////////////////////////
    private void copyDatabaseFile(String destinationPath) throws IOException {

        InputStream assetsDB = this.getAssets().open(db_name);
        OutputStream dbOut = new FileOutputStream(destinationPath);

        byte[] buffer = new byte[1024];

        int length;

        while ((length = assetsDB.read(buffer)) > 0) {

            dbOut.write(buffer, 0, length);
        }

        dbOut.flush();
        dbOut.close();
    } //end of copyDatabaseFile method


    private ArrayAdapter<CharSequence> createAdapterHtml(List<Stolpersteine> s_list) {

        Spanned[] html_array = new Spanned[s_list.size()];

        for (int i = 0; i < s_list.size(); i++) {
            html_array[i] = Html.fromHtml(
                    s_list.get(i).getName()
                    + " "
                    + "ID: "+ s_list.get(i).getID() + "<br></i>"

                    + s_list.get(i).getHouse_Number() +" "
                    + s_list.get(i).getHouse_Number_Extension() + "</i>");
        }

        ArrayAdapter<CharSequence> my_adapter =
                new ArrayAdapter<CharSequence>(this, R.layout.list_item, html_array);

        return my_adapter;

    } // end of createAdapterHtml

    private void startDatabase() {
        AppDatabase database = Room.databaseBuilder(this, AppDatabase.class, db_name)
                .allowMainThreadQueries()
                .build();

        stolpersteinedao = database.getStolpersteineDAO();

    } // end of startDatabase method
    ////////////////////////////// Database ////////////////////////////////////////////////////////

    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.button_home:
                startActivity(new Intent(this, MainActivity.class));
                break;
            case R.id.button_map:
                startActivity(new Intent(this, MapboxActivity.class));
                break;
            case R.id.button_library:
                startActivity(new Intent(this, LibraryActivity.class));
                break;
        }

    }
} // end of class

问题是onItemClick()回调有一个过滤列表后位置的参数;即这个位置是相对于过滤后的列表而不是原始列表,尽管你需要从原始列表中获取实际位置。

要获取原始位置(不是过滤后的位置),您可以先获取过滤后的项目,然后使用原始列表中的 indexOf() 获取其位置。

要应用它,请将 list_view OnItemClickListener 更改为:

//// OnClickListener
list_view.setOnItemClickListener(new AdapterView.OnItemClickListener() {

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        
        // Getting the clicked item from the filtered list
        Stolpersteine filteredItem = (Stolpersteine) ((ListView) parent).getAdapter().getItem(position);

        // Getting the original position
        int originalPos = getList().indexOf(filteredItem);

        // Use originalPos instead of position in your code:
        
        String url = stolpersteine_list.get(originalPos).getURL();
        Intent i = new Intent(getApplicationContext(), RecordActivity.class);

        i.putExtra("url", url);
        i.putExtra("first_name", stolpersteine_list.get(originalPos).getFirst_Name());
        i.putExtra("name", stolpersteine_list.get(originalPos).getName());
        startActivity(i);


    }  // end of listener
});