簡體   English   中英

將復選框的選中狀態保存在自定義列表視圖中時出錯

[英]Error saving checked state of checkbox in custom listview

我想將復選框的選中狀態保存在我的列表視圖中,這樣當我轉到另一個活動然后又回到該活動時,所選的checkox應保持選中狀態。 我使用了自定義適配器來顯示2種布局。 我使用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;
    }
}

如果轉到grep代碼 ,我們將看到:

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

我們還記得,在調用listView.getCheckedItemPositions()時,您將獲得null。 所以我想可能是因為您沒有使用listView.setChoiceMode

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);
    }
}

}

主要活動

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;
}
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM