当我使用自定义适配器和listView取消选中所有项目时,应用程序崩溃

时间:2017-10-25 13:54:03

标签: android listview

我正在尝试检查Tweet列表中的项目:

public class Tweet implements Parcelable {
private int color;
private String pseudo;
private String text;

public Tweet(int color, String pseudo, String text) {
    this.color = color;
    this.pseudo = pseudo;
    this.text = text;
}

public int getColor(){ return this.color; }
public String getPseudo(){ return this.pseudo; }
public String getText(){ return this.text; }

public int setColor(){ return this.color; }
public String setPseudo(){ return this.pseudo; }
public String setText(){ return this.text; }

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel out, int flags) {
    out.writeString(pseudo);
    out.writeString(text);
    out.writeInt(color);
}

public static final Parcelable.Creator<Tweet> CREATOR = new Parcelable.Creator<Tweet>() {
    public Tweet createFromParcel(Parcel in) {
        return new Tweet(in);
    }

    public Tweet[] newArray(int size) {
        return new Tweet[size];
    }
};

protected Tweet(Parcel in) {
    pseudo = in.readString();
    text = in.readString();
    color = in.readInt();
}
}

这里是主要活动的代码:

public class MainActivity extends AppCompatActivity {
private ListView _m_list_view;

TweetAdapter _m_tweet_adaptateur;
List<Tweet> _m_tweets;
@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    _m_list_view = (ListView) findViewById(R.id.list_view);

    _m_tweets = genererTweets();

    _m_tweet_adaptateur = new TweetAdapter(MainActivity.this,
            _m_tweets, _m_list_view.getChoiceMode());
    _m_list_view.setAdapter(_m_tweet_adaptateur);

    _m_list_view.setClickable(true);
    _m_list_view.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Intent tmp_intent;
            // lancement 2nde activité avec un seul item
            tmp_intent = new Intent(MainActivity.this, ShowTweetDetailActivity.class);
            //startActivityForResult(tmp_intent, 0);*
            tmp_intent.putExtra("tweet",(Tweet)_m_list_view.getItemAtPosition(position));
            startActivity(tmp_intent);
        }
    });
    _m_list_view.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
            _m_list_view.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
            _m_tweet_adaptateur.setChoiseMode(_m_list_view.getChoiceMode());
            _m_list_view.setItemChecked(i, true);
            return true;
        }
    });

    _m_list_view.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
        @Override
        public void onItemCheckedStateChanged(ActionMode actionMode, int i, long l, boolean b) {

            updateActionModeTitle(actionMode);
        }

        @Override
        public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.context_menu_tweet, menu);
            actionMode.setCustomView(LayoutInflater.from(MainActivity.this).inflate(R.layout.menu_select_tweet, null));
            updateActionModeTitle(actionMode);
            return(true);
        }

        @Override
        public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
            return false;
        }

        @Override
        public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
            switch (menuItem.getItemId()) {
                //quand on appui sur ok dans le menu
                case R.id.item_select_multi_tweet:
                  /*  int ii;
                    int tmp_key;
                    Intent tmp_intent;
                    ArrayList tmp_list;
                    SparseBooleanArray tmp_checked_list;
                    tmp_list = new ArrayList();
                    tmp_checked_list = _m_list_view.getCheckedItemPositions();
                    if (tmp_checked_list != null) {
                        for (ii = 0; ii < tmp_checked_list.size(); ii++) {
                            tmp_key = tmp_checked_list.keyAt(ii);
                            if (tmp_checked_list.get(tmp_key)) {
                                tmp_list.add(_m_list_view.getItemAtPosition(tmp_key));
                            }
                        }
                        tmp_intent = new Intent(MainActivity.this, ShowTweetDetailActivity.class);
                        //startActivityForResult(tmp_intent, 0);*
                        tmp_intent.putExtra("tweet",tmp_list);
                        startActivity(tmp_intent);
                    }
                    return true;*/
                default:
                    return false;
            }
        }

        @Override
        public void onDestroyActionMode(ActionMode actionMode) {
            _m_list_view.setChoiceMode(ListView.CHOICE_MODE_NONE);
            _m_tweet_adaptateur.setChoiseMode(_m_list_view.getChoiceMode());
            _m_list_view.setAdapter(_m_tweet_adaptateur);
        }
    });

}

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    getMenuInflater().inflate(R.menu.context_menu_tweet, menu);
}

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

private void updateActionModeTitle(ActionMode in_action_mode) {
    int tmp_count;
    TextView tmp_textview;

    tmp_count = _m_list_view.getCheckedItemCount();
    tmp_textview = (TextView) in_action_mode.getCustomView().findViewById(R.id.context_menu_select_tweet_textview);
    tmp_textview.setText(tmp_count + " " + "Tweet" + ((tmp_count > 1) ? "s" : ""));

    if (tmp_count < _m_list_view.getCount()) {
        ((CheckBox) in_action_mode.getCustomView().findViewById(R.id.context_menu_select_tweet_checkbox)).setChecked(false);
    }
    else {
        ((CheckBox) in_action_mode.getCustomView().findViewById(R.id.context_menu_select_tweet_checkbox)).setChecked(true);
    }
}

public void onSelectAllTweet(View in_view) {
    int ii;
    boolean tmp_checked;

    tmp_checked = ((CheckBox) in_view).isChecked();

    if (tmp_checked) {
        for (ii=0; ii<_m_list_view.getCount(); ii++) {
            _m_list_view.setItemChecked(ii, true);
        }
    }
    else {
        for (ii=0; ii<_m_list_view.getCount(); ii++) {
            _m_list_view.setItemChecked(ii, false);
        }
    }
}

    private List<Tweet> genererTweets(){
    List<Tweet> tweets = new ArrayList<Tweet>();
    tweets.add(new Tweet(Color.BLACK, "Florent", "Mon premier tweet !"));
    tweets.add(new Tweet(Color.BLUE, "Kevin", "C'est ici que ça se passe !"));
    tweets.add(new Tweet(Color.GREEN, "Logan", "Que c'est beau..."));
    tweets.add(new Tweet(Color.RED, "Mathieu", "Il est quelle heure ??"));
    tweets.add(new Tweet(Color.GRAY, "Willy", "On y est presque"));
    return tweets;
}

我的CustomAdapter:

public class TweetAdapter extends BaseAdapter {

private int _m_choice_mode;
private List<Tweet> _m_tweet_list;
private Context _m_context;
//tweets est la liste des models à afficher
public TweetAdapter(Context context, List<Tweet> tweets, int in_choice_mode) {
    _m_choice_mode = in_choice_mode;
    _m_tweet_list = tweets;
    _m_context = context;
}

public void setChoiseMode(int in_choise_mode) {
    _m_choice_mode = in_choise_mode;
}


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

@Override
public Tweet getItem(int position) {
    return _m_tweet_list.get(position);
}

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

@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {

    if(convertView == null){
        convertView = LayoutInflater.from(_m_context).inflate(R.layout.row_tweet,parent, false);
    }

    TweetViewHolder viewHolder = (TweetViewHolder) convertView.getTag();
    if(viewHolder == null){
        viewHolder = new TweetViewHolder();
        viewHolder.m_selector = (ImageView) convertView.findViewById(R.id.selector);
        viewHolder.pseudo = (TextView) convertView.findViewById(R.id.pseudotweet);
        viewHolder.text = (TextView) convertView.findViewById(R.id.texttweet);
        viewHolder.avatar = (ImageView) convertView.findViewById(R.id.avatartweet);
        convertView.setTag(viewHolder);
    }

    //getItem(position) va récupérer l'item [position] de la List<Tweet> tweets
    Tweet tweet = getItem(position);

    //il ne reste plus qu'à remplir notre vue
    viewHolder.pseudo.setText(tweet.getPseudo());
    viewHolder.text.setText(tweet.getText());
    viewHolder.avatar.setImageDrawable(new ColorDrawable(tweet.getColor()));

    if (_m_choice_mode == ListView.CHOICE_MODE_MULTIPLE_MODAL) {
        viewHolder.m_selector.setVisibility(View.VISIBLE);
    }
    else {
        viewHolder.m_selector.setVisibility(View.GONE);
    }

    return convertView;
}

private class TweetViewHolder{
    public ImageView m_selector;
    public TextView pseudo;
    public TextView text;
    public ImageView avatar;

}

当ListView处于CHOICE_MODE_MULTIPLE_MODAL模式时取消选中所有项目时出现问题(当我们长时间点击项目时设置此模式)。当我取消选中上次检查的项目时,onDestroyActionMode方法(更准确地说是行_m_list_view.setChoiceMode(...))会给我一个错误,应用程序崩溃而没有消息。
日志:

10-25 15:38:43.396 31949-31949/com.example.vvigie.testappactires D/Error: ERR: stack=java.lang.StackOverflowError: stack size 8MB
                                                                          at android.support.v7.view.SupportActionModeWrapper.finish(SupportActionModeWrapper.java:82)
                                                                          at android.widget.AbsListView.setChoiceMode(AbsListView.java:1603)
                                                                          at com.example.vvigie.testappactires.MainActivity$3.onDestroyActionMode(MainActivity.java:135)
                                                                          at android.widget.AbsListView$MultiChoiceModeWrapper.onDestroyActionMode(AbsListView.java:8355)
                                                                          at com.android.internal.policy.impl.PhoneWindow$DecorView$ActionModeCallbackWrapper.onDestroyActionMode(PhoneWindow.java:3963)
                                                                          at android.support.v7.view.SupportActionModeWrapper$CallbackWrapper.onDestroyActionMode(SupportActionModeWrapper.java:179)
                                                                          at android.support.v7.app.AppCompatDelegateImplV9$ActionModeCallbackWrapperV9.onDestroyActionMode(AppCompatDelegateImplV9.java:1806)
                                                                          at android.support.v7.app.WindowDecorActionBar$ActionModeImpl.finish(WindowDecorActionBar.java:1007)
                                                                          at android.support.v7.view.SupportActionModeWrapper.finish(SupportActionModeWrapper.java:82)
                                                                          at android.widget.AbsListView.setChoiceMode(AbsListView.java:1603)
                                                                          at com.example.vvigie.testappactires.MainActivity$3.onDestroyActionMode(MainActivity.java:135)
                                                                          at android.widget.AbsListView$MultiChoiceModeWrapper.onDestroyActionMode(AbsListView.java:8355)
                                                                          at com.android.internal.policy.impl.PhoneWindow$DecorView$ActionModeCallbackWrapper.onDestroyActionMode(PhoneWindow.java:3963)
                                                                          at android.support.v7.view.SupportActionModeWrapper$CallbackWrapper.onDestroyActionMode(SupportActionModeWrapper.java:179)
                                                                          at android.support.v7.app.AppCompatDelegateImplV9$ActionModeCallbackWrapperV9.onDestroyActionMode(AppCompatDelegateImplV9.java:1806)
                                                                          at android.support.v7.app.WindowDecorActionBar$ActionModeImpl.finish(WindowDecorActionBar.java:1007)
                                                                          at android.support.v7.view.SupportActionModeWrapper.finish(SupportActionModeWrapper.java:82)
                                                                          at android.widget.AbsListView.setChoiceMode(AbsListView.java:1603)
                                                                          at com.example.vvigie.testappactires.MainActivity$3.onDestroyActionMode(MainActivity.java:135)
                                                                          at android.widget.AbsListView$MultiChoiceModeWrapper.onDestroyActionMode(AbsListView.java:8355)
                                                                          at com.android.internal.policy.impl.PhoneWindow$DecorView$ActionModeCallbackWrapper.onDestroyActionMode(PhoneWindow.java:3963)
                                                                          at android.support.v7.view.SupportActionModeWrapper$CallbackWrapper.onDestroyActionMode(SupportActionModeWrapper.java:179)
                                                                          at android.support.v7.app.AppCompatDelegateImplV9$ActionModeCallbackWrapperV9.onDestroyActionMode(AppCompatDelegateImplV9.java:1806)
                                                                          at android.support.v7.app.WindowDecorActionBar$ActionModeImpl.finish(WindowDecorActionBar.java:1007)
                                                                          at android.support.v7.view.SupportActionModeWrapper.finish(SupportActionModeWrapper.java:82)
                                                                          at android.widget.AbsListView.setChoiceMode(AbsListView.java:1603)
                                                                          at com.example.vvigie.testappactires.MainActivity$3.onDestroyActionMode(MainActivity.java:135)
                                                                          at android.widget.AbsListView$MultiChoiceModeWrapper.onDestroyActionMode(AbsListView.java:8355)
                                                                          at com.android.internal.policy.impl.PhoneWindow$DecorView$ActionModeCallbackWrapper.onDestroyActionMode(PhoneWindow.java:3963)
                                                                          at android.support.v7.view.SupportActionModeWrapper$CallbackWrapper.onDestroyActionMode(SupportActionModeWrapper.java:179)
                                                                          at android.support.v7.app.AppCompatDelegateImplV9$ActionModeCallbackWrapperV9.onDestroyActionMode(AppCompatDelegateImplV9.java:1806)
                                                                          at android.support.v7.app.WindowDecorActionBar$ActionModeImpl.finish(WindowDecorActionBar.java:1007)
                                                                          at android.support.v7.view.SupportActionModeWrapper.finish(SupportActionModeWrapper.java:82)
                                                                          at android.widget.AbsListView.setChoiceMode(AbsListView.java:1603)
                                                                          at com.example.vvigie.testappactires.MainActivity$3.onDestroyActionMode(MainActivity.java:135)
                                                                          at android.widget.AbsListView$MultiChoiceModeWrapper.onDestroyActionMode(AbsListView.java:8355)
                                                                          at com.android.internal.policy.impl.PhoneWindow$DecorView$ActionModeCallbackWrapper.onDestroyActionMode(PhoneWindow.java:3963)
                                                                          at android.support.v7.view.SupportActionModeWrapper$CallbackWrapper.onDestroyActionMode(SupportActionModeWrapper.java:179)
                                                                        at android.support.v7.app.AppCom

我不明白为什么这条线会带来这个错误...你能帮帮我吧。 抱歉,我的“法语”英语。

编辑:解决方案在评论中,谢谢!

1 个答案:

答案 0 :(得分:1)

你有一个无限的呼叫循环。此行_m_list_view.setChoiceMode(ListView.CHOICE_MODE_NONE);会导致AbsListView.MultiChoiceModeListener#onDestroyActionMode()被调用,再次调用第一行等等。

摘要是您不应该在_m_list_view.setChoiceMode()中致电onDestroyActionMode(),或者至少不需要将其设置为NONE