एक टुकड़ा और उसके कंटेनर गतिविधि के बीच डेटा पास करना


176

मैं एक खंड और उसके कंटेनर गतिविधि के बीच डेटा कैसे पारित कर सकता हूं? क्या इंटेंट के माध्यम से गतिविधियों के बीच डेटा पास करने के समान है?

मैंने इसे पढ़ा, लेकिन इससे बहुत मदद नहीं मिली:
http://developer.android.com/guide/topics/fundamentals/fragments.html#CommunicatingWithActivity


क्या यह अपर्याप्त है? आप अपनी इच्छानुसार कुछ भी भेज सकते हैं, हो सकता है कि आप और अधिक समझा सकें, आप क्या हासिल करना चाहते हैं?
Marcin Milejski

दस्तावेज़ से मुझे समझ नहीं आया कि, उदाहरण के लिए, मैं गतिविधि से खंड या इसके विपरीत एक मान या स्ट्रिंग पास करूंगा। धन्यवाद
TYB

2
टुकड़ों से अतुल्यकालिक कॉल को संभालने और उन्हें वापस करने का सबसे अच्छा तरीका दोनों तरफ ब्रॉडकास्टर्स को लागू करना है। यदि आप गैर-विशिष्ट अंशों के साथ काम कर रहे हैं तो आपको वैसे भी इसे अतुल्यकालिक बनाना चाहिए।
मर्क सेबेरा

@punisher_malade नहीं, मेरे लिए काम करता है
वादिम

जवाबों:


211

आपके टुकड़े में आप कॉल कर सकते हैं getActivity()

यह आपको उस गतिविधि तक पहुंच प्रदान करेगा जिसने टुकड़ा बनाया था। वहां से आप स्पष्ट रूप से किसी भी तरह के एक्सेसर तरीकों को कॉल कर सकते हैं जो गतिविधि में हैं।

जैसे getResult()आपकी गतिविधि पर एक विधि के लिए उदाहरण :

((MyActivity) getActivity()).getResult();

86
चूंकि आप अपनी गतिविधि के भीतर एक फ़ंक्शन का उपयोग कर रहे हैं (और पैरेंट एंड्रॉइड गतिविधि नहीं) तो आपको अपनी getActivity () कॉल: ((MyActivity) getActivity ()) प्राप्त करने की आवश्यकता होगी। getResult ();
निक

3
टुकड़ा से गतिविधि तक संभवतया पीछे की विधि कैसी होगी?
वासिल वेलेव

6
@VasilValchev, आप एक इंटरफ़ेस बना सकते हैं और गतिविधि को कार्यान्वित करने के लिए बाध्य कर सकते हैं और फिर डेटा को पास करने के लिए अपने टुकड़े में से एक विधि को कॉल कर सकते हैं। यह जाँचने के लिए onAttach विधि का उपयोग करें कि क्या गतिविधि इंटरफ़ेस को लागू करती है।
इवान निकोलोव

3
@IvanNikolov से उत्कृष्ट जवाब। आप Fragments Training Link
bogdan

8
यह एक अच्छा अभ्यास नहीं है और न ही पैटर्न। इंटरफेस के साथ उत्तर सही है।
मोइताब

303

इंटरफेस का उपयोग करके देखें।

कोई भी टुकड़ा जो डेटा को वापस अपनी गतिविधि में पारित करना चाहिए, उसे डेटा को संभालने और पारित करने के लिए एक इंटरफ़ेस घोषित करना चाहिए। फिर सुनिश्चित करें कि आपकी युक्तियां उन इंटरफेस को लागू करती हैं। उदाहरण के लिए:

जावा

आपके टुकड़े में, इंटरफ़ेस घोषित करें ...

public interface OnDataPass {
    public void onDataPass(String data);
}

फिर, onAttach पद्धति में इंटरफ़ेस के इंटरफ़ेस के युक्त कार्यान्वयन को कनेक्ट करें, जैसे:

OnDataPass dataPasser;

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    dataPasser = (OnDataPass) context;
}

आपके टुकड़े के भीतर, जब आपको डेटा के पासिंग को संभालने की आवश्यकता होती है, तो इसे डेटापासर ऑब्जेक्ट पर कॉल करें:

public void passData(String data) {
    dataPasser.onDataPass(data);
}

अंत में, आपकी गतिविधि में जो लागू होता है OnDataPass ...

@Override
public void onDataPass(String data) {
    Log.d("LOG","hello " + data);
}

KOTLIN

चरण 1. इंटरफ़ेस बनाएँ

interface OnDataPass {
    fun onDataPass(data: String)
}

चरण 2. फिर, onAttach विधि (YourFragment) में खंड के इंटरफ़ेस के युक्त कार्यान्वयन को शामिल करें, जैसे:

lateinit var dataPasser: OnDataPass

override fun onAttach(context: Context) {
    super.onAttach(context)
    dataPasser = context as OnDataPass
}

चरण 3. अपने टुकड़े के भीतर, जब आपको डेटा के पारित होने को संभालने की आवश्यकता होती है, तो बस इसे डेटापासर ऑब्जेक्ट पर कॉल करें:

fun passData(data: String){
    dataPasser.onDataPass(data)
}

चरण 4. अंत में, आपकी गतिविधि में OnDataPass को लागू करता है

class MyActivity : AppCompatActivity(), OnDataPass {}

override fun onDataPass(data: String) {
    Log.d("LOG","hello " + data)
}

1
धन्यवाद अच्छा जवाब, बात करने के लिए। यह भी यहाँ बहुत अच्छी तरह से समझाया गया है । मुझे एहसास नहीं हुआ कि आप कई इंटरफेस लागू कर सकते हैं, मैं पहले से ही लागू कर रहा था ActionBar.TabListenerऔर एक अतिरिक्त इंटरफ़ेस जोड़ना था।
यूजीन वैन डेर मेरवे

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

1
कुछ ऐसा है जो मैं सोच रहा हूं ... यह आधिकारिक उत्तर है, और आधिकारिक डेवलपर साइट से वे कहते हैं कि यह नाजुक-अभिनय-सुगंध को संप्रेषित करने का एक सही तरीका है, लेकिन यह भी संभव है कि कास्टिंग गेटएक्टिविटी के माध्यम से ऐसा कैसे करें ( )?
अनम्यूटेडियो

3
ऐसा करने के लिए किसी को अतिरिक्त इंटरफ़ेस की आवश्यकता क्यों है? आप निम्न समाधान को बुरा या अपने समाधान को बेहतर क्यों मानते हैं? ((MyActivity) getActivity) .myMethod (...)
spacifici

3
onAttach (गतिविधि गतिविधि) को हटा दिया गया है, कृपया इसके बजाय onAachach (संदर्भ संदर्भ) का उपयोग करें।
क्रिस .C

23

सबसे आसान दृष्टिकोण लेकिन अनुशंसित नहीं है

आप टुकड़ा से गतिविधि डेटा का उपयोग कर सकते हैं:

गतिविधि:

public class MyActivity extends Activity {

    private String myString = "hello";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);
        ...
    }

    public String getMyData() {
        return myString;
    }
}

टुकड़ा:

public class MyFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        MyActivity activity = (MyActivity) getActivity();
        String myDataFromActivity = activity.getMyData();
        return view;
    }
}

5
यह आपके कोड में उच्च युग्मन जोड़ता है और एक बुरा अभ्यास है। अब आप फ्रैगमेंट का उपयोग किसी अन्य गतिविधि के अलावा नहीं कर सकतेMyActivity
AmeyaB

इस तरीके को बुरा व्यवहार क्यों माना जाता है और क्या इंटरफ़ेस इस प्रश्न का एकमात्र समाधान है?
androidXP

AmeyaB यदि सभी गतिविधि एक बेसएक्टिविटी से फैली हुई हैं या हम इसे बेस एक्टिविटी एक्टिविटी की तरह डालते हैं = (बेस एक्टिविटी) गेटएक्टिविटी (); तब यह सभी गतिविधियों पर काम करेगा
ज़ार ई अहमर

21
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    Bundle b = getActivity().getIntent().getExtras();
            wid = b.getString("wid");
            rid = b.getString("rid");
            View view = inflater.inflate(R.layout.categoryfragment, container, false);
    return view;
 }

14
यह है कि इसे फ्रैगमेंट में कैसे प्राप्त किया जाए, लेकिन यदि आप xml लेआउट फ़ाइल में अपना टुकड़ा रखते हैं, तो आप इसे फ़्रेग्मेंटिंग कॉलिंग क्लास में कैसे सेट करते हैं।
Zapnologica

17

एक टुकड़ा और उसके कंटेनर गतिविधि के बीच डेटा पास करना

गतिविधि:

        Bundle bundle = new Bundle();
        bundle.putString("message", "Alo Elena!");
        FragmentClass fragInfo = new FragmentClass();
        fragInfo.setArguments(bundle);
        transaction.replace(R.id.fragment_single, fragInfo);
        transaction.commit();

टुकड़ा:

टुकड़े में मूल्य पढ़ना

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        String myValue = this.getArguments().getString("message");
        ...
        ...
        ...
        }

हैलो @Elenasys। मैं बंडल डेटा को गतिविधि से टुकड़े में वापस कैसे भेज सकता हूं। मैं खंड से गतिविधि में चला गया और मुझे उस खंड पर वापस जाने की आवश्यकता है जो पहले से ही बनाया गया है (केवल onStart, onResume, ... पर कॉल करता है) और डेटा की आवश्यकता होती है जिसे मैं गतिविधि में प्राप्त करने में सक्षम था। क्या कोई तरीका है कि मैं इसे कैसे करूं या क्या मैं कुछ गलत कर रहा हूं?
मीकल मोरविक

7

मुझे नहीं पता कि यह सबसे अच्छा तरीका है या नहीं बू मैं काफी समय से Google पर खोज कर रहा था कि मैं एक टुकड़ा को इसके कंटेनर गतिविधि से कैसे पारित कर सकता हूं लेकिन मैंने पाया कि गतिविधि के बजाय टुकड़े करने के लिए डेटा भेज रहा था (जो मैं एक नौसिखिया के रूप में मेरे लिए थोड़ा भ्रमित था)।

बाद में मैंने अपने खुद के लिए कुछ आज़माया जो मेरे लिए बिल्कुल वैसा ही काम कर रहा था जैसा मैं चाहता था। तो मैं इसे यहाँ पोस्ट करूँगा जैसे कोई मुझे उसी चीज़ की तलाश में है।

// फ्रैगमेंट से डेटा पास करना।

Bundle gameData = new Bundle();
        gameData.putStringArrayList(Constant.KEY_PLAYERS_ARR,players);
        gameData.putString(Constant.KEY_TEAM_NAME,custom_team_name);
        gameData.putInt(Constant.KEY_REQUESTED_OVER,requestedOver);

        Intent intent = getActivity().getIntent();
        intent.putExtras(gameData);

// कंटेनर गतिविधि से बंडल से डेटा प्राप्त करना।

Bundle gameData = getIntent().getExtras();
        if (gameData != null)
        {
            int over = gameData.getInt(Constant.KEY_REQUESTED_OVER);
            ArrayList<String> players = gameData.getStringArrayList(Constant.KEY_PLAYERS_ARR);
            String team = gameData.getString(Constant.KEY_TEAM_NAME);

        }
        else if (gameData == null)
        {
            Toast.makeText(this, "Bundle is null", Toast.LENGTH_SHORT).show();
        }

6

इंटरफ़ेस सबसे अच्छे समाधानों में से एक है:

गोंद इंटरफ़ेस:

public interface DataProviderFromActivity {

    public String getName();
    public String getId);

}  

MyActivity:

public class MyActivity implements DataProviderFromActivity{

    String name = "Makarov";
    String id = "sys533";

    ... ... ... ... ... .... .... 
    ... ... ... ... ... .... .... 

    public String getName(){
        return name;
    };
    public String getId(){
        return id;
    };
}

MyFragment:

public class MyFragment extends Fragment{

    String fragName = "";
    String fragId = "";

    ... ... ... ... ... .... .... 
    ... ... ... ... ... .... .... 

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        DataProviderFromActivity myActivity= (DataProviderFromActivity) getActivity();
        fragName = myActivity.getName();
        fragId = myActivity.getId();

        ... ... ... ... ... .... .... 
        ... ... ... ... ... .... .... 

        updateFragmentView();
    }
}

हाय @ हसनमकरोव मुझे आपका इंटरफ़ेस पसंद है, सरल और साफ। हालांकि मेरे पास एक मुद्दा है। मुझे नहीं पता कि क्या यह मेरे दृश्य-दर्शक के लिए विशिष्ट है लेकिन मुझे केवल एक बार में अधिकतम 2 टुकड़ों में डेटा मिलता है? स्ट्रिंग्स "मकारोव" और "sys533" खंड 1 और 2 में दिखाई देते हैं जब गतिविधि बनाई जाती है, लेकिन स्ट्रिंग्स 3 में टुकड़े 2 या 3 का चयन होने तक दिखाई नहीं देते हैं? कोई विचार?
JC23

@ JC23 मुझे लगता है कि समस्या टुकड़ा लेनदेन से संबंधित है। MainActivity लॉन्च होने पर कौन सा टुकड़ा सेट होता है?
हसन तारेक

@ JC23 मैं क्या करूँ: Tab / ViewPager के बजाय मैं टूलबार और नेविगेशन दृश्य का उपयोग करता हूँ। OnNavigationItemSelected () मैं टुकड़ों को तदनुसार सेट करने के लिए टुकड़ा लेनदेन करता हूं।
हसन तारेक

2

मैंने एक AppCompatActivity का इस्तेमाल किया जो डेट श्रोताओं को लागू करता है। जब से मुझे एक तिथि सीमा चयनकर्ता को कोड करने की आवश्यकता हुई, तब से फ्रेग्मेंटेशन एक आवश्यकता के रूप में आया। और माता-पिता की गतिविधि के लिए उन्हें वापस करने के लिए मुझे चयनित तिथियों को प्राप्त करने के लिए कंटेनर की भी आवश्यकता थी।

कंटेनर गतिविधि के लिए, यह वर्ग घोषणा है:

public class AppCompatDateRange extends AppCompatActivity implements
    DateIniRangeFragment.OnDateIniSelectedListener, DateFimRangeFragment.OnDateFimSelectedListener

और कॉलबैक के लिए इंटरफेस:

@Override
public void onDateIniSelected(String dataIni) {
    Log.i("data inicial:", dataIni);
}

@Override
public void onDateFimSelected(String dataFim) {
    Log.i("data final:", dataFim);
}

कॉलबैक स्ट्रिंग्स हैं क्योंकि तिथियां एक क्वेरी चयन में परम हैं।

टुकड़ों के लिए कोड (प्रारंभिक तिथि के टुकड़े के आधार पर):

public class DateIniRangeFragment extends Fragment {
OnDateIniSelectedListener callbackIni;

private DatePicker startDatePicker;

public DateIniRangeFragment() {
    ///required empty constructor
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

///through this interface the fragment sends data to the container activity
public interface OnDateIniSelectedListener {
    void onDateIniSelected(String dataIni);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ///layout for the fragment
    View v = inflater.inflate(R.layout.date_ini_fragment, container, false);

    ///initial date for the picker, in this case, current date
    startDatePicker = (DatePicker) v.findViewById(R.id.start_date_picker_appcompat);
    Calendar c = Calendar.getInstance();
    int ano = c.get(Calendar.YEAR);
    int mes = c.get(Calendar.MONTH);
    int dia = c.get(Calendar.DAY_OF_MONTH);
    startDatePicker.setSpinnersShown(false);
    startDatePicker.init(ano, mes, dia, dateSetListener);

    return v;
}

///listener that receives the selected date
private DatePicker.OnDateChangedListener dateSetListener = new DatePicker.OnDateChangedListener() {
    public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
        if (view.isShown()) { ///if the datepicker is on the screen
            String sDataIni = year + "-" + (monthOfYear + 1) + "-" + dayOfMonth;
            callbackIni.onDateIniSelected(sDataIni); //apply date to callback, string format
        }
    }
};

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    /*
    * this function guarantees that the container activity implemented the callback interface
    * */
    try {
        callbackIni = (OnDateIniSelectedListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " deve implementar OnDateIniSelectedListener");
    }
}

}

कंटेनर + अंशों की रचना करने के लिए, मैंने एक कस्टम क्लास के साथ एक ViewPager (AppCompat) का उपयोग किया, जो FragmentPagerAdapter का विस्तार करता है। कोई संवाद नहीं।


2

बस आप EventBus का उपयोग कर सकते हैं यह आसान और महान काम है

EventBus 3 चरणों में

  1. घटनाओं को परिभाषित करें:

    public static class MessageEvent { /* Additional fields if needed */ }

  2. सब्सक्राइबर तैयार करें: अपनी सदस्यता विधि को घोषित और एनोटेट करें, वैकल्पिक रूप से एक थ्रेड मोड निर्दिष्ट करें:

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MessageEvent event) {/* Do something */};

रजिस्टर करें और अपने ग्राहक को अपंजीकृत करें। उदाहरण के लिए, एंड्रॉइड पर गतिविधियों और टुकड़ों को आमतौर पर उनके जीवन चक्र के अनुसार पंजीकृत होना चाहिए:

 @Override
 public void onStart() {
     super.onStart();
     EventBus.getDefault().register(this);
 }

 @Override
 public void onStop() {
     super.onStop();
     EventBus.getDefault().unregister(this);
 }
  1. पोस्ट इवेंट:

    EventBus.getDefault().post(new MessageEvent());


1

मुझे पता है कि यह देर हो सकती है। लेकिन मैं हमेशा इस सवाल पर भी हार गया था। Im इस लिंक को साझा कर रहा हूं ... क्योंकि यह संभवतः इसके लिए वेब पर मुझे मिला सबसे अच्छा स्पष्टीकरण है। यह फ्रैगमेंट को गतिविधि और फ्रैगमेंट को फ्रैगमेंट में हल करता है !

हल किया और वास्तव में अच्छी तरह से समझाया


0

यह मेरे लिए काम कर रहा है ।।

गतिविधि में यह विधि जोड़ें

    public void GetData(String data)
     {
        // do something with your data        
     }

और Fragment में इस लाइन को जोड़ें

((YourActivity)getContext).GetData("your data here");

0
public class Fragmentdemo extends Fragment {

  public interface onDemoEventListener {
    public void demoEvent(String s);
  }

  onDemoEventListener demoEventListener;

  @Override
  public void onAttach(Activity activity) {
    super.onAttach(activity);
        try {
          demoEventListener = (onDemoEventListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement onDemoEventListener");
        }
  }

  final String LOG_TAG = "TAG";

  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragmentdemo, null);

    Button button = (Button) v.findViewById(R.id.button);
    button.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
        demoEventListener.someEvent("Test text to Fragment1");
      }
    });
    enter code here
    return v;
  }
}

-12

कंटेनर गतिविधि में एक टुकड़ा में, एक और गतिविधि से, पारित करने के लिए एक और सरल तरीका है, उदाहरण के लिए:

एक्टिविटी_ए => एक्टिविटी_ (खंड)

अपने गतिविधि_ए में आप एक इरादा बनाते हैं जैसे आप एक डेटा भेज रहे हैं (यहां स्ट्रिंग करें) दूसरी गतिविधि के लिए:

Intent intent = new Intent(getBaseContext(),Activity_B.class);
intent.putExtra("NAME", "Value");
startActivity(intent);

आपके Fragment में, आपके गतिविधि में सम्‍मिलित है:

String data = getActivity().getIntent().getExtras();

getBaseContext()मुझे निम्नलिखित त्रुटि देता है:The method getBaseContext() is undefined for the type new View.OnClickListener(){}
Si8
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.