我制作了一个应用程序,其中包含设备中所有已安装应用程序的列表,我在recyclerview中添加了一个复选框,以便在列表中选择一个应用程序(我将使用此应用程序作为应用程序的基础阻滞剂)。问题是当向上/向下滚动时,复选框状态总是会改变。恩。我检查了facebook然后我向下滚动,当我向上滚动时,facebook未经检查,有时会检查随机应用。
这是我的代码:
ApkInfoextractor:
public class ApkInfoExtractor {
Context context1;
public ApkInfoExtractor(Context context2){
context1 = context2;
}
public List<String> GetAllInstalledApkInfo(){
List<String> ApkPackageName = new ArrayList<>();
Intent intent = new Intent(Intent.ACTION_MAIN,null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED );
//Information that is returned from resolving an intent against an IntentFilter
List<ResolveInfo> resolveInfoList = context1.getPackageManager().queryIntentActivities(intent,0);
for(ResolveInfo resolveInfo : resolveInfoList){
ActivityInfo activityInfo = resolveInfo.activityInfo;
if(!isSystemPackage(resolveInfo)){
ApkPackageName.add(activityInfo.applicationInfo.packageName);
}
}
return ApkPackageName;
}
public boolean isSystemPackage(ResolveInfo resolveInfo){
return ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
}
public Drawable getAppIconByPackageName(String ApkTempPackageName){
Drawable drawable;
try{
drawable = context1.getPackageManager().getApplicationIcon(ApkTempPackageName);
}
catch (PackageManager.NameNotFoundException e){
e.printStackTrace();
drawable = ContextCompat.getDrawable(context1, R.mipmap.ic_launcher);
}
return drawable;
}
public String GetAppName(String ApkPackageName){
String Name = "";
ApplicationInfo applicationInfo;
PackageManager packageManager = context1.getPackageManager();
try {
applicationInfo = packageManager.getApplicationInfo(ApkPackageName, 0);
if(applicationInfo!=null){
Name = (String)packageManager.getApplicationLabel(applicationInfo);
}
}catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return Name;
}
}
AppsAdapter:
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();
}
}
我尝试过谷歌的许多解决方案,但这些解决方案都不适用于我。因此,详细的答案将会有所帮助(非常感谢示例代码或其他参考。)
答案 0 :(得分:1)
您可以使用Set
代替SparseBooleanArray HashSet<Integer> selection = new HashSet<>();
在onBind方法中使用以下,也使用标记而不是使位置最终
//saving states of the checkbox
viewHolder.itemView.setTag(position);
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = (int) v.getTag();
if (selection.contains(pos))
selection.remove(pos);
else
selection.add(pos);
notifyDataSetChanged();
}
});
viewHolder.checkBox.setChecked(selection.contains(position));
答案 1 :(得分:0)
过去2年我也遇到过这个问题。但是我使用HashMap
克服了这些问题。将布尔值保存在Hash Map
上单击的项目中。从HashMap
onBindViewHolder
您可以参考我的ConsistantRecylerAdapter
答案 2 :(得分:0)
将您的观看者更改为
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);
this.setIsRecyclable(false);
}
声明:
this.setIsRecyclable(false);
这只是解决方法,这可能会阻止回收者查看不重用单元格
答案 3 :(得分:0)
我遇到了完全相同的问题并在经过大量研究后得到了解决。原因是每次滚动列表项时都处于循环视图中列表项被回收(再次创建)因此丢失其实例,像textbox或edittext这样的视图不支持其数据。
您可以尝试按照以下方法解决此问题:
单击复选框保存模型类中的值,然后在onCreate中检查JSON模型类中的值并分配给复选框
onCreate:
if(model.isChecked)) {
checkbox.setChecked(true);
}else{
checkbox.setChecked(false);
}
然后点击复选框时点击:
checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){
model.setIsChecked(isChecked);
}
我相信这会解决你的问题。