Was bedeutet diese Errormeldung: Uncaught handler: thread Thread-8 exiting due to uncaught exception?

  • Antworten:5
  • Bentwortet
Arni Antal
  • Forum-Beiträge: 5

09.02.2015, 12:26:09 via Website

Hallo ich bin gerade dabei ein kleines Spiel für Android zu programmieren, dieses habe ich schon mal für Windows in Delphi programmiert. Allerdings habe ich sehr damit zu kämpfen das einige Sachen in Java sehr umständlich gelöst sind(zumindest aus meiner Sicht). Ich habe versucht einen Timer zu programmieren der in einem bestimmten Intervall das View neuzeichnet. Das glabt etwa 4-5 mal dann bricht das Programm ab.
Das ist der Abschnitt aus logcat:

02-09 11:13:06.005      849-855/com.arni.aspirin E/AndroidRuntime﹕ Uncaught handler: thread Thread-8 exiting due to uncaught exception
02-09 11:13:06.015      849-855/com.arni.aspirin E/AndroidRuntime﹕ android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
            at android.view.ViewRoot.checkThread(ViewRoot.java:2683)
            at android.view.ViewRoot.invalidateChild(ViewRoot.java:570)
            at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:596)
            at android.view.ViewGroup.invalidateChild(ViewGroup.java:2396)
            at android.view.View.invalidate(View.java:4945)
            at com.arni.aspirin.Hauptfenster$1.run(Hauptfenster.java:74)
            at java.lang.Thread.run(Thread.java:1096)
02-09 11:13:06.075      849-851/com.arni.aspirin I/dalvikvm﹕ threadid=7: reacting to signal 3
02-09 11:13:06.075      849-851/com.arni.aspirin E/dalvikvm﹕ Unable to open stack trace file '/data/anr/traces.txt': Permission denied
02-09 11:13:21.865      849-855/com.arni.aspirin I/Process﹕ Sending signal. PID: 849 SIG: 9

Ich habe jetzt schon ein paar mal versucht den Fehler im Debugger nach zuvollziehen konnte den Punkt aber nicht genau finden. Es muß irgentwo in der invalidate(); methode sein. Deshalb habe ich vermutet das es der Fehler in der Paint methode liegt und habe einen try catch block reingebaut allerdings kommt er nicht einmal so weit.
Mein Quellcode:
Klasse Hauptfenster:

  package com.arni.aspirin;

import android.app.Activity;
import android.graphics.Point;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.Menu;
import android.view.MenuItem;

import java.util.ArrayList;


public class Hauptfenster extends Activity {
    ArrayList<Punkt> Gegner;
    Spielfeld feld;
    Boolean TimerEnabeld = false;
    Boolean Timeractive = false;
    long TimerInterval=100;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DisplayMetrics metrics=new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        feld = new Spielfeld(Hauptfenster.this,metrics.heightPixels,metrics.widthPixels);
        setContentView(feld);
        Gegner = new ArrayList<Punkt>();
        Gegner.add(new Punkt(1));
        Gegner.add(new Punkt(2));
        Timeractive = true;
        TimerEnabeld = true;
        TimerInterval = 1000;
        Timer();
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_hauptfenster, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public void Timer(){
        new  Thread(new Runnable() {
            @Override
            public void run() {
                while (TimerEnabeld){
                    Point[] x = new Point[Gegner.size()];
                    int a = 0;
                    for (Punkt i: Gegner){
                        i.Bewegen();
                        x[a] = new Point(i.getPosition());
                        a++;
                        }
                        feld.getGegner(x);
                        feld.invalidate();


                        try {
                            Thread.sleep(TimerInterval);
                        } catch (InterruptedException e) {

                        }
                    }
                }

        }).start();
    }
}

Klasse Spielfeld:

package com.arni.aspirin;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.Toast;


import java.util.ArrayList;

/**
 * Created by Arni on 04.02.2015.
 */
public class Spielfeld extends View{
    Paint paint;
    int height;
    int width;
    Point[] Gegner;
    Boolean zeichneGegner = false;

    public Spielfeld(Context context, int Height, int Width){
        super(context);
        paint = new Paint();
        this.height = Height;
        this.width = Width;


        paint.setColor(Color.WHITE);
        zeichneGegner = false;
    }

  @Override
  protected void onDraw(Canvas canvas){
      try {
      super.onDraw(canvas);
     paint.setColor(Color.WHITE);
      canvas.drawRect(0,0,width,height,paint);
      invalidate();



      if (zeichneGegner){
          for (int i = 0; i<Gegner.length;i++){
             paint.setColor(Color.RED);
              canvas.drawCircle(Gegner[i].x*(width/20),Gegner[i].y*(height/40),width/20,paint);
              invalidate();
          }
      }} catch (Exception e){
         Context context = getContext();
          Toast toast = Toast.makeText(context,e.getMessage().toString(),Toast.LENGTH_LONG);
          toast.show();
      }

  }

    public void getGegner(Point[] x){
        this.Gegner = x;
        zeichneGegner = true;

    }


}

Gruß Arni

Antworten
Sven R.
  • Forum-Beiträge: 1.904

09.02.2015, 15:07:09 via App

Mit ondraw habe ich mich noch nie beschäftigt, allerdings weiß ich, dass invalidate() onDraw im Endeffekt aufruft. Also ruft sich onDraw selber auf. Das darf nicht sein.

Wenn dir mein Beitrag gefällt, kannst dich einfach mit dem 👍 "Danke"-Button auf der Website dieses Forums bedanken. 😀

Why Java? - Because I can't C#

Antworten
Arni Antal
  • Forum-Beiträge: 5

09.02.2015, 17:28:39 via Website

Das habe ich aber eigentlich so aus dem Buch Java für Android(Christian Bleske). Ausserdem würde das nicht erklären warum es 4 mal klappt und beim 5 mal nicht mehr.

Antworten
Arni Antal
  • Forum-Beiträge: 5

09.02.2015, 17:40:09 via Website

Dann bricht es sofort nach dem ersten Zeichnen ab

Antworten
Sven R.
  • Forum-Beiträge: 1.904

09.02.2015, 19:42:38 via App

Okay, habe damit wie gesagt nie gearbeitet. Jedenfalls sollte sich die Methode nicht indirekt selbst aufrufen. Ich würde dann vielleicht einen Thread mit Thread.sleep(...) machen, der periodisch invalidate aufruft

Edit: Ach hast du ja schon. Keine Ahnung, vielleicht kann sich jemand anderes äußern.

— geändert am 09.02.2015, 19:45:22

Wenn dir mein Beitrag gefällt, kannst dich einfach mit dem 👍 "Danke"-Button auf der Website dieses Forums bedanken. 😀

Why Java? - Because I can't C#

Arni Antal

Antworten