【问题标题】:Got NullPointerException from Thread从线程得到 NullPointerException
【发布时间】:2012-12-20 14:28:26
【问题描述】:

我正在编写一个小安卓游戏。它应该显示我作为 ImageButtons 实现的 4 只动物的随机序列。用户必须记住这个序列并在之后重复它。

我现在的问题是图像按钮显示的正确时机。

我得到以下 NullPointerException 并且不知道为什么。也许有人可以帮忙!?

这是我的主要活动:

package lichtenberger.paul;

import java.util.Random;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageButton;
import android.widget.TextView;

public class Game extends Activity {

    int Reihenfolge[] = new int[40];

    Random generator = new Random();


    public final int CAT = 0;
    public final int MAN = 1;
    public final int BIRD = 2;
    public final int SHEEP = 3;
    public Handler handler;
    public Thread AnimalThread;
    {for(int i = 0; i<40; i++)Reihenfolge[i]=generator.nextInt(4);}


    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game);

        final ImageButton cat = (ImageButton)findViewById(R.id.catButton);
        final ImageButton sheep = (ImageButton)findViewById(R.id.sheepButton);
        final ImageButton man = (ImageButton)findViewById(R.id.manButton);
        final ImageButton bird = (ImageButton)findViewById(R.id.birdButton);
        final TextView score = (TextView)findViewById(R.id.scoreNTV);

        handler = new Handler(){

            @Override

            public void handleMessage(Message msg){

                switch (msg.what) {
                case 0:
                    cat.setVisibility(1);
                    man.setVisibility(0);
                    bird.setVisibility(0);
                    sheep.setVisibility(0);
                    break;
                case 1:
                    man.setVisibility(1);
                    bird.setVisibility(0);
                    sheep.setVisibility(0);
                    cat.setVisibility(0);
                    break;
                case 2:
                    bird.setVisibility(1);
                    sheep.setVisibility(0);
                    cat.setVisibility(0);
                    man.setVisibility(0);
                    break;
                case 3:
                    sheep.setVisibility(1);
                    cat.setVisibility(0);
                    man.setVisibility(0);
                    bird.setVisibility(0);
                    break;
                }

            }
        };          
            ShowSequence show = new ShowSequence();
            Thread showSeq = new Thread(show);
            showSeq.start();

        };

}

我的线程类:

package lichtenberger.paul;   

public class ShowSequence extends Game implements Runnable{    
    @Override
    public void run() {                 
        show();
    }

    private void show() {

        for(int i = 0; i<40; i++){
        switch (Reihenfolge[i]) {
        case 0:
                try {
                // this pauses the Thread: Alternative to doing stuff...
                Thread.sleep(2000);

                handler.sendEmptyMessage(CAT);
                } catch (InterruptedException e) {
                e.printStackTrace();}
                break;

        case 1:
            try {
                // this pauses the Thread: Alternative to doing stuff...
                Thread.sleep(2000);

                handler.sendEmptyMessage(MAN);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            break;

        case 2:
            try {
                // this pauses the Thread: Alternative to doing stuff...
                Thread.sleep(2000);

                handler.sendEmptyMessage(BIRD);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            break;

        case 3: 
            try {
                // this pauses the Thread: Alternative to doing stuff...
                Thread.sleep(2000);

                handler.sendEmptyMessage(SHEEP);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        default:
            break;
        }
    }
}}

还有我的 LogCat:

12-20 15:20:34.974: ERROR/AndroidRuntime(598): FATAL EXCEPTION: Thread-75
12-20 15:20:34.974: ERROR/AndroidRuntime(598): java.lang.NullPointerException
12-20 15:20:34.974: ERROR/AndroidRuntime(598):     at lichtenberger.paul.ShowSequence.show(ShowSequence.java:50)
12-20 15:20:34.974: ERROR/AndroidRuntime(598):     at lichtenberger.paul.ShowSequence.run(ShowSequence.java:10)
12-20 15:20:34.974: ERROR/AndroidRuntime(598):     at java.lang.Thread.run(Thread.java:856)

编辑:

一个 Activity 中的全部代码不起作用:

package lichtenberger.paul;

import java.util.Random;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageButton;
import android.widget.TextView;

public class Game extends Activity {

    int Reihenfolge[] = new int[40];

    Random generator = new Random();
    public ImageButton cat;
    public ImageButton man;
    public ImageButton bird;
    public ImageButton sheep;
    public TextView score;
    private static Handler handler;
    public final int CAT = 0;
    public final int MAN = 1;
    public final int BIRD = 2;
    public final int SHEEP = 3;
    public Runnable showAnimal;
    public Thread AnimalThread;
    {for(int i = 0; i<40; i++)Reihenfolge[i]=generator.nextInt(4);}


    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game);

        setupUI();
        showSequence();
        initHandler();
    }



    public void showSequence() {

                showAnimal = new showAnimal();
                AnimalThread = new Thread(showAnimal);
                AnimalThread.start();


    }



    public void setupUI() {

        cat = (ImageButton)findViewById(R.id.catButton);
        sheep = (ImageButton)findViewById(R.id.sheepButton);
        man = (ImageButton)findViewById(R.id.manButton);
        bird = (ImageButton)findViewById(R.id.birdButton);
        score = (TextView)findViewById(R.id.scoreNTV);

    }

    private void initHandler() {
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case CAT:
                    cat.setVisibility(1);
                    man.setVisibility(0);
                    bird.setVisibility(0);
                    sheep.setVisibility(0);
                    break;
                case MAN:
                    man.setVisibility(1);
                    bird.setVisibility(0);
                    sheep.setVisibility(0);
                    cat.setVisibility(0);
                    break;
                case BIRD:
                    bird.setVisibility(1);
                    sheep.setVisibility(0);
                    cat.setVisibility(0);
                    man.setVisibility(0);
                    break;
                case SHEEP:
                    sheep.setVisibility(1);
                    cat.setVisibility(0);
                    man.setVisibility(0);
                    bird.setVisibility(0);
                    break;
                }
            }
        };

    }

    class showAnimal implements Runnable {
        public void run() {
            show();
        }

        private void show() {

            for(int i = 0;i<40;i++){

            switch (Reihenfolge[i]) {

            case 0:
                try {
                    // this pauses the Thread: Alternative to doing stuff...
                    Thread.sleep(2000);

                    handler.sendEmptyMessage(CAT);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                break;

            case 1:
                try {
                    // this pauses the Thread: Alternative to doing stuff...
                    Thread.sleep(2000);

                    handler.sendEmptyMessage(MAN);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                break;

            case 2:
                try {
                    // this pauses the Thread: Alternative to doing stuff...
                    Thread.sleep(2000);

                    handler.sendEmptyMessage(SHEEP);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                break;
            case 3:
                try {
                    // this pauses the Thread: Alternative to doing stuff...
                    Thread.sleep(2000);

                    handler.sendEmptyMessage(BIRD);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                break;
            }
        }
    }



}
}

感谢您的帮助;)

【问题讨论】:

  • ShowSequence 类的第 50 行是什么?
  • 错误总是出现在向处理程序发送消息的行上。在这种情况下,它是: handler.sendEmptyMessage(BIRD);
  • 您的类层次结构有些奇怪。在Game.onCreate 中,你实例化了new ShowSequence,它扩展了Game,尽管创建了新的Activity(它永远不会得到它的onCreate,顺便说一句)。也许你应该把你的Runnable写成Game里面的私有类?
  • 对,如果您在此方法“public void handleMessage(Message msg) {...}”中打印 msg 变量会得到什么?
  • 我已经尝试将所有内容放入游戏活动中,但对我来说没有效果。它一次显示所有 4 张图片,而不是暂停线程 2 秒钟然后显示新图片。我像以前一样添加了整个班级的代码。也许有人有解决这个问题的想法。

标签: android multithreading nullpointerexception


【解决方案1】:

问题是您有 2 个单独的对象 - Game 的实例具有非空处理程序。以及带有 null 处理程序的 ShowSequence 实例。你不应该从Game 继承ShowSequecne。它不会自动获取所有Game 的变量,您应该按照@harism 的建议在Game 中创建ShowSequence 内部类。 或者您必须在构造函数中或在创建后立即设置 ShowSequence 中的所有变量。

【讨论】:

  • 我已经尝试将其作为游戏中的内部类。但它一次显示所有 4 张图像,而不是按顺序显示,中间有 2 秒延迟:/
  • @PaulLich 你可以完全避免线程。在处理程序的handleMessage 方法中使用sendEmptyMessageDelayed 以2000 延迟向自身发送空消息。
  • 好的,谢谢。 sendEmptyMessageDelayed 工作。但实际的问题是我在调试时发现的另一个问题。所有图片同时出现的原因是在很短的时间内启动线程。我通过在 showSequence 方法的每个循环之后更改延迟时间来解决这个问题。我在我的问题下方发布我的解决方案。
【解决方案2】:

保罗,

您是否尝试过使“处理程序”变量volatile?您可以从工作线程(即运行“ShowSequence”可运行对象)访问此变量,而无需使用同步(synchronized 关键字)。尽管您甚至可能想考虑添加某种形式的同步(我没有仔细阅读您的代码来做出决定),但您至少应该确保从一个线程对“处理程序”的写入对其他线程是可见的。 volatile 限定符是实现此目的的一种方式。

祝你好运!

PS:ShowSequence 扩展了游戏?哪个又扩展了Activity?我认为您还需要检查此继承树..不确定您是否想要这个..

【讨论】:

    【解决方案3】:

    我不会从游戏中插入 ShowSequence,您可以将处理程序作为参数传递

    //活动

    ShowSequence show = new ShowSequence(handler);
                Thread showSeq = new Thread(show);
                showSeq.start();
    

    // 线程类

    public class ShowSequence implements Runnable{
    Handler handler = null;
    
    public ShowSequence(handler){
          this.handler = handler;
    }
    

    【讨论】:

      【解决方案4】:

      实际问题是我在调试时发现的另一个问题。所有图片同时出现的原因是在很短的时间内启动线程。我通过在 showSequence 方法的每个循环之后更改延迟时间来解决这个问题。

      现在这是我的完整课程:

      package lichtenberger.paul;
      
      import java.util.Random;
      
      import android.app.Activity;
      import android.os.Bundle;
      import android.os.Handler;
      import android.os.Message;
      import android.view.View;
      import android.widget.ImageButton;
      import android.widget.TextView;
      
      public class Game extends Activity {
      
          int Reihenfolge[] = new int[40];
      
          Random generator = new Random();
      
      
          public final int CAT = 0;
          public final int MAN = 1;
          public final int BIRD = 2;
          public final int SHEEP = 3;
          public final int PAUSE = 4;
          public final int ALL = 5;
          public int Zug = 40;
          public int time = 0;
          public Handler handler;
          public Thread AnimalThread;
          public ImageButton cat;
          public ImageButton man;
          public ImageButton bird;
          public ImageButton sheep;
      
          {for(int i = 0; i<40; i++)Reihenfolge[i]=generator.nextInt(4);}
      
      
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_game);
      
              cat = (ImageButton)findViewById(R.id.catButton);
              sheep = (ImageButton)findViewById(R.id.sheepButton);
              man = (ImageButton)findViewById(R.id.manButton);
              bird = (ImageButton)findViewById(R.id.birdButton);
              final TextView score = (TextView)findViewById(R.id.scoreNTV);
      
              handler = new Handler(){
      
                  @Override
      
                  public void handleMessage(Message msg){
      
                      switch (msg.what) {
                      case CAT:
                          cat.setVisibility(View.VISIBLE);
                          man.setVisibility(View.INVISIBLE);
                          bird.setVisibility(View.INVISIBLE);
                          sheep.setVisibility(View.INVISIBLE);
      
                          break;
                      case MAN:
                          man.setVisibility(View.VISIBLE);
                          bird.setVisibility(View.INVISIBLE);
                          sheep.setVisibility(View.INVISIBLE);
                          cat.setVisibility(View.INVISIBLE);
      
                          break;
                      case BIRD:
                          bird.setVisibility(View.VISIBLE);
                          sheep.setVisibility(View.INVISIBLE);
                          cat.setVisibility(View.INVISIBLE);
                          man.setVisibility(View.INVISIBLE);
      
                          break;
                      case SHEEP:
                          sheep.setVisibility(View.VISIBLE);
                          cat.setVisibility(View.INVISIBLE);
                          man.setVisibility(View.INVISIBLE);
                          bird.setVisibility(View.INVISIBLE);
      
                          break;
      
                      case PAUSE:
                          sheep.setVisibility(View.INVISIBLE);
                          cat.setVisibility(View.INVISIBLE);
                          man.setVisibility(View.INVISIBLE);
                          bird.setVisibility(View.INVISIBLE);
      
                      case ALL:
                          sheep.setVisibility(View.VISIBLE);
                          cat.setVisibility(View.VISIBLE);
                          man.setVisibility(View.VISIBLE);
                          bird.setVisibility(View.VISIBLE);
                       }
      
                  }
              };
      
              time = 0;
              Zug = 40;
              showGameSeq(time, Zug); 
              }
      
      
      
          public int showGameSeq(int time, int Zug) {
              ShowSequence show;
              Thread showSeq;
              int x = 0;
      
              for(int i = 1; i<=Zug; ++i, ++x){
      
                      if(Reihenfolge[i-1]!=Reihenfolge[i-1]){
      
                          show = new ShowSequence(Reihenfolge[i-1], time);
                          showSeq = new Thread(show);
                          showSeq.start();
                          time = time + 1000;}
      
                      else{
                          show = new ShowSequence(Reihenfolge[i-1], time);
                          showSeq = new Thread(show);
                          showSeq.start();
                          time = time + 1000;
      
                          show = new ShowSequence(PAUSE, time);
                          showSeq = new Thread(show);
                          showSeq.start();
                          time = time + 500;
      
                      }
                  }
      
      
              if(x==Zug){ 
              show = new ShowSequence(ALL, time);
              showSeq = new Thread(show);
              showSeq.start();
              }else{};
      
      
              return time;
          };
      
      
      
          private class ShowSequence implements Runnable{
      
              int which;
              int time;
      
              public ShowSequence(int which, int time) {
                  this.which = which;
                  this.time = time;
              }
      
              @Override
              public void run() {
      
                  show();
      
              }
      
              private void show() {
      
                      switch (which) {
                      case CAT:
      
                          handler.sendEmptyMessageDelayed(CAT, time);
                          break;
                      case MAN:
      
                          handler.sendEmptyMessageDelayed(MAN, time);
                          break;
                      case BIRD:
      
                          handler.sendEmptyMessageDelayed(BIRD, time);
                          break;
                      case SHEEP:
      
                          handler.sendEmptyMessageDelayed(SHEEP, time);
                          break;
      
                      case PAUSE:
      
                          handler.sendEmptyMessageDelayed(PAUSE, time);
                          break;
      
                      case ALL:
      
                          handler.sendEmptyMessageDelayed(ALL, time);
                          break;
      
                      }
              }
              }
              }
      

      感谢所有启发我解决方案的人!!! :)

      【讨论】:

        猜你喜欢
        • 2014-01-29
        • 2023-03-22
        • 1970-01-01
        • 2015-01-09
        • 1970-01-01
        • 2015-06-24
        • 2016-05-31
        • 2012-04-14
        • 1970-01-01
        相关资源
        最近更新 更多