2013-03-13 41 views
66

我是新來的Android編程和我有而傳遞Parcelable的一個ArrayList片段的問題。 這是推出的活動(工作好!)其中feedlist是parcelable 音樂的ArrayList。安卓:傳遞數據(臨時演員)的片段

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]; 
    } 
}; 
} 

當我運行這段代碼我得到的問題是在片段onCreateView()方法一個顯示java.lang.NullPointerException。 如果有人指出我在正確的方向看到我失敗的地方,我將非常感激。

編輯:問題解決了:我只是需要加入這一行的片段活動onCreate()方法(othwewise的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是Parcelable音樂的ArrayList

+0

第一步是打開LogCat窗口,查看異常並查看導致NullPointerException的原因。如果你無法弄清楚,那麼把異常中的堆棧跟蹤放入你的問題中,這樣可以有人提供幫助。 – Brian 2013-03-13 17:30:07

+0

BrianV:感謝您的提示!這是我執行程序時得到的LogCat! http://pastebin.com/ycVcXLFf – pluralism 2013-03-13 17:35:01

+0

看起來像你在你的視圖佈局文件中有一個錯誤:**引起:android.view.InflateException:二進制XML文件行#10:錯誤膨脹類片段** – Brian 2013-03-13 17:36:55

回答

157

兩件事情。首先,我不認爲你正在添加你想傳遞給片段的數據。你需要傳遞給片段的是一個包,而不是一個意圖。例如,如果我想的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方法後運行。如果你將要捆綁durring您的活動的onCreate方法中檢索信息,也不會在你的片段的onCreateView存在。嘗試在onActivityCreated中使用此功能,稍後再更新您的ListView內容。

+3

簡單的答案,真棒。複製你的代碼示例,它工作得很好! – iamanyone 2013-05-13 16:29:02

+1

那麼...如果參數是由實現特定接口而不是基元的對象指定的呢? – Piotr 2014-02-28 04:23:07

+2

如果你想使用對象,只要確保它們實現了'Parcelable'接口。 'Bundle'支持添加/獲取'Parcelable',所以你可以發送這些也沒有問題。 – Rarw 2014-02-28 17:51:21

1

我更喜歡Serializable =沒有樣板代碼。將數據傳遞給其他片段或活動the speed difference to a Parcelable並不重要。

我總是會爲FragmentActivity提供一個幫助方法,這種方式您總是知道,必須傳遞哪些數據。這裏爲您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); 
    ... 
} 
1

有一個簡單的,爲什麼我要者優先捆綁由於在內存中沒有重複的數據。它包含了片段

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公共方法,您可以通過在init方法創建片段的實例(U可以調用它爲u想)你通過列表​​的無參考通過序列化創建一個副本到片段的實例。這非常有用,因爲如果你在列表中改變了某些東西,你會在應用程序的其他部分獲得它,而當然,你使用更少的內存。

+0

在Android中,這是一種錯誤的方式。因爲在片段重新創建(配置更改(屏幕旋轉)等)時,它會調用一個空的構造函數,並且所有參數都將丟失。按照建議使用'newInstance'和'setArguments'。 – CoolMind 2016-10-27 15:13:15

-2

@Rarw的好回答。嘗試使用捆綁將信息從一個片段傳遞到另一個片段