2017-05-23 1 views
-1

Dans une application Android, j'ai une activité qui contient un fragment.Développement Android comment éviter d'enregistrer le contexte avec un fragment et un menu d'options

Le fragment a une fonction "updateScore" qui a mis à jour l'interface utilisateur avec le score actuel.

Cette fonction est appelée à partir du fragment et doit également être appelée à partir d'un menu d'options qui réside dans l'activité. Ceci peut être réalisé si je sauvegarde le contexte en tant que variable statique dans le fragment, mais c'est une mauvaise pratique. Alors que dois-je faire à la place?

MainActivity:

public class MainActivity extends AppCompatActivity { 

    public static int totalCorrect; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 
     ExerciseFragment exerciseFragment = new ExerciseFragment(); 
     fragmentTransaction.add(R.id.fragment_container, exerciseFragment); 
     fragmentTransaction.commit(); 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     super.onOptionsItemSelected(item); 

     int id = item.getItemId(); 
     if (id == R.id.option_reset_score) { 
      totalCorrect = 0; 
      ExerciseFragment.updateScore(); 
     } 
    } 
} 

ExerciseFragment:

public class ExerciseFragment extends Fragment { 

    private static View view; //bad practice 

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.fragment_exercises, container, false); 
     ExerciseFragment.view = view; 
     updateScore(); 
     return view; 
    } 

    public static void updateScore() { 
     TextView totalCorrectTextView = (TextView) view.findViewById(R.id.total_correct); 
     totalCorrectTextView.setText(MyApp.getAppContext().getString(R.string.correct) + ": " + String.valueOf(MainActivity.totalCorrect)); 

    } 
} 
+0

est ce que vous chargez un ExerciseFragment dans MainActivity ??? –

+0

Connaissez-vous 'interface'? Vous pouvez appeler cette méthode avec une instance statique de fragment. – Piyush

+0

s'il vous plaît poster votre morceau de code que vous chargez un fragment dans l'activité ?? –

Répondre

0

Je pense Voir ou méthode n'a pas besoin d'être statique

public class ExerciseFragment extends Fragment { 

    private View view; 

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.fragment_exercises, container, false); 
     ExerciseFragment.view = view; 
     updateScore(); 
     return view; 
    } 

    public void updateScore() { 
     TextView totalCorrectTextView = (TextView) view.findViewById(R.id.total_correct); 
     totalCorrectTextView.setText(MyApp.getAppContext().getString(R.string.correct) + ": " + String.valueOf(MainActivity.totalCorrect)); 

    } 
} 

Vous devez être initiez le Fragment quelque part.

public class MainActivity extends AppCompatActivity { 

    public static int totalCorrect; 

    public ExerciseFragment exerciseFragment; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     exerciseFragment= new ExerciseFragment(); 

     FragmentManager fragmentManager = getFragmentManager(); 
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 
     if (getFragmentManager().findFragmentById(R.id.fragment_container) != null) 
      fragmentManager.popBackStack(); 
     fragmentTransaction.replace(R.id.fragment_container, currentFragment); 
     fragmentTransaction.addToBackStack(null); 
     fragmentTransaction.commit(); 

    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     super.onOptionsItemSelected(item); 

     int id = item.getItemId(); 
     if (id == R.id.option_reset_score) { 
      totalCorrect = 0; 
      exerciseFragment.updateScore(); 
      return true; 
     } 

     return false; 
    } 
} 
+0

Merci. La variable statique exerciseFragment n'est pas non plus une bonne pratique mais elle ne doit pas être statique. –

+0

@gilads Laissez-moi le corriger. C'était une erreur. –

0

Changer votre ExerciseFragment comme ceci:

public class ExerciseFragment extends Fragment { 

    private View mView; 

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     mView = inflater.inflate(R.layout.fragment_exercises, container, false); 
     updateScore(); 
     return mView; 
    } 

    public void updateScore() { 
     TextView totalCorrectTextView = (TextView) mView.findViewById(R.id.total_correct); 
     totalCorrectTextView.setText(getActivity().getString(R.string.correct) + ": " + String.valueOf(MainActivity.totalCorrect)); 

    } 
} 

Dans votre activité peut trouver votre fragment courant par l'ID de son emballage:

ExerciseFragment exerciseFragment = (ExerciseFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_container); 

Ensuite, vous pouvez utiliser ses méthodes:

exerciseFragment.updateScore(); 
+0

Mais j'ai besoin de changer updateScore() en updateScore (Voir la vue) si je ne veux pas enregistrer la vue de manière statique. –

+0

Je modifie ma réponse. Votre vue n'a pas besoin d'être statique. –

1

Ce n'est pas la meilleure pratique. Ce que je vous conseille de faire est de:

  • Créer une interface, comme « ScoreUpdater » avec une méthode « updateScore »

    public interface ScoreUpdater { 
        void updateScore(); 
    } 
    
  • votre activité relative étendre cette interface
  • déplacer les logiques de votre méthode "updateScore" du fragment à cette méthode surchargée dans l'activité
  • sur la méthode "onAttach" de votre fragment, vérifiez si le contexte auquel le fragment est attaché est l'instance de cette interface ScoreUpdater, et enregistrer un lien vers elle

    @Override 
    public void onAttach(Context context) { 
        super.onAttach(context); 
        if (context instanceof ScoreUpdater) 
         scoreUpdater = (ScoreUpdater)context; 
        ... 
    } 
    
  • chaque fois que vous devez mettre à jour le score de votre fragment, appelez scoreUpdater.updateScore() de votre fragment, updateScore() de votre activité.

Cette façon de programmer est beaucoup plus correcte et suit certains Design Pattern aussi.

0

à partir d'un invoquaient menu d'options qui réside dans l'activité

Il y a votre problème. Votre fragment peut fournir ses propres éléments de menu d'option.Vous devrez remplacer onCreateOptionsMenu et onOptionsItemSelected dans le fragment et appeler le setHasOptionsMenu(true) dans l'une des méthodes de cycle de vie de configuration de votre fragment. Voir this answer.