-1

Ich versuche, ein ImageView zu verschieben, während der Benutzer den Bildschirm berührt. Ich habe ursprünglich eine while-Schleife von einer onTouchEvent-Methode ausprobiert, aber dies hat einige Hintergrundprozesse gestoppt, die ich brauchte. Ich habe jetzt einen Thread, den ich benutze, um mein Spiel zu steuern, was einen Aufruf beinhaltet, um die Position meines ImageView zu aktualisieren, basierend auf einem Float namens 'movementSpeed', der durch Bewegungsereignisse bestimmt wird. Das Problem, glaube ich, liegt in der Initialisierung meines ImageView, aber ich habe viele Lösungen aus anderen Fragen versucht, die für mich nicht zu funktionieren scheinen. Ich überlegte, ob dies wäre, weil ich die Methode von einem Thread anrief und versuchte, die Methode auf dem UI-Thread auszuführen, aber es funktionierte immer noch nicht. Ich habe jedoch festgestellt, dass die Position aktualisiert wird, wenn ich updateCharPos von meiner Berührungsereignismethode aus aufrufe, obwohl dies die oben erwähnte Schwierigkeit bei der Ausführung anderer Aufgaben verursachen würde.ImageView nullPointerException

Aktivität Java:

package fozard.backuptestapp; 


public class Play extends AppCompatActivity { 

private GameThread thread; 
private float charX=0; 
ImageView character; 


@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_play); 
    character = (ImageView) findViewById(R.id.character); 
} 

@Override 
protected void onStart(){ 
    super.onStart(); 
    thread=new GameThread(); 
    thread.setRunning(true); 
    thread.start(); 
} 

public boolean onTouchEvent(MotionEvent event){ 
    switch (event.getAction()){ 
     case MotionEvent.ACTION_DOWN: 
      thread.setMovementSpeed(5); 
      thread.setMoving(true); 
      break; 
     case MotionEvent.ACTION_UP: 
      thread.setMoving(false); 
    } 
    return true; 
} 

public void updateCharPos(float movementSpeed){ 
    Log.d("Updating", "Should be able to update"); 
    charX = character.getX(); 
    System.out.print(charX); 
} 
} 

Thema Code:

public class GameThread extends Thread { 

public static final int maxFps=30; 
private double averageFps; 
private boolean isRunning; 
private int score=0; 
private Play play = new Play(); 
private boolean isMoving; 
private float movementSpeed=0; 


public void setMovementSpeed(float movementSpeed){ 
    this.movementSpeed = movementSpeed; 
} 

public void setMoving(Boolean isMoving){ 
    this.isMoving = isMoving; 
} 

public void setRunning(Boolean isRunning){ 
    this.isRunning = isRunning; 
} 


@Override 
public void run(){ 
    long startTime; 
    long timeMillis; 
    long waitTime; 
    int frameCount=0; 
    long totalTime=0; 
    long targetTime= 1000/maxFps; 

    while (isRunning){ 
     startTime = System.nanoTime(); 

     timeMillis = (System.nanoTime()-startTime)/1000000; 
     waitTime = targetTime-timeMillis; 
     try{ 
      if (waitTime>0){ 
       currentThread().sleep(waitTime); 
      } 
     }catch (Exception e){ 

     } 
     totalTime += System.nanoTime() - startTime; 
     frameCount++; 
     score=score+1; 
     if (isMoving){ 
       try{ 
        update(); 
       }catch (Exception e){ 
        e.fillInStackTrace(); 
       } 
     } 

     if (frameCount==maxFps){ 
      averageFps=1000/((totalTime/frameCount)/1000000); 
      frameCount=0; 
      totalTime=0; 
      System.out.println(averageFps); 
     } 
    } 
} 

public void update(){ 
    play.runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 
      play.updateCharPos(movementSpeed); 
     } 
    }); 

    } 
} 

und mein Stack-Trace:

11-23 19:46:51.715 27465-27504/fozard.backuptestapp I/System.out: 30.0 
11-23 19:46:52.710 27465-27504/fozard.backuptestapp I/System.out: 30.0 
11-23 19:46:53.705 27465-27504/fozard.backuptestapp I/System.out: 30.0 
11-23 19:46:54.105 27465-27465/fozard.backuptestapp D/Updating: Should be able to update 
11-23 19:46:54.105 27465-27465/fozard.backuptestapp D/AndroidRuntime: Shutting down VM 
11-23 19:46:54.105 27465-27465/fozard.backuptestapp W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x41d29700) 
11-23 19:46:54.125 27465-27465/fozard.backuptestapp E/AndroidRuntime: FATAL EXCEPTION: main 
                     java.lang.NullPointerException 
                     at android.app.Activity.findViewById(Activity.java:1914) 
                     at fozard.backuptestapp.Play.updateCharPos(Play.java:55) 
                     at fozard.backuptestapp.GameThread$1.run(GameThread.java:88) 
                     at android.os.Handler.handleCallback(Handler.java:730) 
                     at android.os.Handler.dispatchMessage(Handler.java:92) 
                     at android.os.Looper.loop(Looper.java:176) 
                     at android.app.ActivityThread.main(ActivityThread.java:5419) 
                     at java.lang.reflect.Method.invokeNative(Native Method) 
                     at java.lang.reflect.Method.invoke(Method.java:525) 
                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046) 
                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862) 
                     at dalvik.system.NativeStart.main(Native Method) 
11-23 19:46:54.840 27465-27504/fozard.backuptestapp I/System.out: 30.0 
11-23 19:46:55.835 27465-27504/fozard.backuptestapp I/System.out: 30.0 

jede mögliche Hilfe würde geschätzt!

Xml:

ImageView 
    android:layout_width="100dp" 
    android:layout_height="100dp" 
    android:layout_alignParentBottom="true" 
    android:layout_centerHorizontal="true" 
    android:src="@drawable/character" 
    android:id="@+id/character" 
    android:scaleType="fitCenter" 
    android:clickable="false" 
    android:longClickable="false"/
+0

Sind ersetzen Sie sicher R.id.character ist mit einem Image zeigen? Kannst du dein activity_play Layout posten? – mWhitley

+0

@mWhitley. von meinem activity_play Layout: Ich glaube, das ist richtig? Wenn ich die updateCharPos() - Methode von der onTouchEvent-Methode aus aufrufen, wird die Position aktualisiert, aber es wird ein Problem mit anderen Aufgaben verursacht (oben). – BFozard

+0

@BFozard können Sie Ihren Layout-Code (XML) posten? – HenriqueMS

Antwort

0

EDIT:

ich nicht bemerkt hatte, aber ich mag @ njzk2 schrieb in den Kommentaren sind Sie manuell eine Klasse instanziieren, die Activity erstreckt, die das seltsame Verhalten erklärt Ich sprach über

private Play play = new Play(); 

Activity ‚s Unterklassen sollten nicht direkt instanziiert werden, rechts here ist ein gutes Tutorial in diesem.

Wenn Sie diese von innen Aktivität tun Sie können:

Intent intent = new Intent(this, NAME_OF_NEW_ACTIVITY.class); 
    startActivity(intent); 

Ihre tatsächliche Anruffluss geht so:

Play (Activity) -> new GameThread() -> new Play() (Activity) -> new GameThread() 

Es ist wahrscheinlich nicht das, was Sie mit der rechten wollen?

Außerdem, wenn Sie eine Aktion von einem anderen Thread beginnen, benötigen Sie einen Kontext haben, damit Sie die neue Aktivität starten können

Intent myIntent = new Intent(mContext, Play.class); 

mContext.startActivity(myIntent); 

Die Tatsache, dass Sie die NPE werden immer direkt in der findViewById() Anruf macht mich denken, dass Sie die Aktivität noch nicht vollständig erstellt haben, die seltsam ist.

Für weitere Debugging können Sie

character = (ImageView) findViewById(R.id.character); 

für

LayoutInflater mInflater; 
    mInflater = LayoutInflater.from(this); 

    //breakpoint here, check if you have the mInflater 
    View layoutView = mInflater.inflate(R.layout.activity_play, null); 

    //breakpoint here, check if you have the layoutView 
    ImageView character = (ImageView) layoutView.findViewById(R.id.character); 

    //if you get here you should be in the clear 
    setContentView(layoutView); 
+0

Vielen Dank für Ihre Hilfe! Sie und @ njzk2 hatten Recht damit, dass eine neue Instanz der Aktivität erstellt wurde. Am Ende habe ich 'öffentliches statisches Play Play' innerhalb der Aktivität verwendet und 'play = this;' innerhalb onCreate(). Dies ermöglichte mir, auf die vorhandene Instanz der Aktivität aus dem Thread mit "Play.play.updateCharPos (movementSpeed)" zu verweisen. und es funktioniert jetzt perfekt! Danke nochmal für die Hilfe! – BFozard

+0

@BFozard seien Sie vorsichtig mit dieser Idea, indem Sie die statische Referenz auf die Aktivität beibehalten. Es besteht eine hohe Wahrscheinlichkeit, dass Sie verhindern, dass der Müll gesammelt wird und daher Speicher verloren geht. Ich würde dir empfehlen, Aktivitäten nach Android-Mustern zu verwenden. Ich bin froh, dass ich helfen konnte Prost;) – HenriqueMS

0

Unter der Annahme, dass R.id.character tatsächlich eine gültige Sicht verweist, können Sie die Hintergrund-Thread Initialisierung thread=new GameThread(); entweder die onStart() oder onResume() Funktion zu gewährleisten bewegen, dass die erforderlichen UI-Komponenten tatsächlich vorhanden sind.

Weitere Informationen zum Android-Lebenszyklus finden Sie unter this SO post.

+0

Danke für den Vorschlag @Boo. Ich habe überprüft, dass R.id.character eine gültige Ansicht referenziert und die folgende Änderung versucht: '@Override' protected void onStart() { super.onStart(); thread = neu GameThread(); thread.setRunning (true); thread.start(); }, aber das Problem tritt immer noch auf. Der seltsame Teil ist, dass, wenn ich das updateCharPos vom Touch-Ereignis anrufe, es funktioniert (obwohl das das ursprüngliche Problem mit dem Anhalten anderer Prozesse verursacht) – BFozard