在自定义列表视图中保存选中状态的复选框时出错

时间:2016-07-29 09:22:40

标签: android listview android-sharedpreferences

我想在listview中保存复选框的选中状态,以便当我转到另一个活动然后返回此活动时,所选的检查工具应保持选中状态。我使用自定义适配器来显示两种类型的布局。我使用sparsebooleanarray和sharedpreference来保存检查状态。这在使用List时有效但我在使用List时遇到NullPointerException。有没有办法在这里拯救国家?

public class ListViewActivity extends AppCompatActivity {

    SharedPreferences sharedPreferences;
    ListView listView;

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

        listView = (ListView) findViewById(R.id.listview);

        List<Item> items = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            items.add(new Item("I am TextView layout #" + i, Item.TYPE_TEXTVIEW, false));
            items.add(new Item("I am ImageView layout #" + i, Item.TYPE_IMAGEVIEW, false));
        }

        MultipleLayoutAdapter adapter = new MultipleLayoutAdapter(this, items);
        listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        listView.setAdapter(adapter);

        sharedPreferences = getSharedPreferences("MySharedPrefs", Context.MODE_PRIVATE);



        Set<String> checkedItemsSource = sharedPreferences.getStringSet("checked_items", new HashSet<String>());
        SparseBooleanArray checkedItems = convertToCheckedItems(checkedItemsSource);
        for (int i = 0; i < checkedItems.size(); i++) {
            int checkedPosition = checkedItems.keyAt(i);
            listView.setItemChecked(checkedPosition, true);
        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        SparseBooleanArray checkedItems = listView.getCheckedItemPositions();
////got exception here
        Set<String> stringSet = convertToStringSet(checkedItems);
        sharedPreferences.edit()
                .putStringSet("checked_items", stringSet)
                .apply();
    }

    private SparseBooleanArray convertToCheckedItems(Set<String> checkedItems) {
        SparseBooleanArray array = new SparseBooleanArray();
        for(String itemPositionStr : checkedItems) {
            int position = Integer.parseInt(itemPositionStr);
            array.put(position, true);
        }

        return array;
    }

    private Set<String> convertToStringSet(SparseBooleanArray checkedItems) {
        Set<String> result = new HashSet<>();
////got exception here
        for (int i = 0; i < checkedItems.size(); i++) {
            result.add(String.valueOf(checkedItems.keyAt(i)));
        }

        return result;
    }
}


public class MultipleLayoutAdapter extends BaseAdapter {

    private Context    context;
    private List<Item> items;

    public MultipleLayoutAdapter(Context context, List<Item> items) {
        this.context = context;
        this.items = new ArrayList<>(items);
    }

    @Override
    public int getCount() {
        return items.size();
    }

    @Override
    public Item getItem(int position) {
        return items.get(position);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public int getViewTypeCount() {
        return 2;
    }

    @Override
    public int getItemViewType(int position) {
        return getItem(position).getType();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Item item = getItem(position);
        int viewType = getItemViewType(position);
        switch (viewType) {

            case Item.TYPE_TEXTVIEW:
                convertView = inflateTextView(convertView, parent, item);
                break;

            case Item.TYPE_IMAGEVIEW:
                convertView = inflateImageView(convertView, parent, item);
                break;
        }
        return convertView;
    }


    private View inflateTextView(View convertView, ViewGroup parent, Item item) {
        TextViewHolder viewHolder;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.textview_list_row, parent, false);
            viewHolder = new TextViewHolder(convertView);
            convertView.setTag(viewHolder);
        }
        else {
            viewHolder = (TextViewHolder) convertView.getTag();
        }

        viewHolder.textView.setText(item.getData());
        viewHolder.checkBox.setChecked(item.isBox());

        return convertView;
    }

    private View inflateImageView(View convertView, ViewGroup parent, Item item) {
        ImageViewHolder viewHolder;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.imageview_list_row, parent, false);
            viewHolder = new ImageViewHolder(convertView);
            convertView.setTag(viewHolder);
        }
        else {
            viewHolder = (ImageViewHolder) convertView.getTag();
        }

        viewHolder.textView.setText(item.getData());
        viewHolder.checkBox.setChecked(item.isBox());


        return convertView;
    }




    static class TextViewHolder {
        private TextView textView;
        private CheckBox checkBox;

        public TextViewHolder(View convertView) {
            this.textView = (TextView) convertView.findViewById(R.id.textview);
            this.checkBox = (CheckBox) convertView.findViewById(R.id.checkbox);
        }
    }

    static class ImageViewHolder {
        private ImageView imageView;
        private TextView  textView;
        private CheckBox checkBox;

        public ImageViewHolder(View convertView) {
            this.imageView = (ImageView) convertView.findViewById(R.id.imageview);
            this.textView = (TextView) convertView.findViewById(R.id.textview);
            this.checkBox = (CheckBox) convertView.findViewById(R.id.checkbox);
        }
    }

}

public class Item {
    public static final int TYPE_TEXTVIEW  = 0;
    public static final int TYPE_IMAGEVIEW = 1;

    private String data;
    private int    type;
    private boolean box;
    private Context context;

    public Item(Context context) {
        this.context = context;
    }

    public Item(String data, int type, boolean box) {
        this.data = data;
        this.type = type;
        this.box = box;
    }

    public String getData() {
        return data;
    }

    public int getType() {
        return type;
    }

    public boolean isBox() {
        return box;
    }

    public void setBox(boolean box) {
        this.box = box;
    }
}

2 个答案:

答案 0 :(得分:0)

如果我们转到grep code,我们会看到:

public SparseBooleanArray More ...getCheckedItemPositions() {
    if (mChoiceMode != CHOICE_MODE_NONE) {
        return mCheckStates;
    }
    return null;
}

我们记得,当你致电listView.getCheckedItemPositions()时,你收到了空。所以我认为可能是,因为你没有使用listView.setChoiceMode

答案 1 :(得分:0)

<强> MultipleLayoutAdapter

public class MultipleLayoutAdapter extends BaseAdapter {

private Context context;
private List<Item> items;

public MultipleLayoutAdapter(Context context, List<Item> items) {
    this.context = context;
    this.items = new ArrayList<>(items);
}

@Override
public int getCount() {
    return items.size();
}

@Override
public Item getItem(int position) {
    return items.get(position);
}

@Override
public long getItemId(int i) {
    return i;
}

@Override
public int getViewTypeCount() {
    return 2;
}

@Override
public int getItemViewType(int position) {
    return getItem(position).getType();
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    Item item = getItem(position);
    int viewType = getItemViewType(position);
    switch (viewType) {

        case Item.TYPE_TEXTVIEW:
            convertView = inflateTextView(convertView, parent, item);
            break;

        case Item.TYPE_IMAGEVIEW:
            convertView = inflateImageView(convertView, parent, item);
            break;
    }
    return convertView;
}


private View inflateTextView(View convertView, ViewGroup parent, final Item item) {
    TextViewHolder viewHolder;
    if (convertView == null) {
        convertView = LayoutInflater.from(context).inflate(R.layout.textview_list_row, parent, false);
        viewHolder = new TextViewHolder(convertView);
        convertView.setTag(viewHolder);
    }
    else {
        viewHolder = (TextViewHolder) convertView.getTag();
    }

    viewHolder.textView.setText(item.getData());

    viewHolder.checkBox.setOnCheckedChangeListener(null);
    viewHolder.checkBox.setChecked(item.isBox());
    viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
            item.setBox(b);
        }
    });

    return convertView;
}

private View inflateImageView(View convertView, ViewGroup parent, final Item item) {
    ImageViewHolder viewHolder;
    if (convertView == null) {
        convertView = LayoutInflater.from(context).inflate(R.layout.imageview_list_row, parent, false);
        viewHolder = new ImageViewHolder(convertView);
        convertView.setTag(viewHolder);
    }
    else {
        viewHolder = (ImageViewHolder) convertView.getTag();
    }

    viewHolder.textView.setText(item.getData());

    viewHolder.checkBox.setOnCheckedChangeListener(null);
    viewHolder.checkBox.setChecked(item.isBox());
    viewHolder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
            item.setBox(b);
        }
    });


    return convertView;
}




static class TextViewHolder {
    private TextView textView;
    private CheckBox checkBox;

    public TextViewHolder(View convertView) {
        this.textView = (TextView) convertView.findViewById(R.id.textview);
        this.checkBox = (CheckBox) convertView.findViewById(R.id.checkbox);
    }
}

static class ImageViewHolder {
    private ImageView imageView;
    private TextView textView;
    private CheckBox checkBox;

    public ImageViewHolder(View convertView) {
        this.imageView = (ImageView) convertView.findViewById(R.id.imageview);
        this.textView = (TextView) convertView.findViewById(R.id.textview);
        this.checkBox = (CheckBox) convertView.findViewById(R.id.checkbox);
    }
}

}

<强> MainActivity

public class MainActivity extends AppCompatActivity {

SharedPreferences sharedPreferences;
ListView listView;
List<Item> items = new ArrayList<>();
MultipleLayoutAdapter adapter;

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

    listView = (ListView) findViewById(R.id.listview);

    for (int i = 1; i <= 10; i++) {
        items.add(new Item("I am TextView layout #" + i, Item.TYPE_TEXTVIEW, false));
        items.add(new Item("I am ImageView layout #" + i, Item.TYPE_IMAGEVIEW, false));
    }

    findViewById(R.id.btn_go).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            startActivity(new Intent(MainActivity.this, Main2Activity.class));
        }
    });
}

@Override
protected void onResume() {
    super.onResume();

    sharedPreferences = getSharedPreferences("MySharedPrefs", Context.MODE_PRIVATE);
    Set<String> checkedItemsSource = sharedPreferences.getStringSet("checked_items", new HashSet<String>());
    SparseBooleanArray checkedItems = convertToCheckedItems(checkedItemsSource);

    for (int i = 0; i < checkedItems.size(); i++) {
        int checkedPosition = checkedItems.keyAt(i);
        items.get(checkedPosition).setBox(true);
    }

    if (adapter == null) {
        adapter = new MultipleLayoutAdapter(this, items);
        listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        listView.setAdapter(adapter);
    } else {
        adapter.notifyDataSetChanged();
    }
}

@Override
protected void onPause() {
    Set<String> stringSet = new HashSet<>();
    for (int i = 0; i < items.size(); i++) {
        if (items.get(i).isBox()) {
            stringSet.add(String.valueOf(i));
        }
    }

    sharedPreferences.edit()
            .putStringSet("checked_items", stringSet)
            .apply();

    super.onPause();
}

private SparseBooleanArray convertToCheckedItems(Set<String> checkedItems) {
    SparseBooleanArray array = new SparseBooleanArray();
    for (String itemPositionStr : checkedItems) {
        int position = Integer.parseInt(itemPositionStr);
        array.put(position, true);
    }

    return array;
}

private Set<String> convertToStringSet(SparseBooleanArray checkedItems) {
    Set<String> result = new HashSet<>();
    for (int i = 0; i < checkedItems.size(); i++) {
        result.add(String.valueOf(checkedItems.keyAt(i)));
    }

    return result;
}
}