首页 > 解决方案 > RecyclerView Adapter 无故改变对象的值

问题描述

我正在收听通知,因此我想创建一个 RecyclerView 用户可以用来排除某些应用程序。它显示了应用程序的徽标和名称,以及用于启用/禁用每个应用程序的切换按钮。

我创建了一个App包含每个应用程序的一些数据的类。

public class App {

    private String name;
    private String packageName;
    private Drawable icon;
    private boolean enabled;

    public App(String name, String packageName, Drawable icon, boolean enabled) {
        this.name = name;
        this.packageName = packageName;
        this.icon = icon;
        this.enabled = enabled;
    }

    public String getName() {
        return name;
    }

    public String getPackageName() {
        return packageName;
    }

    public Drawable getIcon() {
        return icon;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public boolean isEnabled() {
        return enabled;
    }
}

这是适配器:

public class AppsAdapter extends RecyclerView.Adapter<AppsAdapter.AppViewHolder> {

    private List<App> apps;

    public AppsAdapter(PackageManager packageManager) {
        apps = packageManager.getInstalledApplications(PackageManager.GET_META_DATA)
                .stream()
                .filter(applicationInfo -> packageManager.getLaunchIntentForPackage(applicationInfo.packageName) != null)
                .map(applicationInfo -> new App(applicationInfo.loadLabel(packageManager).toString(), applicationInfo.packageName, applicationInfo.loadIcon(packageManager), true))
                .collect(Collectors.toList());
    }

    @Override
    public AppViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new AppViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.app_item, parent, false));
    }

    @Override
    public void onBindViewHolder(AppsAdapter.AppViewHolder holder, int position) {
        App app = apps.get(position);

        holder.nameTextView.setText(app.getName());
        holder.appToggleButton.setChecked(app.isEnabled());
        holder.iconImageView.setImageDrawable(app.getIcon());
    
        holder.appToggleButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
            app.setEnabled(isChecked);
        });
    }

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

    protected static class AppViewHolder extends RecyclerView.ViewHolder {

        private TextView nameTextView;
        private ToggleButton appToggleButton;
        private ImageView iconImageView;

        public AppViewHolder(View itemView) {
            super(itemView);

            nameTextView = itemView.findViewById(R.id.name_text_view);
            appToggleButton = itemView.findViewById(R.id.app_toggle_button);
            iconImageView = itemView.findViewById(R.id.icon_image_view);
        }
    }
}

当我通过单击按钮“禁用”应用程序时,它似乎工作正常。但是当我在 RecyclerView 中向下滚动然后备份时,我禁用的应用程序的条目再次显示在屏幕上,该应用程序不再被禁用。

不幸的是,我不知道如何调试它以及可能导致此问题的原因。

编辑:如果我setOnCheckedChangeListener之前setChecked在切换按钮上打电话,它似乎正在工作。我不懂为什么。

标签: javaandroidandroid-recyclerview

解决方案


在适配器构造函数中启用 setHasStableIds(true)。

AppsAdapter(){
setHasStableIds(true);
}

推荐阅读