1

Les fragments sont une partie de la barre de navigation inférieure, jusqu'ici si bon sur la partie navigation. Mais lorsque j'essaie de transmettre des données de fragment1 à fragment2, l'application plante. Aussi, j'utilise l'exemple donné par google à ce qui suit linkCommunication entre fragments via des interfaces

Lorsque j'utilise le code suivant, Android Studio me donne un avertissement désapprouvé!

@Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 

Je me sers CONTEXTE au lieu de ACTIVITÉ ci-dessous est mon code qui tombe en panne:

MainActivity

import android.support.annotation.NonNull; 
import android.support.design.widget.BottomNavigationView; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentTransaction; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.MenuItem; 
import android.view.View; 
import android.widget.TextView; 
import com.br.tron.bottombar.RadioFragment; 
import com.br.tron.bottombar.StreamFragment; 
import com.br.tron.bottombar.InfoFragment; 

public class MainActivity extends AppCompatActivity implements RadioFragment.OnNameSetListener { 

    BottomNavigationView bottomNavigationView; 
    private Fragment fragment; 
    private FragmentManager fragmentManager; 

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

     fragmentManager = getSupportFragmentManager(); 
     fragment = new RadioFragment(); 
     final FragmentTransaction transaction = fragmentManager.beginTransaction(); 
     transaction.add(R.id.main_container, fragment).commit(); 

     bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottomNavigationBar); 
     bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener(){ 
      @Override 
      public boolean onNavigationItemSelected(@NonNull MenuItem item) { 

       switch (item.getItemId()) { 
        case R.id.nav_button_one: 
         fragment = new RadioFragment(); 
         break; 
        case R.id.nav_button_two: 
         fragment = new StreamFragment(); 
         break; 
        case R.id.nav_button_three: 
         fragment = new InfoFragment(); 
         break; 
       } 
       final FragmentTransaction transaction = fragmentManager.beginTransaction(); 
       transaction.replace(R.id.main_container, fragment).commit(); 
       return true; 
      } 
     }); 
    } 

    public void performStreamClick(){ 
     View view = bottomNavigationView.findViewById(R.id.nav_button_two); 
     view.performClick(); 
    } 

    @Override 
    public void setUrl(String url) { 
     StreamFragment frag=(StreamFragment) getSupportFragmentManager().findFragmentByTag("frag"); 
     frag.getUrl(url); 
    } 
} 

RadioFragment (Fragment1 où les données existent)

import android.app.Activity; 
import android.content.Context; 
import android.support.v4.app.Fragment; 
import android.os.Bundle; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentTransaction; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.Button; 

public class RadioFragment extends Fragment implements Button.OnClickListener { 

    Button buttonman; 
    View rootView; 
    String url; 
    Activity a; 
    OnNameSetListener onNameSetListener; 

    @Override 
    public void onAttach(Context context) { 
     super.onAttach(context); 
     if (context instanceof Activity) { 
      a = (Activity) context; 
      try{ 
       onNameSetListener=(OnNameSetListener) context; 
      } 
      catch (Exception e){} 
     } 
    } 

    public RadioFragment(){ 
    }; 

    @Override 
    public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState) { 

     rootView = inflater.inflate(R.layout.fragment_player, container, false); 
     buttonman = (Button)rootView.findViewById(R.id.buttonman); 
     buttonman.setOnClickListener(this); 
     return rootView; 
    } 

    @Override 
    public void onClick(View v) { 
     /*Fragment fragment = new StreamFragment(); 
     FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); 
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 
     fragmentTransaction.replace(R.id.main_container, fragment); 
     fragmentTransaction.addToBackStack(null); 
     fragmentTransaction.commit();*/ 
     url="www.idontknow.com"; 
     onNameSetListener.setUrl(url); 
     ((MainActivity)a).performStreamClick(); 
    } 

    public interface OnNameSetListener 
    { 
     public void setUrl(String url); 
    } 
} 

StreamFragment (fragment2 où je veux envoyer les données -De fragment1)

import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.TextView; 

public class StreamFragment extends Fragment { 

    TextView textViewStream; 

    public StreamFragment(){}; 

    @Override 
    public View onCreateView(final LayoutInflater inflater,final ViewGroup container,final Bundle savedInstanceState) { 
     return inflater.inflate(R.layout.fragment_stream, container, false); 

    } 

    public void getUrl(String url) 
    { 
     textViewStream.setText(url); 
    } 

} 

LogCat

01-06 20: 10: 23,023 3744-3744 /com.br.tron.bottombar E/AndroidRuntime: FATAL EXCEPTION: principal Processus: com.br.tron.bottombar, PID: 3744 java.lang.NullPointerException: Tentative d'invocation de la méthode virtuelle 'void com.br.tron.bottombar.StreamFragment.getUrl (java.lang.String)' sur une référence d'objet null at com.br.tron.bottombar.MainActivity.setUrl (MainActivity.java:64) à com.br.tron.bottombar.RadioFragment.onClick (RadioFragment.java:61) à android.view.View.performClick (View.java:5201) at android.view.View $ PerformClick.run (View.java:21209) à android.os.Handler.handleCallback (Handler.java:739) à android.os.Handler.dispatchMessage (Handler.java:95) à android.os.Looper .loop (Looper.java:148) at android.app.ActivityThre ad.main (ActivityThread.java:5525) à java.lang.reflect.Method.invoke (méthode native) à com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:730) à com .android.internal.os.ZygoteInit.main (ZygoteInit.java:620) 01-06 20: 10: 24.663 3744-3744 /? I/Process: Signal d'envoi. PID: 3744 SIG: 9

Répondre

0

Vous devez initialiser votre textViewStream dans le fragment StreamFragment.

+0

Où dois-je initialiser oncreate ou à l'intérieur getUrl? ce qui est mieux ? –

+0

S'il vous plaît ajouter un peu plus d'informations à votre réponse. Peut-être expliquer pourquoi cette solution devrait fonctionner et pourquoi le PO ne fonctionne pas. –

3

Vous n'enregistrez jamais l'étiquette frag que vous recherchez plus tard.

Dans votre MainActivity ACTUALISATION:

final FragmentTransaction transaction = fragmentManager.beginTransaction(); 
transaction.add(R.id.main_container, fragment, "frag").commit(); 
... 
final FragmentTransaction transaction = fragmentManager.beginTransaction(); 
transaction.replace(R.id.main_container, fragment, "frag").commit(); 
... 

En plus de cela au sein de votre classe StreamFragment vous ne définissez la variable TextViewStream après vous gonflez votre mise en page.

@Override 
public View onCreateView(final LayoutInflater inflater,final ViewGroup container,final Bundle savedInstanceState) { 
    View view = inflater.inflate(R.layout.fragment_stream, container, false); 
    textViewStream = (TextView) view.findViewById(R.id.ID_GOES_HERE); 
    return view; 
} 

Edit: D'autres erreurs

vous obtenez un ClassCastException parce que vous n'êtes pas vérifier pour voir si le fragment que vous obtenez dans MainActivity.setUrl est un StreamFragment. Et il est logique que cela échoue parce que vous enregistrez la balise frag pour les trois types de fragments personnalisés. Voici une autre solution:

 fragment = new RadioFragment(); 
     final FragmentTransaction transaction = fragmentManager.beginTransaction(); 
     transaction.add(R.id.main_container, fragment, "radio_fragment").commit(); 
     ... 

     @Override 
     public boolean onNavigationItemSelected(@NonNull MenuItem item) { 

      switch (item.getItemId()) { 
       String tag = ""; 
       case R.id.nav_button_one: 
        fragment = new RadioFragment(); 
        tag = "radio_fragment"; 
        break; 
       case R.id.nav_button_two: 
        fragment = new StreamFragment(); 
        tag = "stream_fragment"; 
        break; 
       case R.id.nav_button_three: 
        fragment = new InfoFragment(); 
        tag = "info_fragment"; 
        break; 
      } 
      final FragmentTransaction transaction = fragmentManager.beginTransaction(); 
      transaction.replace(R.id.main_container, fragment, tag).commit(); 
      return true; 
     } 

Faire les changements appropriés dans la chaîne de Tag dans setUrl:

StreamFragment frag=(StreamFragment) getSupportFragmentManager().findFragmentByTag("stream_fragment"); 
if (frag != null) frag.getUrl(url); 
+1

toujours écrasant mate J'ai initialisé le textViewStream comme siva déjà souligné que dehors et modifié le MainActivity selon votre suggestion –

+0

@ user3599100 Est-ce que le stacktrace est toujours le même? Pourriez-vous s'il vous plaît poster la nouvelle pile. – asadmshah

+0

Nouvelle trace Stack -> java.lang.ClassCastException: RadioFragment ne peut pas être jeté à StreamFragment En gros ce code est pointé -> '@Override public void setUrl (String url) { StreamFragment frag = (StreamFragment) getSupportFragmentManager() .findFragmentByTag ("frag"); frag.getUrl (url); } ' –

0

deux la clé de réponses actuelles sur votre problème de plantage. Je m'attends à ce que cela prenne soin de votre question principale. @asadmshah semble avoir pris soin de votre prochain problème. Assurez-vous de voter sa réponse & l'accepter.

En ce qui concerne l'avertissement d'utiliser l'exemple de code de Google, voici ce que AS vous donnera actuellement si vous lui dites de créer un nouveau fragment.

@Override 
public void onAttach(Context context) { 
    super.onAttach(context); 
    if (context instanceof OnFragmentInteractionListener) { 
     mListener = (OnFragmentInteractionListener) context; 
    } else { 
     throw new RuntimeException(context.toString() 
       + " must implement OnFragmentInteractionListener"); 
    } 
} 

Le but de cela est de faire en sorte que l'activité que vous attacher à implémente l'interface que vous avez défini dans votre fragment.

Et au sujet de l'interface, toutes les communications fragment-activité devraient être faites à travers elle. Il serait préférable de trouver un moyen d'appeler le performStreamClick() via l'interface. (Je viens juste de réaliser que j'ai fait la même erreur sur une application que j'ai commencé il y a plusieurs mois mais que je suis en train de finir maintenant :). Pour finir, juste un FYI, vous pouvez obtenir l'activité ci-jointe d'un fragment avec getActivity().

EDIT: 1er, il pourrait être utile de voir votre code actuel. Je vais supposer que vous avez ce que Asad a mis dans sa réponse, plus ou moins. Aussi, quel est le comportement attendu? Je crois que vous faites une sélection dans RadioFragment puis le remplacer par StreamFragment. Autrement dit, les deux fragments prennent toute la barre de navigation, ils n'existent pas en même temps. Si c'est faux, faites le moi savoir. Si vous appelez toujours setUrl() et performStreamClick() dans le même ordre que précédemment, vous obtenez null car vous n'avez jamais créé de fragment portant ce nom. Vous ne pouvez pas trouver un fragment que vous n'avez pas déjà créé. Sans réellement mettre cela en place pour le tester moi-même, je crois que ce que vous devez faire serait de sauvegarder l'URL dans une variable globale en setUrl(), puis dans votre écouteur de clic, passez le StreamFragment lorsque vous le créez.

Voir la « Livrer un message à un fragment » section du lien que vous avez situé pour le faire

 Bundle args = new Bundle(); 
     args.putInt(ArticleFragment.ARG_POSITION, position); 
     newFragment.setArguments(args); 

(de toute évidence, la manipulation de votre chaîne url au lieu de l'int dans l'exemple)

en outre, ce n'est pas une mauvaise idée de gérer les valeurs nULL lorsque la recherche d'un fragment qui devrait déjà exister

StreamFragment frag=(StreamFragment) getSupportFragmentManager().findFragmentByTag("stream_frag"); 
    if(frag == null) { 
     final FragmentTransaction transaction = fragmentManager.beginTransaction(); 
     StreamFragment fragment = new StreamFragment(); 
     transaction.replace(R.id.main_container, fragment, "stream_frag").commit(); 
    }   
+0

Merci l'homme que j'ai été en mesure de réaliser ce que vous avez dit à travers l'interface au lieu de créer un nouvelle activité .. vous m'avez sauvé un peu de mémoire :) Je n'ai pas assez de points ou je l'aurais voté –

+0

Content de vous aider. Seulement environ 1 an et demi à Android et encore apprendre beaucoup moi-même. Si Asad ne vous répond pas sur votre dernière question, faites le moi savoir et je vais essayer d'aider. – Gary99

+0

vous pourriez m'aider aussi .. la question est toujours sans réponse! Je ne suis pas en mesure d'envoyer les données au fragment cible :( –