Recycleview checkbox state keeps changing

时间:2018-02-03 09:20:38

标签: android checkbox android-recyclerview

I have an app that shows a list of all the installed apps inside a user's phone. I want to add a checkbox to every cardview because I'm planning to make an app blocker app. The problem is the checkboxes always change their states when I move up/down the list.

here's my code:

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

    private Context context1;
    private List<String> stringList;

    public AppsAdapter(Context context, List<String> list){
        context1 = context;
        stringList = list;
    }

    //viewholder initialized
    @Override
    public AppsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){

        View view2 = LayoutInflater.from(context1).inflate(R.layout.cardview_layout,parent,false);
        ViewHolder viewHolder = new ViewHolder(view2);
        return viewHolder;
    }

    private SparseBooleanArray sba = new SparseBooleanArray();

    //DATA IS BOUND TO VIEWS
    @Override
    public void onBindViewHolder(ViewHolder viewHolder,final int position){

        viewHolder.setIsRecyclable(false);
        ApkInfoExtractor apkInfoExtractor = new ApkInfoExtractor(context1);
            final String ApplicationPackageName = (String) stringList.get(position);

        //calling apps name and icon
        String ApplicationLabelName = apkInfoExtractor.GetAppName(ApplicationPackageName);
        Drawable drawable = apkInfoExtractor.getAppIconByPackageName(ApplicationPackageName);

        //setting app name and icon for every card
        viewHolder.textView_App_Name.setText(ApplicationLabelName);
        viewHolder.imageView.setImageDrawable(drawable);

        //saving states of the checkbox
        viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sba.put(position, !sba.get(position));
                notifyDataSetChanged();
            }
        });
        viewHolder.checkBox.setChecked(sba.get(position));

    }

    //viewholder
    public class ViewHolder extends RecyclerView.ViewHolder{

        public CardView cardView;
        public ImageView imageView;
        public TextView textView_App_Name;
        public CheckBox checkBox;

        public ViewHolder (View view){

            super(view);
            checkBox = (CheckBox) view.findViewById(R.id.chckbox);
            cardView = (CardView) view.findViewById(R.id.card_view);
            imageView = (ImageView) view.findViewById(R.id.imageview);
            textView_App_Name = (TextView) view.findViewById(R.id.Apk_Name);
            //textView_App_Package_Name = (TextView) view.findViewById(R.id.Apk_Package_Name);

        }
    }


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

any answer will be appreciated.

2 个答案:

答案 0 :(得分:0)

This should be your main class

public class AppPackage {
    public String package;
    public String name;
    public Drawable icon;
    public boolean isChecked;
}

Then create a list of objects with the info taken from the package manager and fill the properties you need in the Adapter:

public List<AppPackage> myPackageList = {your implementation}

Then your adapter should be something similar to this:

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

    private Context context1;
    private List<AppPackage> appPackageList;

    public AppsAdapter(Context context, List<AppPackage> appPackageList){
        context1 = context;
        this.appPackageList = appPackageList;
    }

    //viewholder initialized
    @Override
    public AppsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
        View view2 = LayoutInflater.from(context1)
               .inflate(R.layout.cardview_layout,parent,false);
        ViewHolder viewHolder = new ViewHolder(view2);
        return viewHolder;
    }

    //DATA IS BOUND TO VIEWS
    @Override
    public void onBindViewHolder(ViewHolder viewHolder,final int position){

        final AppPackage app = appPackageList.get(position); 

        //setting app name and icon for every card
        viewHolder.textView_App_Name.setText(app.name);
        viewHolder.imageView.setImageDrawable(app.icon);

        //saving states of the checkbox
        viewHolder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                 //save the state of the current checked app
                 app.IsChecked = isChecked;
             }
        });    
    }

    //viewholder
    public class ViewHolder extends RecyclerView.ViewHolder{

        public CardView cardView;
        public ImageView imageView;
        public TextView textView_App_Name;
        public CheckBox checkBox;

        public ViewHolder (View view){

            super(view);
            checkBox = (CheckBox) view.findViewById(R.id.chckbox);
            cardView = (CardView) view.findViewById(R.id.card_view);
            imageView = (ImageView) view.findViewById(R.id.imageview);
            textView_App_Name = (TextView) view.findViewById(R.id.Apk_Name);
            //textView_App_Package_Name = (TextView) view.findViewById(R.id.Apk_Package_Name);

        }
    }


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

答案 1 :(得分:0)

you are not putting value in SparseBooleanArray..

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

private Context context1;
private List<String> stringList;

public AppsAdapter(Context context, List<String> list){
    context1 = context;
    stringList = list;
}

//viewholder initialized
@Override
public AppsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){

    View view2 = LayoutInflater.from(context1).inflate(R.layout.cardview_layout,parent,false);
    ViewHolder viewHolder = new ViewHolder(view2);
    return viewHolder;
}

private SparseBooleanArray sba = new SparseBooleanArray();

//DATA IS BOUND TO VIEWS
@Override
public void onBindViewHolder(ViewHolder viewHolder,final int position){

    viewHolder.setIsRecyclable(false);
    ApkInfoExtractor apkInfoExtractor = new ApkInfoExtractor(context1);
    final String ApplicationPackageName = (String) stringList.get(position);

    // here the modification in your source code
    // you just put this line
    sba.put(position,viewHolder.checkBox.isChecked());

    //calling apps name and icon
    String ApplicationLabelName = apkInfoExtractor.GetAppName(ApplicationPackageName);
    Drawable drawable = apkInfoExtractor.getAppIconByPackageName(ApplicationPackageName);

    //setting app name and icon for every card
    viewHolder.textView_App_Name.setText(ApplicationLabelName);
    viewHolder.imageView.setImageDrawable(drawable);

    //saving states of the checkbox
    viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            sba.put(position, !sba.get(position));
            notifyDataSetChanged();
        }
    });
    viewHolder.checkBox.setChecked(sba.get(position));

}

//viewholder
public class ViewHolder extends RecyclerView.ViewHolder{

    public CardView cardView;
    public ImageView imageView;
    public TextView textView_App_Name;
    public CheckBox checkBox;

    public ViewHolder (View view){

        super(view);
        checkBox = (CheckBox) view.findViewById(R.id.chckbox);
        cardView = (CardView) view.findViewById(R.id.card_view);
        imageView = (ImageView) view.findViewById(R.id.imageview);
        textView_App_Name = (TextView) view.findViewById(R.id.Apk_Name);
        //textView_App_Package_Name = (TextView) view.findViewById(R.id.Apk_Package_Name);

    }
}


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