【发布时间】: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())什么都不做。 -
checkedButtonmID 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