Android调用TextView.setTypeface()报空指针异常求助
Android猜题游戏TextView空指针崩溃修复
报错信息
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setTypeface(android.graphics.Typeface)' on a null object reference at com.practechs.kubetnew28_05.GameActivity.addView(GameActivity.java:83) at com.practechs.kubetnew28_05.GameActivity.doValidate(GameActivity.java:137) at com.practechs.kubetnew28_05.GameActivity.access$200(GameActivity.java:20) at com.practechs.kubetnew28_05.GameActivity$1.onClick(GameActivity.java:104) at android.view.View.performClick(View.java:7441)
问题根因
崩溃触发逻辑非常明确:
- 第一次进入页面执行
onCreate时,布局内所有固定控件(textScreen、textQuestion、textTitle、editText)都正常挂载在根布局下,findViewById能正常找到实例,不会报错 - 答完题触发
doValidate方法时,直接对根布局layoutParent调用了removeAllViews(),这个操作会把根布局下所有子View(包括前面说的几个固定控件)全部从视图树移除 - 移除完所有控件后,循环调用
addView重新生成字母按钮,在addView里再次调用findViewById查找那几个固定TextView时,因为控件已经被删掉,返回null,调用setTypeface就触发了空指针
另外把固定控件的初始化、字体设置逻辑写在每次生成字母按钮都会调用的addView方法里,属于重复无效操作,也放大了问题触发概率。
修复步骤
- 第一步:修改布局文件,给原本留空的水平LinearLayout加专属id,作为动态字母按钮的容器,不要用根布局承载动态按钮
<LinearLayout android:id="@+id/layoutKeyboard" android:layout_marginLeft="24dp" android:layout_marginRight="24dp" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> </LinearLayout>
- 第二步:把固定控件的初始化、字体设置逻辑全部移到
onCreate方法中,只执行一次,不要放在addView里重复调用 - 第三步:所有动态添加、删除字母按钮的操作,都针对新增的
layoutKeyboard容器执行,禁止对根布局调用removeAllViews(),避免误删固定控件
修复后核心代码
onCreate方法
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_game); smallbigforth = AnimationUtils.loadAnimation(this, R.anim.smallbigforth); // 固定控件初始化、字体设置仅执行一次 Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/FredokaOneRegular.ttf"); textQuestion = findViewById(R.id.textQuestion); textScreen = findViewById(R.id.textScreen); textTitle = findViewById(R.id.textTitle); EditText editText = findViewById(R.id.editText); LinearLayout keyboardLayout = findViewById(R.id.layoutKeyboard); textQuestion.setTypeface(typeface); textScreen.setTypeface(typeface); textTitle.setTypeface(typeface); editText.setTypeface(typeface); keys = shuffleArray(keys); for (String key : keys) { addView(keyboardLayout, key, editText); } maxPresCounter = 4; }
addView方法
private void addView(LinearLayout viewParent, final String text, final EditText editText) { LinearLayout.LayoutParams linearLayoutParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT ); linearLayoutParams.rightMargin = 30; final TextView textView = new TextView(this); textView.setLayoutParams(linearLayoutParams); textView.setBackground(this.getResources().getDrawable(R.drawable.bgpink)); textView.setTextColor(this.getResources().getColor(R.color.colorPurple)); textView.setGravity(Gravity.CENTER); textView.setText(text); textView.setClickable(true); textView.setFocusable(true); textView.setTextSize(32); // 仅给动态生成的字母按钮设置字体 Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/FredokaOneRegular.ttf"); textView.setTypeface(typeface); textView.setOnClickListener(new View.OnClickListener() { @SuppressLint("SetTextI18n") @Override public void onClick(View v) { if(presCounter < maxPresCounter) { if (presCounter == 0) editText.setText(""); editText.setText(editText.getText().toString() + text); textView.startAnimation(smallbigforth); textView.animate().alpha(0).setDuration(300); presCounter++; if (presCounter == maxPresCounter) doValidate(); } } }); viewParent.addView(textView); }
doValidate方法
private void doValidate() { presCounter = 0; EditText editText = findViewById(R.id.editText); LinearLayout keyboardLayout = findViewById(R.id.layoutKeyboard); if(editText.getText().toString().equals(textAnswer)) { Intent a = new Intent(GameActivity.this,BossAct.class); startActivity(a); editText.setText(""); } else { Toast.makeText(GameActivity.this, "Wrong", Toast.LENGTH_SHORT).show(); editText.setText(""); } keys = shuffleArray(keys); // 仅清空键盘容器内的字母按钮,不会影响其他固定控件 keyboardLayout.removeAllViews(); for (String key : keys) { addView(keyboardLayout, key, editText); } }
内容的提问来源于stack exchange,提问作者Bishop
相关产品推荐
相关产品推荐

