2017-10-22 4 views
0

Ich verstehe nicht, warum meine getActivity(), die um meinen runonUiThread herum ist, null zurückkommt. Unten ist der Code wo ich das Problem habe. Ich denke, es hat etwas damit zu tun, wo ich meine onAttach-Methode einsetze, aber ich bin mir nicht sicher. Bitte ingore alle Kommentare, da ich meinen Code säubern werde, wenn dieser Fehler behoben ist. Beachten Sie auch, dass dies der Java-Code für ein Fragment ist. Vielen Dank.Warum ist meine getActivity() in dieser Situation null?

public void onAttach(Context context){ 
      super.onAttach(context); 
      Activity a; 
      if(context instanceof Activity) 
      { 
       a=(Activity) context; 
      } 

    } 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     // Inflate the layout for this fragment 



     super.onActivityCreated(savedInstanceState); 
     //setCont(R.layout.fragment_level_one); 
     // return inflater.inflate(R.layout.fragment_level_one,container, false); 

     View view = inflater.inflate(R.layout.fragment_level_one, container, false); 

     //creating viewables and such 
     viewer = (ViewGroup) view.findViewById(R.id.view_level); 
     img = (ImageView) view.findViewById(R.id.imageView); 
     failButton = (Button) view.findViewById(R.id.failureButton); 
     countDownMain = (TextView) view.findViewById(R.id.countDownMain); 
     countDownBeginText = (TextView) view.findViewById(R.id.countDownBeginText); 
     beginButton = (Button) view.findViewById(R.id.beginButton); 

     /*if (view != null) { 
      ViewGroup parent = (ViewGroup) view.getParent(); 
      if (parent != null) { 
       parent.removeView(view); 
      } 
     } 
     try { 
      view = inflater.inflate(R.layout.fragment_level_one, container, false); 
     } catch (InflateException e) { 

     }*/ 

     RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(150, 150); 
     img.setLayoutParams(layoutParams); 
     img.setOnTouchListener(new LevelOneFragment.ChoiceTouchListener()); 

     //begin random movement 
     if(isAdded()) { 
      startRandomButton(img); 
     } 
     else 
     { 
      Log.d("line 98 is", " is null"); 
     } 

     //setting up button for failure CORRECT TO TAKE YOU TO THE MAIN MENU 
     failButton.setOnClickListener(new View.OnClickListener(){ 
      public void onClick(View v){ 
       startActivity(new Intent(getActivity(), MainMenu.class)); 
      } 
     }); 

     //setting countdown text to 3 
     countDownBeginText.setText(":3"); 

     //begin countdown from three 
     beginButton.setOnClickListener(new View.OnClickListener(){ 
      public void onClick(View beginT) { 
       CountDownTimer countDownTimer = new CountDownTimer(3*1000, 3) { 
        @Override 
        public void onTick(long millisUntilFinished) { 

         countDownBeginText.setText(":" + millisUntilFinished/1000); 
         //add possible sound here every tick 
        } 

        @Override 
        public void onFinish() { 
         beginButton.setVisibility(View.INVISIBLE); 
         countDownBeginText.setVisibility(View.INVISIBLE); 

         //countdown from 60------- change parameters in count down timer to the time desired 
         CountDownTimer countDownTimer = new CountDownTimer(60*1000, 3) { 
          @Override 
          public void onTick(long millisUntilFinishedMain) { 

           countDownMain.setText(":" + millisUntilFinishedMain/1000); 
           //add possible sound here every tick 
          } 

          @Override 
          public void onFinish() { 
           Toast.makeText(getActivity(),"You lose", Toast.LENGTH_LONG).show(); 
           //rest of text in method is trial 

           startActivity(new Intent(getActivity(), MainMenu.class)); 

          } 
         }.start(); 

        } 
       }.start(); 
      } 
     }); 
     return view; //inflater.inflate(R.layout.fragment_level_one,container, false); 
    } 
    //getting screen size 
    public static Point getDisplaySize(@NonNull Context context){ 

     Point point = new Point(); 
     WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 
     manager.getDefaultDisplay().getSize(point); 
     return point; 
    } 

    //randomly move 
    public void randomMovement(ImageView img){ 
     //int x = new Random().nextInt(getDisplaySize(getActivity()).x); 
     //int y = new Random().nextInt(getDisplaySize(getActivity()).y); 

     if(isAdded()) { 
      int x = new Random().nextInt(getDisplaySize(getActivity()).x); 
      int y = new Random().nextInt(getDisplaySize(getActivity()).y); 
      img.setY(y); 
      img.setX(x); 
     } 
     else 
      Log.d("Random mover is null", " is null"); 

    } 

    //creating timer 
    public void startRandomButton(final ImageView img){ 
     Timer timer = new Timer(); 
     timer.schedule(new TimerTask() { 
      @Override 
      public void run() { 
       if(isAdded()){ 
       getActivity().runOnUiThread(new Runnable() { //best method in the entire world-- use when trying to update ui in the background 
        @Override 
        public void run() { 
         randomMovement(img); 
        } 
       });}else{ 
        Log.d("Fragment one", "Is null");} 
      } 
     }, 0, 5000); 
    } 

Im Folgenden meine log Katze ist der Ort, wo ich, dass die Null-Referenz bin immer richtig ist in meinem startRandomButton() -Methode:

                 [ 10-22 14:34:13.423 15104:15141 D/   ] 
                     SurfaceInterface::setAsyncMode: set async mode 1 
10-22 14:34:13.429 15104-15141/name.inserttitlenameD/EGL_emulation: eglMakeCurrent: 0x9bb040c0: ver 3 0 (tinfo 0x9bb03290) 
10-22 14:34:13.448 15104-15141/name.inserttitlename D/EGL_emulation: eglMakeCurrent: 0x9bb040c0: ver 3 0 (tinfo 0x9bb03290) 
10-22 14:34:13.453 15104-15141/name.inserttitlename D/EGL_emulation: eglMakeCurrent: 0x9bb040c0: ver 3 0 (tinfo 0x9bb03290) 
10-22 14:34:13.474 15104-15141/name.inserttitlename I/chatty: uid=10083(u0_a83) RenderThread identical 2 lines 
10-22 14:34:15.124 15104-15141/name.inserttitlename D/EGL_emulation: eglMakeCurrent: 0x9bb040c0: ver 3 0 (tinfo 0x9bb03290) 
10-22 14:34:17.606 15104-15141/name.inserttitlenameD/EGL_emulation: eglMakeCurrent: 0x9bb040c0: ver 3 0 (tinfo 0x9bb03290) 
10-22 14:34:17.628 15104-15141/name.inserttitlename I/chatty: uid=10083(u0_a83) RenderThread identical 1 line 
10-22 14:34:17.638 15104-15141/name.inserttitlename D/EGL_emulation: eglMakeCurrent: 0x9bb040c0: ver 3 0 (tinfo 0x9bb03290) 
10-22 14:34:18.272 15104-15141/name.inserttitlename D/EGL_emulation: eglMakeCurrent: 0x9bb040c0: ver 3 0 (tinfo 0x9bb03290) 
10-22 14:34:18.467 15104-15141/name.inserttitlename D/EGL_emulation: eglMakeCurrent: 0x9bb040c0: ver 3 0 (tinfo 0x9bb03290) 
10-22 14:34:18.480 15104-15141/name.inserttitlename D/EGL_emulation: eglMakeCurrent: 0x9bb040c0: ver 3 0 (tinfo 0x9bb03290) 
10-22 14:34:18.487 15104-15141/name.inserttitlename D/EGL_emulation: eglMakeCurrent: 0x9bb040c0: ver 3 0 (tinfo 0x9bb03290) 
10-22 14:34:20.156 15104-16453/com.example.name.inserttitlename D/Fragment one: Is null 
10-22 14:34:25.157 15104-16453/com.example.name.inserttitlename D/Fragment one: Is null 
10-22 14:34:50.161 15104-16453/com.example.name.inserttitlename I/chatty: uid=10083(u0_a83) Timer-1 identical 5 lines 

komplette fragment.java

package com.example.name.insertitlename; 


import android.app.Activity; 
import android.content.Context; 
import android.content.Intent; 
import android.graphics.Point; 
import android.os.Bundle; 
import android.os.CountDownTimer; 
import android.support.annotation.NonNull; 
import android.support.v4.app.Fragment; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.WindowManager; 
import android.widget.Button; 
import android.widget.ImageView; 
import android.widget.RelativeLayout; 
import android.widget.TextView; 
import android.widget.Toast; 
import android.view.InflateException; 

import java.lang.ref.WeakReference; 
import java.util.Random; 
import java.util.Timer; 
import java.util.TimerTask; 
import java.util.logging.Level; 


/** 
* A simple {@link Fragment} subclass. 
*/ 
public class LevelOneFragment extends Fragment { 

    //creating variables 
    private ImageView img; 
    private ViewGroup viewer; 
    TextView textCount; 
    Button failButton; 
    Button beginButton; 
    TextView countDownBeginText; 
    private TextView countDownMain; 
    public int scoreCounter; 

    public LevelOneFragment() { 
     // Required empty public constructor 
    } 

@Override 
    public void onAttach(Context context){ 
     super.onAttach(context); 
     Activity a; 
     if(context instanceof Activity) 
     { 
      a=(Activity) context; 
     } 

    } 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     // Inflate the layout for this fragment 



     // super.onActivityCreated(savedInstanceState); 
     //setCont(R.layout.fragment_level_one); 
     // return inflater.inflate(R.layout.fragment_level_one,container, false); 

     View view = inflater.inflate(R.layout.fragment_level_one, container, false); 

     //creating viewables and such 
     viewer = (ViewGroup) view.findViewById(R.id.view_level); 
     img = (ImageView) view.findViewById(R.id.imageView); 
     failButton = (Button) view.findViewById(R.id.failureButton); 
     countDownMain = (TextView) view.findViewById(R.id.countDownMain); 
     countDownBeginText = (TextView) view.findViewById(R.id.countDownBeginText); 
     beginButton = (Button) view.findViewById(R.id.beginButton); 

     /*if (view != null) { 
      ViewGroup parent = (ViewGroup) view.getParent(); 
      if (parent != null) { 
       parent.removeView(view); 
      } 
     } 
     try { 
      view = inflater.inflate(R.layout.fragment_level_one, container, false); 
     } catch (InflateException e) { 

     }*/ 

     RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(150, 150); 
     img.setLayoutParams(layoutParams); 
     img.setOnTouchListener(new LevelOneFragment.ChoiceTouchListener()); 

     //begin random movement 
     if(isAdded()) { 
      startRandomButton(img); 
     } 
     else 
     { 
      Log.d("line 98 is", " is null"); 
     } 

     //setting up button for failure CORRECT TO TAKE YOU TO THE MAIN MENU 
     failButton.setOnClickListener(new View.OnClickListener(){ 
      public void onClick(View v){ 
       startActivity(new Intent(getActivity(), MainMenu.class)); 
      } 
     }); 

     //setting countdown text to 3 
     countDownBeginText.setText(":3"); 

     //begin countdown from three 
     beginButton.setOnClickListener(new View.OnClickListener(){ 
      public void onClick(View beginT) { 
       CountDownTimer countDownTimer = new CountDownTimer(3*1000, 3) { 
        @Override 
        public void onTick(long millisUntilFinished) { 

         countDownBeginText.setText(":" + millisUntilFinished/1000); 
         //add possible sound here every tick 
        } 

        @Override 
        public void onFinish() { 
         beginButton.setVisibility(View.INVISIBLE); 
         countDownBeginText.setVisibility(View.INVISIBLE); 

         //countdown from 60------- change parameters in count down timer to the time desired 
         CountDownTimer countDownTimer = new CountDownTimer(60*1000, 3) { 
          @Override 
          public void onTick(long millisUntilFinishedMain) { 

           countDownMain.setText(":" + millisUntilFinishedMain/1000); 
           //add possible sound here every tick 
          } 

          @Override 
          public void onFinish() { 
           Toast.makeText(getActivity(),"You lose", Toast.LENGTH_LONG).show(); 
           //rest of text in method is trial 

           startActivity(new Intent(getActivity(), MainMenu.class)); 

          } 
         }.start(); 

        } 
       }.start(); 
      } 
     }); 
     return view; //inflater.inflate(R.layout.fragment_level_one,container, false); 
    } 
    //getting screen size 
    public static Point getDisplaySize(@NonNull Context context){ 

     Point point = new Point(); 
     WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 
     manager.getDefaultDisplay().getSize(point); 
     return point; 
    } 

    //randomly move 
    public void randomMovement(ImageView img){ 
     //int x = new Random().nextInt(getDisplaySize(getActivity()).x); 
     //int y = new Random().nextInt(getDisplaySize(getActivity()).y); 

     if(isAdded()) { 
      int x = new Random().nextInt(getDisplaySize(getActivity()).x); 
      int y = new Random().nextInt(getDisplaySize(getActivity()).y); 
      img.setY(y); 
      img.setX(x); 
     } 
     else 
      Log.d("Random mover is null", " is null"); 

    } 

    final WeakReference<Activity> activityRef = getActivity(); 
    //creating timer 
    public void startRandomButton(final ImageView img){ 
     Timer timer = new Timer(); 
     timer.schedule(new TimerTask() { 
      @Override 
      public void run() { 
       if(isAdded()){ 
     activityRef.get().runOnUiThread(new Runnable() { //best method in the entire world-- use when trying to update ui in the background 
        @Override 
        public void run() 
        { 
         Activity activity = activityRef.get(); 
         randomMovement(img); 
        } 
       });} 
       else 
       {Log.d("Fragment one", "Is null");} 
      } 
     }, 0, 5000); 
    } 


    //listener for the moving ball 
    private final class ChoiceTouchListener implements View.OnTouchListener { 
     public boolean onTouch(View view, MotionEvent event){ 

      //Calling Counter 
      textCount = (TextView) getView().findViewById(R.id.textViewCount); 



      //switch statement for different events 
      switch (event.getAction() & MotionEvent.ACTION_MASK){ 

       case MotionEvent.ACTION_DOWN: 
        break; 

       case MotionEvent.ACTION_UP: 
        //this is where youre going to generate randmom location with id.setX(randomX) and id.setY(randomY) 
        randomMovement(img); 

        //Setting Counter to count when img is clicked 
        String countValue = textCount.getText().toString(); 
        scoreCounter = Integer.parseInt(countValue); 
        scoreCounter++; 
        textCount.setText(String.valueOf(scoreCounter)); 
        break; 


       case MotionEvent.ACTION_POINTER_DOWN: 
        break; 

       case MotionEvent.ACTION_POINTER_UP: 
        break; 


      } 



      //checking score 
      if(scoreCounter == 10) 
      { 
       Toast.makeText(getActivity(),"You win", Toast.LENGTH_LONG).show(); 

      } 

      viewer.invalidate(); 
      return true; 
     } 
    } 
} 
+0

Es gibt eine spezifische Fragmentlebenszyklus-Methode namens "onActivityCreated", die sicherstellt, dass die Methode "onCreate" der Aktivitäten aufgerufen wurde. Gehen Sie nicht davon aus, dass es außerhalb dieser Methode ordnungsgemäß erstellt wurde. – Spidey

+0

können Sie bitte Ihren Code Ihres Fragments vervollständigen, so dass wir sehen können, wo Sie die 'isAdded()' – Jerrol

+0

ja ich werde eine Bearbeitung dafür jetzt machen. – Cantum2

Antwort

0

Zu allererst Ich sehe Sie rufen super.onActivityCreated von onCreateView.

Zweitens isAdded() ist falsch bedeutet nicht getActivity() ist null. Es gibt auch mAdded Variable innerhalb dieser Methode.

Drittens, wenn Sie einen Timer haben, CountDownLatch - Sie sollten sich abmelden oder stoppen Sie es entweder in OnStop oder onDestroy Callbacks, um Speicherlecks zu verhindern.

Weiter, verwenden Sie Handler#postDelayed, um eine Aktion zu veröffentlichen, die später auf dem UI-Thread ausgeführt werden sollte.

+0

Wie stelle ich sicher, dass es hinzugefügt wird? Aus meiner Sicht bekomme ich diesen Fehler, weil die Aktivität nicht zum Fragment korrekt hinzugefügt wird? Wenn das korrekt ist, wie füge ich die Aktivität dem Fragment hinzu? – Cantum2

+0

Verwenden Sie entweder onActivityCreated oder onStart Callback. – Mike

0

Diese Zeile entfernen: super.onActivityCreated(savedInstanceState);. Diese Zeile wird nicht benötigt, da Sie den Status des Fragments bereits definiert haben. Daher wird die Superklassenvariante nicht benötigt. Erhalten Sie auch nicht die Kontextreferenz von onAttach, in onActivityCreated. Nur diese Lebenszyklusmethode garantiert, dass der Kontext tatsächlich verfügbar ist.

+0

Also um das zu tun ändere ich nur meine onAttatch zu onActivityCreated und behalte alles andere von der on attatch Methode die gleiche? Wo stelle ich diese Methode auf? In meiner Seite onCreateView oder was? – Cantum2

0

Willkommen beim Multithreading. Zuerst prüfen Sie, ob das Fragment hinzugefügt wurde und seine Aktivitätsreferenz nicht null ist (wie getActivity().runOnUiThread wurde nicht abgestürzt), dann versuchen Sie wieder getActivity() aufzurufen, in der Hoffnung, dass es noch nicht null ist. Aber es kann perfekt dazwischen geändert werden, bevor Sie zum zweiten Mal getActivity() anrufen.

Arbeitslösung hier wäre, die Aktivitätsreferenz in WeakReference<Activity> zu speichern, dann rufen Sie ihre get() Methode auf, um mit Activity zu arbeiten, die überprüft, dass es nicht null wird.

Eine andere Lösung wäre, getActivity() Ergebnis in einer Variablen zu speichern, aber das könnte zu Lecks führen, wenn das Entfernen der Aktivität unmöglich ist.

+0

Ich mag Ihre Arbeitslösung. Wie gehe ich vor? – Cantum2

+0

Nur 'final WeakReference activityRef = getActivity()' vor 'runOnUiThread' dann fügen Sie' Activity activity = activityRef.get(); 'in' runOnUiThread' runnable, überprüfen Sie es auf Null und wenn das nicht Null ist - übergeben an ' randomMovement' als zweites Argument. –

+0

nehme ich 'letzte WeakReference activityRef = getActivity()' und legte sie direkt vor runOnUIThread wie wie folgt ... 'letzte WeakReference activityRef = getActivity(). RunonUiThread (new Runnable() {' – Cantum2

Verwandte Themen