【问题标题】:Filtering in RealmRecyclerViewAdapter does not hide excluded elementsRealmRecyclerViewAdapter 中的过滤不会隐藏排除的元素
【发布时间】:2020-09-09 18:18:03
【问题描述】:

我目前正在构建一个应用程序,它使用RealmRecyclerViewAdapter 来显示Realm 中的元素。

我正在考虑实现 Filterable 接口,我设法做到了(感谢这些答案:Link 1Link 2)但现在我有一个副作用:当我过滤时,Adapter显示所有元素,即使它们与过滤器不匹配。此外,排除的元素确实显示了不正确的信息。当我关闭SearchView时,一切都恢复正常了。

当我拨打Adapter时,这里是Activity

 public class MainActivity extends AppCompatActivity {
    private Realm realm;
    HabitCardAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setUIMode();
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Set the title inside the top bar for this activity.
        // I'm not doing it inside the Manifest because it changes the app's name
        setTitle(R.string.MainActivityTitle);

        // Bottom App Bar setup
        BottomAppBar bottomAppBar = findViewById(R.id.bottomAppBar);
        cutBottomAppEdge(bottomAppBar);     // Diamond shape

        // Add listener to Stats button inside the bottom app bar
        MenuItem statsMenuItem = bottomAppBar.getMenu().findItem(R.id.statsMenuItem);
        statsMenuItem.setOnMenuItemClickListener(item -> {
            if(item.getItemId() == R.id.statsMenuItem){
                Intent i = new Intent(getApplicationContext(), StatsActivity.class);
                startActivity(i);
                return true;
            }
            return false;
        });

        // FAB button setup
        FloatingActionButton fab = findViewById(R.id.fabAddButton);
        fab.setOnClickListener(view -> {
            Intent intent = new Intent(getBaseContext(), CreateHabitActivity.class);
            startActivity(intent);
        });

        RecyclerView rv = findViewById(R.id.habitCardRecyclerView);
        TextView emptyMessage = findViewById(R.id.mainEmptyHabitListMessage);
        realm = Realm.getDefaultInstance();
        RealmResults<Habit> results = realm.where(Habit.class).sort("id").findAll();

        results.addChangeListener(habits -> {
            if (habits.size() > 0) {
                rv.setVisibility(View.VISIBLE);
                emptyMessage.setVisibility(View.GONE);
            } else {
                emptyMessage.setVisibility(View.VISIBLE);
                rv.setVisibility(View.GONE);
            }
        });

        //this is necessarily because it is not changed yet
        if (results.size() > 0) {
            rv.setVisibility(View.VISIBLE);
            emptyMessage.setVisibility(View.GONE);

        } else {
            emptyMessage.setVisibility(View.VISIBLE);
            rv.setVisibility(View.GONE);
        }
        final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        rv.setLayoutManager(layoutManager);
        adapter = new HabitCardAdapter(results, true, this, realm);
        rv.setAdapter(adapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.top_app_bar_menu, menu);

        SearchView searchView = (SearchView) menu.findItem(R.id.searchMenuItem).getActionView();
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                adapter.getFilter().filter(query);
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                if (adapter != null) {
                    adapter.getFilter().filter(newText);
                    return true;
                }
                return false;
            }
        });
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection
        switch (item.getItemId()) {
            case R.id.searchMenuItem:
                return true;

            case R.id.settingMenuItem:
                Intent intent = new Intent(getApplicationContext(), SettingsActivity.class);
                startActivity(intent); //FIXME: animazione
                return true;

            case R.id.aboutMenuItem:
                MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
                builder.setTitle(getString(R.string.about_us_title));
                builder.setMessage(getString(R.string.about_us_message));
                builder.setIcon(R.drawable.ic_sprout_fg_small);
                builder.setPositiveButton("OK", (dialogInterface, i) -> {
                    dialogInterface.dismiss();
                });
                builder.show();
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }


    /**
     * Set the Night/Light UI. On the first run of the app, the user get the Light UI.
     */
    private void setUIMode() {

        SharedPreferences preferences = getSharedPreferences(SettingsActivity.SHARED_PREFS_FILE, MODE_PRIVATE);

        int pref = preferences.getInt(SettingsActivity.SHARED_PREFS_DARK_MODE, AppCompatDelegate.MODE_NIGHT_NO);

        AppCompatDelegate.setDefaultNightMode(pref);
    }

    private void cutBottomAppEdge(BottomAppBar bar) {
        BottomAppBarTopEdgeTreatment topEdge = new SproutBottomAppBarCutCornersTopEdge(
                bar.getFabCradleMargin(),
                bar.getFabCradleRoundedCornerRadius(),
                bar.getCradleVerticalOffset());
        MaterialShapeDrawable babBackground = (MaterialShapeDrawable) bar.getBackground();
        //It requires 1.1.0-alpha10
        babBackground.setShapeAppearanceModel(
                babBackground.getShapeAppearanceModel()
                        .toBuilder()
                        .setTopEdge(topEdge)
                        .build());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        realm.removeAllChangeListeners();
        realm.close();
    }
} 

这里是 HabitCardAdapter 扩展 RealmRecyclerViewAdapter

public class HabitCardAdapter extends RealmRecyclerViewAdapter<Habit, HabitCardAdapter.ViewHolder> implements Filterable {
    Context ct;
    OrderedRealmCollection<Habit> list;
    Realm mRealm;

    public HabitCardAdapter(@Nullable OrderedRealmCollection<Habit> data, boolean autoUpdate, Context context, Realm realm) {
        super(data, autoUpdate); //autoUpdate to true
        ct = context;
        list = data;
        mRealm = realm;
    }

    @Override
    public int getItemCount() {
        return this.list.size();
    }

    @NonNull
    @Override
    public HabitCardAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        //TODO: inflatare diversi tipi di carte a seconda del habitType
        View view = inflater.inflate(R.layout.fragment_habit_counter_card, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull HabitCardAdapter.ViewHolder holder, int position) {
        final Habit habit = getItem(position);
        if (habit != null) {
            holder.setHabit(habit);

            holder.editHabitButton.setOnClickListener(view -> {
                Intent intent = new Intent(ct, EditHabitActivity.class);
                intent.putExtra("HABIT_ID", habit.getId());
                //TODO: Aggiungere l'animazione
                ct.startActivity(intent);
            });

            holder.checkButton.setOnClickListener(view -> {
                int habitId = habit.getId();
                int newRepValue = habit.getRepetitions() + 1;
                int maxReps = habit.getMaxRepetitions();
                Log.d("Testing", newRepValue + " - " + maxReps);
                if (newRepValue <= habit.getMaxRepetitions()) {
                    habit.getRealm().executeTransaction(realm -> {
                        Habit result = realm.where(Habit.class).equalTo("id", habitId).findFirst();
                        if (result != null) {
                            result.setRepetitions(newRepValue);
                            String newLabel = "Completato " + newRepValue + " volte su " + maxReps;
                            holder.progressLabel.setText(newLabel);
                        }
                    });
                }
            });
        }

    }

    public void filterResults(String text) {
        text = text == null ? null : text.toLowerCase().trim();

        if (text == null || "".equals(text)) {
            updateData(mRealm.where(Habit.class).sort("id").findAllAsync());
        } else {
            updateData(mRealm.where(Habit.class).contains("title", text).sort("id").findAllAsync());
        }

    }

    public Filter getFilter() {
        HabitFilter filter = new HabitFilter(this);
        return filter;
    }

    private class HabitFilter extends Filter {
        private final HabitCardAdapter adapter;

        private HabitFilter(HabitCardAdapter adapter) {
            this.adapter = adapter;
        }

        @Override
        protected FilterResults performFiltering(CharSequence charSequence) {
            return new FilterResults();
        }

        @Override
        protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
            adapter.filterResults(charSequence.toString());
        }
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView habitTitle;
        ProgressBar progressBar;
        TextView progressLabel;
        ImageButton editHabitButton;
        Button checkButton;


        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            habitTitle = itemView.findViewById(R.id.habitCardTitle);
            editHabitButton = itemView.findViewById(R.id.counterHabitEditButton);
            progressBar = itemView.findViewById(R.id.counterHabitProgressBar);
            checkButton = itemView.findViewById(R.id.checkButton);
            progressLabel = itemView.findViewById(R.id.counterHabitProgressLabel);
        }

        void setHabit(Habit habit) {
            this.habitTitle.setText(habit.getTitle());
            this.progressBar.setProgress(habit.getRepetitions());
            this.progressBar.setMax(habit.getMaxRepetitions());
            this.progressLabel.setText("Completato " + habit.getRepetitions() + " volte su " + habit.getMaxRepetitions()); //FIXME: sposta la stringa
        }
    }
}

【问题讨论】:

    标签: java android filter realm realm-mobile-platform


    【解决方案1】:

    我真的不知道这是否是解决这个问题的方法,但它现在的行为符合预期,所以我将在这里分享解决方案。

    HabitCardAdapter 中,我添加了另一个OrderedRealmCollection&lt;Habit&gt; 成员,称为filteredList,而list 包含整个数据。在 costructor 中,filteredListlist 都与传递给构造函数的数据相关联,但是 filteredList 将被查询修改,list 不会(可能将其放入 final 是最好的实践)。 Then everything in the Adapter will now reference to filteredList instead of list, and when the SearchView is selected and the query is up, filteredList will get the data, and then updateData(filteredList) will be called .

    这是我改变的:

    public class HabitCardAdapter extends RealmRecyclerViewAdapter<Habit, HabitCardAdapter.ViewHolder> implements Filterable {
        Context ct;
        OrderedRealmCollection<Habit> list;
        OrderedRealmCollection<Habit> filteredList;
        Realm mRealm;
    
        ...
    }
    
    public HabitCardAdapter(@Nullable OrderedRealmCollection<Habit> data, Context context, Realm realm) {
            super(data, true, true);
            ct = context;
            list = data;
            filteredList = data;
            mRealm = realm;
            setHasStableIds(true);
        }
    

    可能错误出现在getItemCount() 中,当时filteredListsize 小于list 之一,但由于我没有引用filteredList,所以我没有任何办法更改该大小,因此Adapter 将继续显示 - 例如 - 6 个视图,而我正在查询 3。将它作为一个适当的类成员让我可以这样做:

    @Override
        public int getItemCount() {
            return this.filteredList.size();
        }
    
    public void filterResults(String text) {
            text = text == null ? null : text.toLowerCase().trim();
            if (text == null || "".equals(text)) {
                filteredList = list;
            } else {
                filteredList = mRealm.where(Habit.class).beginsWith("title", text, Case.INSENSITIVE).sort("id").findAll();
            }
            updateData(filteredList);
        }
    

    【讨论】:

      猜你喜欢
      • 2020-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-23
      • 1970-01-01
      • 1970-01-01
      • 2019-09-21
      • 1970-01-01
      相关资源
      最近更新 更多