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 72

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 может вызвать его, как вы хотите) вы передаете ссылку на свой список без создания копии путем сериализации в экземпляр фрагмента. Это очень полезно, потому что если вы измените что-то в списке, вы получите его в других частях приложение и, конечно же, вы используете меньше памяти.

отличный ответ от @Rarw. Попробуйте использовать пакет для передачи информации от одного фрагмента к другому