बंडल के माध्यम से वस्तुओं को कैसे भेजें


119

मुझे उस वर्ग के संदर्भ को पास करने की आवश्यकता है जो बंडल के माध्यम से मेरे प्रसंस्करण का अधिकांश हिस्सा करता है।

समस्या यह है कि इसका इंटेंट्स या संदर्भों से कोई लेना-देना नहीं है और इसमें बड़ी मात्रा में गैर-आदिम वस्तुएं हैं। मैं कक्षा को कैसे पार्सलेबल / सीरियल करने योग्य बनाता हूँ और इसे पास करता हूँ startActivityForResult?


2
"मुझे एक बंडल के माध्यम से अपने प्रसंस्करण के अधिकांश वर्ग के संदर्भ को पास करने की आवश्यकता है" - क्यों?
कॉमन्सवेअर

1
मेरे पास एक ऑब्जेक्ट (DataManager) है, यह एक सर्वर को हैंडल करता है और कुछ GUI के लिए कुछ बैकएंड चलाता है। जब कभी कोई नया कनेक्शन स्थापित होता है, तो मैं चाहता हूं कि उपयोगकर्ता एक नई गतिविधि शुरू करने में सक्षम हो, जो सभी सक्रिय कनेक्शनों की सूची दृश्य में सूचीबद्ध हो और उपयोगकर्ता को एक चुनें। परिणामी डेटा फिर एक नए जीयूआई से जुड़ जाएगा। यह वास्तव में बैक एंड के लिए सिर्फ एक स्किन चॉसर है।
अयोध्या

3
यदि आप कई गतिविधियों पर एक वस्तु के एक ही उदाहरण के साथ काम कर रहे हैं, तो आप सिंगलटन पैटर्न पर विचार कर सकते हैं । यहाँ एक अच्छा ट्यूटोरियल है
sotrh

जवाबों:


55

यह पता लगाने के लिए कि क्या रास्ता लेना है, न केवल कॉमन्सवेयर के "क्यों" के महत्वपूर्ण प्रश्न का उत्तर देने की आवश्यकता है, बल्कि "क्या?" क्या आप इसे पारित कर रहे हैं

वास्तविकता यह है कि केवल एक चीज जो बंडलों के माध्यम से जा सकती है, वह है सादे डेटा - बाकी सब कुछ इस बात की व्याख्या पर आधारित है कि डेटा का अर्थ क्या है या किस ओर इशारा करता है। आप वस्तुतः एक वस्तु पास नहीं कर सकते, लेकिन आप जो कर सकते हैं वह तीन चीजों में से एक है:

1) आप ऑब्जेक्ट को उसके गठित डेटा तक तोड़ सकते हैं, और अगर दूसरे छोर पर उसी तरह की वस्तु का ज्ञान है, तो यह क्रमबद्ध डेटा से एक क्लोन को इकट्ठा कर सकता है। इस तरह से अधिकांश सामान्य प्रकार बंडल से गुजरते हैं।

2) आप एक अपारदर्शी संभाल कर सकते हैं। यदि आप इसे उसी संदर्भ में पारित कर रहे हैं (हालांकि कोई यह पूछ सकता है कि परेशान क्यों है) जो एक ऐसा हैंडल होगा जिसे आप लागू कर सकते हैं या आपत्ति कर सकते हैं। लेकिन अगर आप इसे बिंदर से एक अलग संदर्भ में पास करते हैं तो यह शाब्दिक मूल्य एक मनमाना नंबर होगा (वास्तव में, ये मनमाने संख्या क्रमिक रूप से स्टार्टअप से गिनते हैं)। आप कुछ भी नहीं कर सकते हैं, लेकिन इसका ध्यान रखें, जब तक आप इसे मूल संदर्भ में वापस नहीं भेजते हैं, जो इसे बाइंडर को मूल हैंडल में बदलने का कारण बनेगा, इसे फिर से उपयोगी बना देगा।

3) आप एक मैजिक हैंडल को पास कर सकते हैं, जैसे कि फाइल डिस्क्रिप्टर या कुछ ओएस / प्लेटफ़ॉर्म ऑब्जेक्ट्स के संदर्भ में, और यदि आप सही झंडे सेट करते हैं तो बाइंडर प्राप्तकर्ता के लिए उसी संसाधन की ओर इशारा करते हुए एक क्लोन बनाएगा, जिसका वास्तव में उपयोग किया जा सकता है दूसरा छोर। लेकिन यह केवल कुछ ही प्रकार की वस्तुओं के लिए काम करता है।

सबसे अधिक संभावना है, आप या तो अपनी कक्षा उत्तीर्ण कर रहे हैं, इसलिए दूसरा छोर इसका ट्रैक रख सकता है और इसे बाद में आपको वापस दे सकता है, या आप इसे एक ऐसे संदर्भ में दे रहे हैं, जहाँ अनुक्रमित घटक डेटा से एक क्लोन बनाया जा सकता है ... या फिर आप कुछ ऐसा करने की कोशिश कर रहे हैं जो सिर्फ काम नहीं कर रहा है और आपको पूरे दृष्टिकोण पर पुनर्विचार करने की आवश्यकता है।


1
दौरे के उत्तर के लिए धन्यवाद। आपका अधिकार, मुझे बस इतना करना है कि मेरी नई गतिविधि के लिए वस्तुओं की सूची का एक संदर्भ केवल पास करें। नई गतिविधि सूची से कुछ डेटा लेगी और एक चयन योग्य सूची दृश्य प्रदर्शित करेगी। onSelect, गतिविधि होस्ट गतिविधि के लिए एक परिणाम (क्लिक ऑब्जेक्ट से संबंधित कुछ डेटा) लौटाएगी। अगर मुझे सही तरीके से समझ में आता है, तो मुझे विश्वास है कि आपका विकल्प 2 इसे सबसे उपयुक्त तरीके से संभालता है; मुझे यह अपारदर्शी हैंडल कैसे मिलेगा?
होल्डर

आपकी अन्य गतिविधि किसी भी डेटा को अपारदर्शी वस्तु से प्रदर्शित करने के लिए नहीं निकाल सकती है। आप जो करना चाहते हैं, वह एक समर्थित प्रकार की कुछ सरोगेट वस्तुओं को बनाना और पास करना है जिसमें प्रदर्शित की जाने वाली जानकारी की प्रतियां शामिल हैं।
क्रिस स्ट्रैटन

158

आप किसी ऑब्जेक्ट को JSONObject में बदलने और बंडल पर पास करने के लिए Gson का भी उपयोग कर सकते हैं। मेरे लिए ऐसा करने का सबसे सुंदर तरीका था। मैंने परीक्षण नहीं किया है कि यह प्रदर्शन को कैसे प्रभावित करता है।

प्रारंभिक गतिविधि में

Intent activity = new Intent(MyActivity.this,NextActivity.class);
activity.putExtra("myObject", new Gson().toJson(myobject));
startActivity(activity);

अगली गतिविधि में

String jsonMyObject;
Bundle extras = getIntent().getExtras();
if (extras != null) {
   jsonMyObject = extras.getString("myObject");
}
MyObject myObject = new Gson().fromJson(jsonMyObject, MyObject.class);

3
चूंकि यह गतिविधियों के बीच सामानों को पारित करने की बात है, यह अक्सर ऐसा नहीं होता है जो ऐप के समग्र प्रदर्शन पर बहुत प्रभाव डालता है। कहा जा रहा है कि मुझे संदेह है कि यह मूल पोस्ट के DataManager को क्रमबद्ध करने के लिए काम करेगा क्योंकि यह लगता है कि इसमें सॉकेट कनेक्शन और अन्य समान कक्षाएं हैं।
britzl

4
Google इस समाधान को Serialize के बजाय सुझाता है: इस डॉक्टर पृष्ठ
TechNyquist

3
चेतावनी के एक शब्द के रूप में, मैंने थोड़ी देर के लिए इस तकनीक का पालन किया, लेकिन एक स्मृति सीमा है कि आप स्ट्रिंग के रूप में क्या पारित कर सकते हैं, तो सुनिश्चित करें कि आपका डेटा बहुत बड़ा नहीं है।
जिदुआ

अपने प्रोजेक्ट में Gson समर्थन कैसे जोड़ें, यह जानने के लिए blog.madadipouya.com/2015/09/21/… देखें ।
geekQ

स्मार्ट समाधान, आप से नफरत करता है!
रोहित मंडीवाल

20

Parcelable इंटरफ़ेस एक आशय के साथ एक वस्तु पारित करने के लिए एक अच्छा तरीका है।

मैं अपनी कस्टम वस्तुओं को कैसे पार्सल कर सकता हूं? Parcelable का उपयोग कैसे करें पर एक बहुत अच्छा जवाब है

आधिकारिक Google डॉक्स में एक उदाहरण भी शामिल है


1
या वे धारावाहिक भी हो सकते हैं।
जेफरी बट्टमैन

1
लेकिन काफी कम प्रदर्शन 10x !! इस बेंचमार्क को देखें: developerphil.com/parcelable-vs-serializable
saiyancoder

2
+1 @ माटी की टिप्पणी, हालांकि इसे संदर्भ 10x में डालने के लिए जब किसी एकल ऑब्जेक्ट पर लागू किया जाता है 1 एमएस के बराबर। तो शायद उतना बुरा नहीं जितना लगता है।
पाइनॉयड

1
इस बात से सहमत। समस्या तब होती है जब आप संग्रह से निपटते हैं, जो कि एक सामान्य उपयोग का मामला है यदि आपको रेस्ट एपीआई से संसाधन मिल रहे हैं। लेकिन एक ही वस्तु के लिए, कुछ कुख्यात नहीं होना चाहिए। वैसे भी, अगर सभी बॉयलरप्लेट कोड आपके रास्ते में कुछ हो रहा है, तो आप इस देयता को आज़मा सकते हैं जो आपके लिए यह सब उत्पन्न करता है: github.com/johncarl81/parceler । एक बहुत अच्छा तरीका!
सईयाँकरोड

टूटा हुआ लिंक: 404 (नहीं मिला)
गालल

14

आप वैश्विक अनुप्रयोग स्थिति का उपयोग कर सकते हैं ।

अपडेट करें:

अनुकूलित करें और फिर इसे अपने AndroidManifest.xml में जोड़ें:

<application android:label="@string/app_name" android:debuggable="true" android:name=".CustomApplication"

और फिर आपके प्रोजेक्ट में इस तरह एक वर्ग है:

package com.example;

import android.app.Application;

public class CustomApplication extends Application {
    public int someVariable = -1;
}

और क्योंकि " इसे किसी भी गतिविधि या सेवा से getApplication () के माध्यम से एक्सेस किया जा सकता है ", आप इसे इस तरह उपयोग करते हैं:

CustomApplication application = (CustomApplication)getApplication();
application.someVariable = 123; 

उम्मीद है की वो मदद करदे।


1
उत्तर के लिए धन्यवाद, लेकिन कैसे?
एनोडर

मेरा मानना ​​है कि आप सिर्फ उपवर्ग का आवेदन कर सकते हैं और फिर अपनी पसंद की कोई भी चीज़ स्टोर कर सकते हैं। उपरोक्त लिंक में आपके द्वारा बताए गए xml परिवर्तन आवश्यक हैं।
मार्क स्टायर

9
एक सामान्य डिजाइन प्रिंसिपल के रूप में, यह ग्लोबल्स से बचने के लिए एक अच्छा विचार है जब तक कि आपको वास्तव में उनकी आवश्यकता न हो। इस मामले में अच्छे विकल्प हैं।
ढग

ठीक है, मुझे लगता है कि मुझे वही मिल रहा है जो आप कह रहे हैं। बस एप्लिकेशन का विस्तार करें और उस वस्तु को पकड़े हुए एक चर में फेंक दें जिसे पारित करने की आवश्यकता है; मैंने संदर्भ पृष्ठ की समीक्षा की और आवश्यक xml परिवर्तन नहीं देखे।
18

मैं इसे एक उत्तर के रूप में भी लिखना चाहता था। यह निश्चित रूप से इसे करने के तरीकों में से एक है। लेकिन ध्यान रखें कि ये ऑब्जेक्ट तब तक मेमोरी में रहते हैं जब तक कि आप उन्हें डी-रीफ्रेंस नहीं करते (या ऐप का संदर्भ नष्ट हो जाता है) और जब आपको उनकी आवश्यकता नहीं होती है तो अंतरिक्ष पर कब्जा कर सकते हैं।
इगोर :04ordaš

12

आप अपनी वस्तुओं को सीरियल करने योग्य भी बना सकते हैं और बंडल के getSerializable और putSerializable तरीकों का उपयोग कर सकते हैं ।


1
मैंने कोशिश की और जल्दी से एहसास हुआ कि यह अव्यावहारिक होगा। मुझे नहीं लगता कि उत्तीर्ण वर्ग (थ्रेड्स) में संग्रहीत अधिकांश वस्तुएँ क्रमबद्ध हैं। :) हालांकि धन्यवाद।
एनोडर

10

संभावित समाधान:

Bundle bundle = new Bundle();
bundle.putSerializable("key", new CustomObject());

क्लास कस्टमऑब्जेक्ट:

class CustomObject implements Serializable{
 private SubCustomObject1 sc1;
 private SubCustomObject2 sc2;
}

उप-वस्तुएं:

class SubCustomObject1 implements Serializable{ }

class SubCustomObject2  implements Serializable{ }

7

बंडल कोड के माध्यम से वस्तुओं को भेजने का एक और तरीका नमूना कोड का उपयोग करके हैbundle.putByteArray

public class DataBean implements Serializable {
private Date currentTime;

public setDate() {
    currentTime = Calendar.getInstance().getTime();
 }

public Date getCurrentTime() {
    return currentTime;
 }
}

बंडल में DataBean की वस्तु डालें:

class FirstClass{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your code...

//When you want to start new Activity...
Intent dataIntent =new Intent(FirstClass.this, SecondClass.class);
            Bundle dataBundle=new Bundle();
            DataBean dataObj=new DataBean();
            dataObj.setDate();
            try {
                dataBundle.putByteArray("Obj_byte_array", object2Bytes(dataObj));

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();

            }

            dataIntent.putExtras(dataBundle);

            startActivity(dataIntent);
}

वस्तुओं को बाइट सरणियों में बदलना

/**
 * Converting objects to byte arrays
 */
static public byte[] object2Bytes( Object o ) throws IOException {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream( baos );
      oos.writeObject( o );
      return baos.toByteArray();
    }

बंडल से ऑब्जेक्ट वापस प्राप्त करें:

class SecondClass{
DataBean dataBean;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your code...

//Get Info from Bundle...
    Bundle infoBundle=getIntent().getExtras();
    try {
        dataBean = (DataBean)bytes2Object(infoBundle.getByteArray("Obj_byte_array"));
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

बाइट सरणियों से वस्तुओं को प्राप्त करने की विधि:

/**
 * Converting byte arrays to objects
 */
static public Object bytes2Object( byte raw[] )
        throws IOException, ClassNotFoundException {
      ByteArrayInputStream bais = new ByteArrayInputStream( raw );
      ObjectInputStream ois = new ObjectInputStream( bais );
      Object o = ois.readObject();
      return o;
    }

आशा है कि इससे अन्य मित्रों को मदद मिलेगी।


यह कोड को देखने में आसान और आसान लगता है। लेकिन मुझे लगता है कि एसडीके वस्तुओं को पारित करने के लिए कुछ इस तरह की पेशकश क्यों नहीं करता है, इस पर कुछ और है। क्या आप मुझे इस समाधान पर कुछ और बता सकते हैं?
मारियो Lenci

3
सभी कोड के लिए कोई ज़रूरत नहीं है! बंडल का उपयोग करें। Serializable (objectImplementingSerializable) - यह आपके फिर से यहां फिर से लागू होने के नीचे क्या करता है ...
Risadinha

3

1. एक बहुत ही प्रत्यक्ष और उदाहरण का उपयोग करने के लिए आसान, वस्तु बनाने के लिए पारित किया जा सकता है।

class Object implements Serializable{
    String firstName;
   String lastName;
}

बंडल में 2.पास वस्तु

Bundle bundle = new Bundle();
Object Object = new Object();
bundle.putSerializable("object", object);

6. बंडल से ऑब्जेक्ट को सीरियल के रूप में चुनें, फिर ऑब्जेक्ट को कास्ट करें।

Object object = (Object) getArguments().getSerializable("object");

0

यह मेरे अपने प्रश्न का बहुत ही उलझा हुआ उत्तर है, लेकिन इस पर ध्यान जाता रहता है, इसलिए मुझे लगता है कि मुझे इसे संबोधित करना चाहिए। इनमें से अधिकांश उत्तर सही हैं और काम को पूरी तरह से संभालते हैं। हालांकि, यह एप्लिकेशन की जरूरतों पर निर्भर करता है। इस उत्तर का उपयोग इस समस्या के दो समाधानों का वर्णन करने के लिए किया जाएगा।

आवेदन

पहला अनुप्रयोग है , क्योंकि यह यहाँ उत्तर के बारे में सबसे अधिक बोला गया है। आवेदन संस्थाओं के लिए एक अच्छी वस्तु है जो एक संदर्भ के संदर्भ की आवश्यकता है। एक `सर्वरसॉकेट` को निस्संदेह एक संदर्भ (फ़ाइल I / o या सरल` ListAdapter` अपडेट के लिए) की आवश्यकता होगी। मैं, व्यक्तिगत रूप से, इस मार्ग को प्राथमिकता देता हूं। मुझे आवेदन पसंद है, वे संदर्भ प्राप्त करने के लिए उपयोगी हैं (क्योंकि उन्हें स्थिर बनाया जा सकता है और स्मृति रिसाव की संभावना नहीं है) और एक सरल जीवनचक्र है।

सर्विस

Service` पीछे नहीं है। एक `सेवा` वास्तव में मेरी समस्या के लिए बेहतर विकल्प है क्योंकि यह सेवा करने के लिए डिज़ाइन किया गया है:
एक सेवा एक अनुप्रयोग घटक है जो लंबे समय तक चलने वाले कार्यों को कर सकता है
पृष्ठभूमि और एक यूजर इंटरफेस प्रदान नहीं करता है।
सेवाएँ साफ-सुथरी हैं कि उनमें एक अधिक परिभाषित जीवनचक्र है जिसे नियंत्रित करना आसान है। इसके अलावा, यदि आवश्यक हो, सेवाएं बाहरी रूप से एप्लिकेशन (यानी बूट पर) चला सकती हैं। यह कुछ ऐप्स या सिर्फ एक नीट फीचर के लिए आवश्यक हो सकता है।

यह या तो पूर्ण विवरण नहीं था, लेकिन मैंने उन डॉक्स के लिए लिंक छोड़ दिया, जो अधिक जांच करना चाहते हैं। कुल मिलाकर Serviceमेरे लिए आवश्यक उदाहरण के लिए बेहतर है - एक सर्वर सॉकेट को मेरे एसपीपी डिवाइस पर चलाना।


0

मुझे यह सवाल तब आया जब मैं एक डेट ऑब्जेक्ट को पास करने के लिए रास्ता ढूंढ रहा था। मेरे मामले में, जैसा कि जवाबों के बीच सुझाया गया था, मैंने बंडल का उपयोग किया। Sputializable () लेकिन यह मूल पोस्ट में वर्णित DataManager के रूप में एक जटिल चीज के लिए काम नहीं करेगा।

मेरा सुझाव है कि Application में DataManager को डालने के लिए एक समान परिणाम देगा या इसे एक सिंगलटन बनाने के लिए निर्भरता इंजेक्शन का उपयोग करेगा और DataManager को एक सिंगलटन स्कोप में बाँध देगा और जहाँ भी ज़रूरत होगी DataManager को इंजेक्ट करेगा। न केवल आपको बढ़ी हुई परीक्षण क्षमता का लाभ मिलता है, बल्कि आपको बॉयलर प्लेट के सभी वर्गों और गतिविधियों के बीच "आस-पास की निर्भरता" कोड के बिना क्लीनर कोड भी मिलेगा। (रोबो) गाइस के साथ काम करना बहुत आसान है और नया डैगर फ्रेमवर्क भी आशाजनक लगता है।


1
खैर, एक तारीख की तरह कुछ के साथ, आप बस लंबे समय के मूल्य को पारित कर सकते हैं। लेकिन, बाकी सब अच्छा लगता है। धन्यवाद।
एहोडर

0

एक बंडल का उपयोग करके वस्तु को पास करने का दूसरा सरल तरीका:

  • क्लास ऑब्जेक्ट में, एक स्थैतिक सूची या एक कुंजी के साथ एक और डेटा संरचना बनाएं
  • जब आप ऑब्जेक्ट बनाते हैं, तो इसे सूची / डेटा संरचना में कुंजी के साथ रखें (जैसे कि ऑब्जेक्ट बनाते समय लंबा टाइमस्टैम्प)
  • सूची से ऑब्जेक्ट प्राप्त करने के लिए विधि स्थिर getObject (लंबी कुंजी) बनाएं
  • बंडल में कुंजी को पास करें, ताकि आप कोड में किसी अन्य बिंदु से बाद में ऑब्जेक्ट प्राप्त कर सकें
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.