Android: passer des données (extras) à un fragment
je suis nouveau à la programmation Android et j'ai des problèmes en passant une liste D'un parcellaire à un fragment. C'est l'activité qui est lancée(ça marche bien!) où feedlist est un ArrayList d'un Musique .
Intent in = new Intent(context, ListMusicsActivity.class);
in.putExtra("arrayMusic", feedList);
activity.startActivity(in);
Le fragment de l'Activité onCreate() la méthode:
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activitymusiclist);
if(savedInstanceState != null)
{
ListMusicFragment frag = new ListMusicFragment();
frag.setArguments(getIntent().getExtras());
}
}
le code de Fragment:
public class ListMusicFragment extends SherlockFragment{
private ArrayList<Music> listMusics = new ArrayList<Music>();
private ListView listMusic;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
listMusics = (ArrayList<Music>) getArguments().getSerializable("arrayMusic");
View view = inflater.inflate(R.layout.musiclistview, container, false);
listMusic = (ListView) view.findViewById(R.id.musicListView);
listMusic.setAdapter(new MusicBaseAdapter(getActivity(), listMusics));
return view;
}
}
je pense que le le problème est dans la ligne
listMusics = (ArrayList<Music>) getArguments().getSerializable("arrayMusic");
enfin c'est mon cours de musique:
public class Music implements Parcelable{
private String url;
private String artist;
private String title;
private String duration;
private String info_url;
private String lyrics;
public Music(String url, String artist, String title,
String duration, String lyrics, String info_url)
{
this.url = url;
this.artist = artist;
this.title = title;
this.duration = duration;
this.lyrics = lyrics;
this.info_url = info_url;
}
public Music(Parcel in)
{
url = ParcelUtils.readString(in);
artist = ParcelUtils.readString(in);
title = ParcelUtils.readString(in);
duration = ParcelUtils.readString(in);
info_url = ParcelUtils.readString(in);
lyrics = ParcelUtils.readString(in);
}
public String getUrl()
{
return url;
}
public String getArtist()
{
return artist;
}
public String getTitle()
{
return title;
}
public String getDuration()
{
return duration;
}
public String getLyrics()
{
return lyrics;
}
public String getInfo()
{
return info_url;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags)
{
ParcelUtils.writeString(dest, url);
ParcelUtils.writeString(dest, artist);
ParcelUtils.writeString(dest, title);
ParcelUtils.writeString(dest, duration);
ParcelUtils.writeString(dest, lyrics);
ParcelUtils.writeString(dest, info_url);
}
public static final Parcelable.Creator<Music> CREATOR =
new Parcelable.Creator<Music>() {
public Music createFromParcel(Parcel in)
{
return new Music(in);
}
public Music[] newArray(int size)
{
return new Music[size];
}
};
}
quand j'exécute ce code le problème que j'obtiens est un java.lang.NullPointerException dans la Méthode Fragment onCreateView () . J'apprécierais beaucoup que quelqu'un me montre la bonne direction pour voir où j'échoue.
EDIT : Problème résolu: j'ai juste besoin d'ajouter cette ligne à la méthode de fragment Activity onCreate () (sinon getargument () retournerait null):
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, frag).commit();
et ajouter ceci au code de fragment:
@Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
Bundle bundle = getArguments();
if(bundle != null)
{
listMusics = bundle.getParcelableArrayList("arrayMusic");
listMusic.setAdapter(new MusicBaseAdapter(getActivity(), listMusics));
}
}
où, listMusics est un ArrayList
de Parcelable
de la Musique.
4 réponses
deux choses. D'abord je ne pense pas que vous ajoutez les données que vous souhaitez passer à la fragment correctement. Ce que vous devez passer au fragment est un paquet, Pas une intention. Par exemple, si je voulais envoyer une valeur int
à un fragment, je créerais un bundle, je mettrais le int
dans ce bundle, puis je définirais ce bundle comme un argument à utiliser lorsque le fragment a été créé.
Bundle bundle = new Bundle();
bundle.putInt(key, value);
fragment.setArguments(bundle);
seconde pour récupérer l'information dont vous avez besoin pour obtenir les arguments envoyés au fragment. Vous extrayez ensuite la valeur en fonction de la clé avec laquelle vous l'avez identifiée. Par exemple dans votre fragment:
Bundle bundle = this.getArguments();
if (bundle != null) {
int i = bundle.getInt(key, defaulValue);
}
ce que vous obtenez change selon ce que vous mettez. Aussi la valeur par défaut est généralement null
, mais n'a pas besoin d'être. Cela dépend si vous définissez une valeur par défaut pour cet argument.
enfin, je ne pense pas que vous puissiez faire cela dans onCreateView
. Je pense que vous devez récupérer ces données dans la méthode onActivityCreated
de votre fragment. Mon raisonnement est le suivant. onActivityCreated
fonctionne après que l'activité sous-jacente a terminé sa propre méthode onCreate
. Si vous placez les informations que vous souhaitez récupérer dans le faisceau de votre activité onCreate
méthode, il n'existera pas pendant votre fragment onCreateView
. Essayez de l'utiliser dans onActivityCreated
et mettez à jour votre contenu ListView
plus tard.
je préfère Serializable
= pas de code boilerplate. Pour transmettre des données à d'autres Fragments ou activités , la différence de vitesse à un Parcelable
n'a pas d'importance.
Je fournirais aussi toujours une méthode d'aide pour un Fragment
ou Activity
, de cette façon vous savez toujours, quelles données doivent être passées. Voici un exemple pour votre ListMusicFragment
:
private static final String EXTRA_MUSIC_LIST = "music_list";
public static ListMusicFragment createInstance(List<Music> music) {
ListMusicFragment fragment = new ListMusicFragment();
Bundle bundle = new Bundle();
bundle.putSerializable(EXTRA_MUSIC_LIST, music);
fragment.setArguments(bundle);
return fragment;
}
@Override
public View onCreateView(...) {
...
Bundle bundle = intent.getArguments();
List<Music> musicList = (List<Music>)bundle.getSerializable(EXTRA_MUSIC_LIST);
...
}
il y a une raison simple pour laquelle j'ai préféré le bundle en raison de l'absence de données dupliquées en mémoire. Il s'agit d'une méthode init public pour le fragment
private ArrayList<Music> listMusics = new ArrayList<Music>();
private ListView listMusic;
public static ListMusicFragment createInstance(List<Music> music) {
ListMusicFragment fragment = new ListMusicFragment();
fragment.init(music);
return fragment;
}
public void init(List<Music> music){
this.listMusic = music;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.musiclistview, container, false);
listMusic = (ListView) view.findViewById(R.id.musicListView);
listMusic.setAdapter(new MusicBaseAdapter(getActivity(), listMusics));
return view;
}
}
en deux mots, vous créez une instance du fragment an par la méthode init (u peut l'appeler comme u veut) vous passez la référence de votre liste sans créer de copie par sérialisation à l'instance du fragment. C'est très utile parce que si vous changez quelque chose dans la liste, vous l'obtiendrez dans d'autres parties de l'application et, bien sûr, vous utilisez moins de mémoire.
grande réponse de @Rarw. Essayez d'utiliser un paquet pour transmettre des informations d'un fragment à un autre