एंड्रॉइड: डेटा (एक्स्ट्रा) पास करने के लिए एक टुकड़ा


84

मैं एंड्रॉइड प्रोग्रामिंग के लिए नया हूं और मुझे एक टुकड़ा करने के लिए एक पार्सल के एरेलेस्ट पास करते समय समस्याएं आ रही हैं। यह वह गतिविधि है जो लॉन्च की गई है (अच्छी तरह से काम कर रही है!) जहां फीडलिस्ट एक पार्सल म्यूज़िक का एक एरियरिस्ट है ।

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.lang.NullPointerException फ्रैगमेंट ऑनक्रिएट व्यू () विधि में है । मैं बहुत सराहना करूंगा अगर कोई मुझे सही दिशा में देखने के लिए इशारा करे कि मैं कहां असफल हो रहा हूं।

संपादित करें : समस्या हल: मुझे इस लाइन को खंड गतिविधि में जोड़ने की जरूरत है OnCreate () विधि (getArguments प्राप्त करें () शून्य हो जाएगी):

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

जहाँ, सूची संगीत का एक ArrayListहै Parcelable


पहला कदम LogCat विंडो खोलने जा रहा है, अपवाद को देखें और देखें कि NullPointerException क्या कारण है। यदि आप इसका पता नहीं लगा सकते हैं, तो स्टैकट्रेस को अपवाद से अपने प्रश्नों में डाल दें ओ कोई मदद कर सकता है।
ब्रायन

ब्रायन: टिप के लिए धन्यवाद! जब मैं इस कार्यक्रम को निष्पादित करता हूं, तो यह लॉगकट मुझे मिलता है! pastebin.com/ycVcXLFf
बहुवचन

ऐसा लगता है कि आपकी दृश्य लेआउट फ़ाइल में कोई त्रुटि है: ** इसके कारण: android.view.InflateException: बाइनरी एक्सएमएल फ़ाइल लाइन # 10: कक्षा फ़ैलाने में त्रुटि **
ब्रायन

नहीं, त्रुटि ListView के कोड में है, मुझे इस पर यकीन है। अगर मैं ListMusicFragment में संगीत ऑब्जेक्ट्स का एक ArrayList बनाता हूं तो कोड ठीक काम करता है। वैसे भी, यहाँ यह मेरी लेआउट फाइलें हैं: pastebin.com/4DwHh1yk
बहुवचन

जवाबों:


196

दो चीज़ें। पहले मुझे नहीं लगता कि आप उस डेटा को जोड़ रहे हैं जिसे आप सही तरीके से टुकड़े में पास करना चाहते हैं। टुकड़े को पास करने के लिए आपको जो कुछ चाहिए वह एक बंडल है, न कि कोई मंशा। उदाहरण के लिए अगर मैं 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बाद में अपनी सामग्री को अपडेट करें ।


3
सरल उत्तर, कमाल। अपने कोड उदाहरण को कॉपी किया और इसने एक ट्रीट का काम किया!
Iamanyone

1
इसलिए ... क्या होगा यदि तर्क विशिष्ट इंटरफेस को लागू करने वाली वस्तुओं द्वारा निर्दिष्ट किए जाते हैं और न कि आदिम हैं?
पयोट्र

2
यदि आप ऑब्जेक्ट का उपयोग करना चाहते हैं, तो सुनिश्चित करें कि वे Parcelableइंटरफ़ेस को लागू करते हैं । Bundleजोड़ने / प्राप्त Parcelableकरने का समर्थन करता है ताकि आप उन लोगों को भेज सकें और कोई समस्या न हो।
17

1
क्या आपके पास वर्कफ़्लो है जब गतिविधि के लेआउट में परिभाषित किया गया है। xml गतिविधि? इस मामले में मेरा मानना ​​है कि एंड्रॉइड अपने आप ही उस टुकड़े को तुरंत हटा देगा जिसका अर्थ है कि आप तर्क नहीं दे सकते हैं? व्यक्तिगत रूप से मैं एक इवेंटबस (otto) और एक निर्माता का उपयोग कर रहा हूं, जो गतिविधि से डेटा को टुकड़े में पारित करने के लिए है।
एलेक होम्स

ज़रूर - जब आप अपने XML में टुकड़े को परिभाषित करते हैं तो एंड्रॉइड का उपयोग करें: उस टुकड़े के लिए एक टैग सेट करने के लिए टैग विशेषता। आपकी गतिविधि में आप उस टुकड़े का पता लगाने के लिए FragmentManager.findFragmentByTag () का उपयोग कर सकते हैं और फिर एक नए टुकड़े के साथ XML टुकड़े को बदलने के लिए एक FragmentTransaction का उपयोग करके जिस तरह से आप चाहते हैं। एक और तरीका यह होगा कि findFragmentById का उपयोग करें और अपने XML टुकड़े के android: id मान का उपयोग करें।
रारव

2

मैं पसंद करता हूं Serializable= कोई बॉयलरप्लेट कोड नहीं। अन्य Fragments या गतिविधियों के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);
    ...
}

1

एक सरल क्यों है कि मैं स्मृति में कोई डुप्लिकेट डेटा नहीं होने के कारण बंडल को पसंद करता था। यह टुकड़े के लिए एक 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 विधि द्वारा टुकड़ा का एक उदाहरण बनाते हैं (आप इसे यू के रूप में कॉल कर सकते हैं) आप अपनी सूची के संदर्भ को क्रमांकन के बिना प्रतिलिपि बनाकर खंड के उदाहरण से बनाते हैं। यह बहुत उपयोगी है क्योंकि यदि आप सूची में कुछ बदलते हैं तो यू इसे ऐप के अन्य हिस्सों और टोकोर्स में मिलेगा, आपको कम मेमोरी मिलती है।


1
Android में यह एक गलत तरीका है। क्योंकि टुकड़ा मनोरंजन (कॉन्फ़िगरेशन परिवर्तन (स्क्रीन रोटेशन) और कुछ अन्य पर) यह एक खाली कंस्ट्रक्टर का आह्वान करेगा, और सभी पैरामीटर खो जाएंगे। उपयोग newInstanceऔर setArgumentsअनुशंसित के रूप में।
कूलमाइंड

-5

@Rarw द्वारा शानदार जवाब। एक टुकड़े से दूसरे में जानकारी पारित करने के लिए एक बंडल का उपयोग करने का प्रयास करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.