【问题标题】:findViewById() in extends subclass [closed]扩展子类中的 findViewById() [关闭]
【发布时间】:2012-10-10 15:52:19
【问题描述】:

我有两个类:

public class Game extends Activity

public class CoreGame extends Game

CoreGame 类中我有:

public void init(){
    layout = (RelativeLayout)findViewById(R.id.rlayout);
}

执行在layout = (RelativeLayout)findViewById(R.id.rlayout); CoreGame 类行返回NullPointerException

为什么?

OnCreate :

   @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.game);

        core = new CoreGame(this);
        core.runCoreGame();

    }

Core.runCoreGame():

public void runCoreGame(){
    init();
}

public void init(){
    layout = (RelativeLayout)findViewById(R.id.rlayout);
}

堆栈跟踪:

FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to start activity ComponentInfo{gianbalex.mgs_revenge/gianbalex.mgs_revenge.Game}: java.lang.NullPointerException
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
        at android.app.ActivityThread.access$2300(ActivityThread.java:125)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:123)
        at android.app.ActivityThread.main(ActivityThread.java:4627)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:521)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
        at dalvik.system.NativeStart.main(Native Method)
    Caused by: java.lang.NullPointerException
        at android.app.Activity.findViewById(Activity.java:1637)
        at gianbalex.mgs_revenge.CoreGame.initVariables(CoreGame.java:118)
        at gianbalex.mgs_revenge.CoreGame.runCoreGame(CoreGame.java:84)
        at gianbalex.mgs_revenge.Game.onCreate(Game.java:28)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)

【问题讨论】:

  • 你从哪里调用 init()?
  • 发布您的堆栈跟踪 (logcat)
  • 这里的信息很少,所以几乎不可能提供帮助。你能告诉我们剩下的代码吗?
  • 所以我们可以看到问题所在。此外,使用 cmets 进行响应。如果您编辑帖子以获取回复,我们将永远看不到它们。
  • 你是从构造函数调用 init() 吗?如果是这样,您需要将其移至onCreate()

标签: java android class android-view


【解决方案1】:

好的...所以这段代码中存在不止一个问题,所以我将逐点解决它。

1.您没有以正确的方式启动 Activity

要开始CoreGame,您需要使用Intent,如下所示:

Intent intent = new Intent(getBaseContext(), CoreGame.class);
startActivity(intent);

这将运行 Activity,Android 将调用 CoreGame.onCreate()。您不需要调用构造函数等。您在构造函数中所做的任何事情都应该在 onCreate()onStart() 方法中完成。

现在你的第二个问题

2。修复 Intent 位后,您将得到 NPE

我不确定发布的onCreate() 属于哪个类,所以我将把它分为两种情况:

场景一:发布的 onCreate() 属于游戏

在这种情况下,当您将new CoreGame 行替换为Intent 启动方法时,当您尝试使用findViewById() 时,您仍然会得到NullPointerException。这是因为您只在Game 活动中调用了setContentView(),而现在您将尝试从不同的Activity 访问Views。要解决此问题,您还必须在 CoreGame 中调用 setContentView()

场景2:发布的onCreate()属于CoreGame

在这种情况下,您可以完全删除这两行:

core = new CoreGame(this);
core.runCoreGame();

相反,只需调用runCoreGame() 就足够了

【讨论】:

  • 哇...谢谢您的回复!我试试这个,一会儿:)
【解决方案2】:

使用这个,这是初始化和创建对象的正确方法。

 RelativeLayout layout = (RelativeLayout) findViewById(R.id.rlayout);

【讨论】:

  • 虽然正确,但它并没有解决 NPE。
【解决方案3】:

如果我错了,请纠正我,但看起来你正试图这样做

  1. 声明一个变量,但类型周围有 ()。这应该会在编译时给您一条错误消息。

  2. 使用强制转换来获取变量的属性,它可能没有。 layout实际上是RelativeLayout对象吗?

我的钱在第二个选项上。如果对象不属于正确的类,您将得到一个异常,这就是强制转换听起来正确的原因。这是我在学习 Java 和 Objective-C 时的一个简单想法:“如果它不是正确的类型,我可以将其转换为 make 正确的类型”。简单地说,没有。您似乎在这里做的是尝试从不具有该属性的东西中获取/设置属性,因此该函数返回nilnull。在 Java 中,如果我没记错的话,将不惜一切代价避免这些。

您可以通过像这样声明 layout 来解决此问题:

RelativeLayout layout = (RelativeLayout) findViewById(R.id.rlayout);

这使它成为正确的类型,因此它可以正确接收任何和所有信息。现在,我是 Java 和 Android SDK 的新手,但我仍然有一个建议:在尝试使用 Java 构建真正的应用程序之前,先尝试学习 Java 并熟悉它。不幸的是,您显然并不完全熟悉该语言及其特性。如果我错了,那可能是因为我很困惑。您确实应该发布显示layout 声明的代码,以便我们可以看到那里的任何潜在问题。

编辑:正如 AedonEtLIRA 在对您的评论中所说,无论如何您都应该在其他地方这样做。除非你真的知道确切你在做什么,否则将这种代码放入构造函数是非常危险的。即使应用程序之后看起来很好,这种事情也会导致它运行得更慢并且更不稳定。其他代码可能会导致它无缘无故地崩溃。这是因为它可以在应用程序中创建僵尸和“死内存”,当其他活动需要内存时,这可能会导致问题。

【讨论】:

  • 为什么投反对票?我搞砸了什么?
  • 如果布局不是RelativeLayout 或从那里派生的类,则异常是ClassCastException。引用的行与“获得财产”无关。看起来您在猜测代表点数,这可能就是投反对票的原因。
  • @Simon 只是为了澄清一下,我 am 猜测,但不是为了代表。猜测是基于我不了解 Android SDK 的事实,但我确实对 Java 有所了解,而且我自己也犯过类似的错误。但是,您对ClassCastExecption 的看法是正确的,我承认我错了。不管怎样,我希望我的一些观点是正确和有用的。
猜你喜欢
  • 2012-01-09
  • 2011-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-19
  • 1970-01-01
  • 1970-01-01
  • 2013-04-02
相关资源
最近更新 更多