Android: передача данных (дополнительно) на фрагмент
Я новичок в программировании на Android, и у меня возникли проблемы при передаче ArrayList Parcelable фрагменту. Это деятельность, которая запускается(работает хорошо!) где feedlist является ArrayList из parcelable музыка.
Intent in = new Intent(context, ListMusicsActivity.class);
in.putExtra("arrayMusic", feedList);
activity.startActivity(in);
фрагмент активности onCreate() метод:
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activitymusiclist);
if(savedInstanceState != null)
{
ListMusicFragment frag = new ListMusicFragment();
frag.setArguments(getIntent().getExtras());
}
}
фрагмент кода:
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;
}
}
Я думаю, что проблема в строке
listMusics = (ArrayList<Music>) getArguments().getSerializable("arrayMusic");
наконец-то это мое Музыкальный класс:
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];
}
};
}
когда я запускаю этот код, проблема, которую я сделать это java.ленг.NullPointerException в фрагменте onCreateView () метод. Я был бы очень признателен, если бы кто-то указал мне в правильном направлении, чтобы увидеть, где я терплю неудачу.
EDIT: проблема решена: мне просто нужно было добавить эту строку в метод фрагмента Activity onCreate () (иначе getArguments () вернет null):
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, frag).commit();
и добавьте это к фрагмент кода:
@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));
}
}
где, listMusics является ArrayList
на Parcelable
музыка.
4 ответа:
две вещи. Во-первых, я не думаю, что вы добавляете данные, которые вы хотите передать фрагменту правильно. То, что вам нужно передать фрагменту, - это пакет, а не намерение. Например, если я хотел отправить
int
значение для фрагмента я бы создал пакет, поставилint
в этот пакет, а затем установить этот пакет в качестве аргумента, который будет использоваться при создании фрагмента.Bundle bundle = new Bundle(); bundle.putInt(key, value); fragment.setArguments(bundle);
во-вторых, чтобы получить эту информацию вам нужно получить аргументов, переданных фрагмент. Затем вы извлекаете значение на основе ключа, с которым вы его идентифицировали. Например, в вашем фрагменте:
Bundle bundle = this.getArguments(); if (bundle != null) { int i = bundle.getInt(key, defaulValue); }
что вы получаете изменения в зависимости от того, что вы ставите. Также значение по умолчанию обычно
null
но не нужно. Это зависит от того, если вы установите значение по умолчанию для этого аргумента.наконец я не думаю, что вы можете сделать это
onCreateView
. Я думаю, что вы должны получить эти данные в пределах вашего фрагментаonActivityCreated
метод. Мои рассуждения таковы.onActivityCreated
выполняется после того, как основная деятельность закончила свою собственнуюonCreate
метод. Если вы размещаете информацию, которую вы хотите получить в пакете во время вашей деятельностиonCreate
метод, он не будет существовать во время вашего фрагментаonCreateView
. Попробуйте использовать это вonActivityCreated
и просто обновить вашListView
содержимое позже.
предпочитаю
Serializable
= нет шаблонного кода. Для передачи данных в другие фрагменты или действия разница в скорости наParcelable
не имеет значения.Я бы также всегда предоставлял вспомогательный метод для
Fragment
илиActivity
, таким образом, вы всегда знаете, какие данные должны быть переданы. Вот пример для вашего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); ... }
есть простая причина, почему я предпочел пакет из-за отсутствия дубликатов данных в памяти. Он состоит из открытого метода init для фрагмент
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; } }
в двух словах, вы создаете экземпляр фрагмента с помощью метода init (u может вызвать его, как вы хотите) вы передаете ссылку на свой список без создания копии путем сериализации в экземпляр фрагмента. Это очень полезно, потому что если вы измените что-то в списке, вы получите его в других частях приложение и, конечно же, вы используете меньше памяти.