You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

问题根因

崩溃触发逻辑非常明确:

  1. 第一次进入页面执行onCreate时,布局内所有固定控件(textScreen、textQuestion、textTitle、editText)都正常挂载在根布局下,findViewById能正常找到实例,不会报错
  2. 答完题触发doValidate方法时,直接对根布局layoutParent调用了removeAllViews(),这个操作会把根布局下所有子View(包括前面说的几个固定控件)全部从视图树移除
  3. 移除完所有控件后,循环调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 17:30:46