2017-07-20 5 views
0

J'ai une MainActivity avec un TabLayout et plusieurs Fragments. Lorsque l'application est créée, tout fonctionne correctement, cependant, lorsque l'application s'est exécutée en arrière-plan et retourne, j'obtiens une exception nullpointer. Les objets que j'ai créés dans la méthode OnCreateView de Fragments sont null.Pourquoi ces objets sont-ils nuls lorsque je retourne à l'application?

Ceci est ma classe FragmentPagerAdapter:

public class SectionsPagerAdapter extends FragmentPagerAdapter { 
    private FragmentStrobe fragmentStrobe = null; 
    private FragmentFlashLight fragmentFlashLight = null; 
    private FragmentDisco fragmentDiscoLight = null; 
    private FragmentShaking fragmentShaking = null; 
    private FragmentPoliceLights fragmentPoliceLights = null; 

    public SectionsPagerAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     switch (position) { 
      case 0: 
       if(fragmentDiscoLight == null){ 
        fragmentDiscoLight = new FragmentDisco(); 
       } 
       return fragmentDiscoLight; 
      case 1: 
       if(fragmentStrobe == null){ 
        fragmentStrobe = new FragmentStrobe(); 
       } 
       return fragmentStrobe; 
      case 2: 
       if(fragmentFlashLight == null){ 
        fragmentFlashLight = new FragmentFlashLight(); 
       } 
       return fragmentFlashLight; 
      case 3: 
       if(fragmentShaking == null){ 
        fragmentShaking = new FragmentShaking(); 
       } 
       return fragmentShaking; 
      case 4: 
       if(fragmentPoliceLights == null){ 
        fragmentPoliceLights = new FragmentPoliceLights(); 
       } 
       return fragmentPoliceLights; 
      default: 
       return null; 
     } 
    } 

    @Override 
    public int getCount() { 
     return 5; 
    } 

    @Override 
    public CharSequence getPageTitle(int position) { 
     return null; 
    } 
} 

Dans mon MainActivity, j'ai quelques boutons qui sont au-dessus des fragments. Lorsque ce bouton est cliqué, j'appelle une méthode dans le fragment;

private void initializeButtonStart(){ 
    buttonStart = (Button) findViewById(R.id.start); 

    buttonStart.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      myPreferences.setBoolPreferences(MyPreferences.MY_PREFS_START, 
        !myPreferences.getBoolPreferences(MyPreferences.MY_PREFS_START, MyPreferences.MY_PREFS_START_DEFAULT)); 

      setIcon(); 

      ((FragmentInterface) mSectionsPagerAdapter.getItem(tabLayout.getSelectedTabPosition())).onRunPermissionChanged(); 
     } 
    }); 
} 

Et voici le code d'un fragment.

public class FragmentDisco extends Fragment implements FragmentInterface { 

private static final double IMAGE_RATIO = 1.08158; 

private View viewBackground; 

private View rootView; 

private ImageView imageViewDiscoBall; 

private Bitmap bitmap; 

private Disco disco; 

private MyPreferences myPreferences; 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    rootView = inflater.inflate(R.layout.fragment_discolight, container, false); 

    disco = new Disco(getContext()); 

    myPreferences = new MyPreferences(getContext()); 

    bitmap = BitmapFactory.decodeResource(getContext().getResources(),R.drawable.disco_start); 

    initializeView(); 
    initializeImageView(); 

    return rootView; 
} 

private void initializeView(){ 
    viewBackground = getActivity().findViewById(R.id.viewMain); 
} 

private void initializeImageView(){ 
    imageViewDiscoBall = (ImageView) rootView.findViewById(R.id.discoBall); 

    imageViewDiscoBall.setImageBitmap(bitmap); 

    imageViewDiscoBall.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
     @Override 
     public void onGlobalLayout() { 
      imageViewDiscoBall.getViewTreeObserver().removeOnGlobalLayoutListener(this); 

      int width = imageViewDiscoBall.getWidth(); 
      int resultHeight = (int)((float) width * IMAGE_RATIO); 

      ViewGroup.LayoutParams layoutParams = imageViewDiscoBall.getLayoutParams(); 
      layoutParams.height = resultHeight; 
      imageViewDiscoBall.setLayoutParams(layoutParams); 
     } 
    }); 
} 


@Override 
public void onResume() { 
    super.onResume(); 
} 

@Override 
public void onStop() { 
    super.onStop(); 

    stopDisco(); 
} 

@Override 
public void onTabSelected() { 
    if(myPreferences == null || imageViewDiscoBall == null || viewBackground == null || disco == null){ 
     return; 
    } 

    if(myPreferences.getBoolPreferences(MyPreferences.MY_PREFS_START, MyPreferences.MY_PREFS_START_DEFAULT) && 
      (myPreferences.getIntPreferences(MyPreferences.MY_PREFS_CURRENT_FRAGMENT, MyPreferences.MY_PREFS_CURRENT_FRAGMENT_DEFAULT) == MainActivity.FRAGMENT_DISCO)){ 
     disco.start(viewBackground, imageViewDiscoBall); 
    } 
} 

@Override 
public void onTabUnselected() { 
    stopDisco(); 
} 

@Override 
public void onRunPermissionChanged() { 
    if(myPreferences == null || imageViewDiscoBall == null || viewBackground == null || disco == null){ 
     System.out.println("NULLL !!!!!!"); 
     return; 
    } 

    if(myPreferences.getBoolPreferences(MyPreferences.MY_PREFS_START, MyPreferences.MY_PREFS_START_DEFAULT)){ 
     disco.start(viewBackground, imageViewDiscoBall); 
    } else { 
     stopDisco(); 
    } 
} 

private void stopDisco(){ 
    if(disco == null || imageViewDiscoBall == null || viewBackground == null){ 
     return; 
    } 

    disco.stop(); 

    viewBackground.setBackgroundColor(Color.TRANSPARENT); 
    imageViewDiscoBall.setImageBitmap(bitmap); 
} 
} 

La plupart du temps lorsque je reviens de l'arrière-plan, la méthode appelée dans les Fragments affiche "NULL !!!". Comment puis-je réparer cela?

+0

qu'est ce que 'myPreferences'? vous n'avez pas montré comment vous l'avez déclaré. Vous pouvez également utiliser le débogage pour déterminer ce que exactyl est nul. –

+0

J'ai édité la question. J'ai ajouté maintenant toute la classe Fragment. – tomhogenkamp

Répondre

0

L'android efface vos données de la mémoire pour économiser l'espace mémoire et la puissance. Cela peut se produire beaucoup plus rapidement si vous avez un périphérique mémoire faible où le système d'exploitation doit effacer les tâches en arrière-plan (voir également, si votre arrière-plan limite dans Paramètres -> Paramètres du développeur -> Limite du processus d'arrière-plan sur votre périphérique) Avec l'application de premier plan, assurez-vous qu'il dispose de suffisamment de mémoire, de ressources etc.

Donc, pour éviter cela,

  • Faire de grands objets que dans la portée où ils sont nécessaires comme des objets d'image de chargement où ils seront utilisés.
  • Utilisez savedInstances pour permettre à votre activité de revenir à l'état précédent.
  • Pour l'utilisation de savedInstances, vous devez rendre vos objets sérialisables.
+0

Merci pour la réponse, alors dois-je sauvegarder les Fragments dans savedInstances? Peut-être que vous pouvez le clarifier? – tomhogenkamp

+0

n ° Des choses comme des fragments doivent être créées dans la méthode getFragment de votre adaptateur. Sinon nulle part. Cela vous permettra de créer beaucoup d'applications plus légères. –

+0

Voici ce que vous devriez faire. Faites des progrès en identifiant des variables comme la partie où l'application fonctionnait. Maintenant, sur la méthode 'OnPause()', vous sauvegardez ces variables dans savedInstances. Sur la méthode 'OnResume()', android va redonner ces variables. Donc, reprenez l'état en activité. Idem pour les fragments, sauvegarder l'état actuel et reprendre cela. Par exemple, vous étiez dans le 3ème onglet qui contient listview et vous étiez en train de faire quelque chose sur le 11ème élément. Donc enregistrer 3, 11 et l'identifiant de travail dans savedInstances et au moment de la reprise, vous passerez à l'onglet 3 et ensuite dire fragment pour aller au 11e élément et ainsi de suite. –