【问题标题】:NullPointerException in RadioGroup.setOnCheckedChangeListener in APIS 15 & 16APIS 15 和 16 中 RadioGroup.setOnCheckedChangeListener 中的 NullPointerException
【发布时间】:2017-03-30 15:01:33
【问题描述】:

其实我要问你一个关于 RadioGroup 的 setOnCheckedChangeListener 中的 NPE 的问题。我已经在 15 到 23 的 API 中测试了这段代码,只有 API 15 和 16 会崩溃。

起初,我不需要解决NPE,我做到了。我需要知道为什么android给radioButton ID分配一个负值,这会导致'group.findViewById'返回NULL。

这里有代码:

private List<Question> listItems;

private Question getItem(int position) {
    return listItems.get(position);
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.questionLayout, parent, false);
    return new VHQuestion(v);
}

@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {

    final Question currentItem = getItem(position); 

    VHQuestion VHQuestion = (VHQuestion)holder;
    RadioGroup group = new RadioGroup(context);
    VHQuestion.listLayout.removeAllViewsInLayout();

    if(currentItem.getOptions() != null){
        for(int i = 0; i< currentItem.getOptions().size(); i++) {
            CustomRadioButton radioButton = new CustomRadioButton(context);
            radioButton.setText("Question " + i);
            group.addView(radioButton, i);
            if (currentItem.getAnswer() != null ) {
                group.check(radioButton.getId());
                // More code...
            }
        }
    }

    group.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {

            int radioButtonID = group.getCheckedRadioButtonId();
            CustomRadioButton checkedButton = (CustomRadioButton) group.findViewById(radioButtonID);
            if (checkedButton.hasAnswer()) {
                // More code...
            }

        }

    });

    VHQuestion.listLayout.addView(group);

}

class VHQuestion extends RecyclerView.ViewHolder{

    LinearLayout listLayout;

    public VHQuestion(View itemView) {
        this.listLayout = (LinearLayout)itemView.findViewById(R.id.card_layout);
    }

}

这里我们有xml“questionLayout.xml”

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tool="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:elevation="0dp">

    <android.support.v7.widget.CardView
        xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:id="@+id/card_view"
        android:layout_marginLeft="@dimen/side_margin_left"
        android:layout_marginRight="@dimen/side_margin"
        android:layout_marginBottom="5dp"
        android:layout_gravity="center"
        android:layout_width="match_parent"
        card_view:cardCornerRadius="0dp"
        card_view:cardElevation="0dp"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="@dimen/card_content_padding"
            android:layout_marginLeft="10dp">

            <LinearLayout
                android:id="@+id/card_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:layout_marginTop="10dp">
            </LinearLayout>

        </LinearLayout>
    </android.support.v7.widget.CardView>
</LinearLayout>

使用这段代码,我遇到了这个问题:

  • group.check(radioButton.getId()) 什么都不做。
  • checkedButton mID attr 具有负值(例如:-1352790336)。
  • CustomRadioButton checkedButton = (CustomRadioButton) group.findViewById(radioButtonID) 返回 null。
  • findViewByIdreturns null 如果 ID 值为 negative
  • if (checkedButton.hasAnswer()) 抛出 NPE。

所以,我不知道为什么这个 API 会抛出这个 NPE。

我已经解决了这个问题:

group.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(RadioGroup radiogroup, int checkedId) {

        if (shouldCallCheckedChange) {

            shouldCallCheckedChange = false;

            CustomRadioButton checkedButton = (CustomRadioButton) group.findViewById(checkedId);

            if (android.os.Build.VERSION.SDK_INT < 17) {
                for (int i = 0; i < group.getChildCount(); i++) {
                        ((CustomRadioButton) group.getChildAt(i)).setChecked(false);
                }
                for (int i = 0; i < group.getChildCount(); i++) {
                    if (group.getChildAt(i).getId() == checkedId) {
                        checkedButton = (CustomRadioButton) group.getChildAt(i);
                        checkedButton.setChecked(true);
                    }
                }
            }

            if (checkedButton.hasAnswer()) {
                // More code...
            }

            shouldCallCheckedChange = true;

        }

    }
});
...

还有这段代码: group.check(radioButton.getId());

被替换为: radioButton.setChecked(true);

所以我的问题是如何避免 NPE: 为什么 android 为动态创建的 RadioButton 分配负值?

谢谢大家!!

【问题讨论】:

  • 你从来没有为你的CustomRadioButton radioButton = new CustomRadioButton(context);设置一个ID。尝试通过radioButton.setId(id) 这样做。
  • @raxelsson 我在其他问题中找到了答案,但没有解释。是否有任何 Google 问题解释了为什么在 API 15 和 16 中需要使用radioButton.setId(id)
  • 如果你查看 View.java 源代码,你可以看到默认的 View id 是-1。默认情况下,此 ID 分配给所有视图。
  • :point_up: - @VladMatvienko 所说的。 SalvaCano,不确定这是不是真的。您不必在 API
  • @raxelsson,我知道我说的是真的:grepcode.com/file/repository.grepcode.com/java/ext/…

标签: android nullpointerexception radio-button radio-group


【解决方案1】:

我正在测试我的应用程序...我已经看到了

setOnCheckedChangeListener

有重载函数

onCheckedChanged

为 api15 和 api 16 中的单选按钮返回负 id... 在进行测试时,我认识到 RadioButtons 在 xml 中没有 id ... 这似乎是一个奇怪的错误......虽然它适用于最常见的 android api,但它不适用于 api 15-16.. 在我在 xml 上提供 id 后,它适用于 15-16.. 这是示例

android:id="@+id/sunday"

只需为每个单选按钮提供 id,您就会看到它起作用了

【讨论】:

    猜你喜欢
    • 2017-05-08
    • 2018-06-07
    • 2016-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多