findViewById在子类SurfaceView中抛出RuntimeException

时间:2010-10-09 17:42:19

标签: android

如果我将findViewById调用移动到Activity,此代码可以正常工作。有关为什么它不能在LearningView类内部工作的任何提示?我已经尝试在com.example.LearningView标记内移动TextView但没有快乐。我更喜欢从SurfaceView子类中获取TextView,因为我认为将电视视为SV的“孩子”更合乎逻辑。

这是我写的一个人为的例子,用来在更大的应用程序中找出问题,但它的要点是相同的,堆栈跟踪基本相同。

对于它的价值,findViewById调用返回null,这显然在一些尝试中修复了NullPointerExceptions。

正如你可能从我的尝试中收集到的那样,我对这一次失明了。

Learning.java:

package com.example.Learning;

import android.app.Activity;
import android.os.Bundle;

public class Learning extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

LearningView.java:

package com.example.Learning;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;

public class LearningView extends SurfaceView implements SurfaceHolder.Callback {
    public LearningView(Context context, AttributeSet atts) {
        super(context, atts);
        getHolder().addCallback(this);      
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        TextView t = (TextView) findViewById(R.id.contents);
        t.setText("testing");
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    }
}

main.xml中:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <com.example.Learning.LearningView
        android:id="@+id/learningview" android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
    <TextView android:id="@+id/contents" android:layout_gravity="bottom|left"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:textColor="#ffffffff" />
</FrameLayout>

堆栈追踪:

Thread [<3> main] (Suspended (exception RuntimeException))  
    ActivityThread.performLaunchActivity(ActivityThread$ActivityRecord, Intent) line: 2454  
    ActivityThread.handleLaunchActivity(ActivityThread$ActivityRecord, Intent) line: 2470   
    ActivityThread.access$2200(ActivityThread, ActivityThread$ActivityRecord, Intent) line: 119 
    ActivityThread$H.handleMessage(Message) line: 1821  
    ActivityThread$H(Handler).dispatchMessage(Message) line: 99 
    Looper.loop() line: 123 
    ActivityThread.main(String[]) line: 4310    
    Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]  
    Method.invoke(Object, Object...) line: 521  
    ZygoteInit$MethodAndArgsCaller.run() line: 860  
    ZygoteInit.main(String[]) line: 618 
    NativeStart.main(String[]) line: not available [native method]  

3 个答案:

答案 0 :(得分:2)

您正在崩溃,因为TextViewfindViewById()为空。 TextView不是SurfaceView的孩子,因此以findViewById()为起点调用SurfaceView将无法找到它。

答案 1 :(得分:2)

您可以将上下文强制转换为活动,并按如下方式查找视图:

(TextView)((Activity)context).findViewById(R.id.contents);

现在它不会为空。

答案 2 :(得分:1)

我遇到了同样的问题,Loke提供的答案解决了我的问题。我不知道铸造是否是一个很好的干净方式来为Android sdk编程。这是我的代码最终结果:

我的活动有:

setContentView(R.layout.game);

我的game.xml:

<TextView  
    android:text="@string/text_foul_counter_1"  
    android:layout_height="wrap_content"  
    android:background="#fff"  
    android:gravity="center"  
    android:textColor="#000"  
    android:id="@+id/TextViewFoulCounter1"  
    android:layout_width="wrap_content"  
    android:layout_below="@+id/TextViewFoul1" 
    android:padding="2dp"></TextView>

从我的班级中调用finViewById:     public class PlayerView extends Activity实现OnClickListener,OnLongClickListener {...}

没有强制转换我曾经得到一个空指针异常。下面是现在有效的代码行。

foulsTextViewTeam1 = (TextView) ((Activity) context).findViewById(R.id.TextViewFoulCounter1);