2016-09-14 3 views
8

में नेस्टेड टुकड़ों के बीच संचार मैंने हाल ही में how to make nested fragments in Android सीखा। मुझे नहीं पता कि संचार कैसे होना चाहिए, हालांकि।एंड्रॉइड

enter image description here

fragment communication documentation पढ़ने से मुझे पता है कि

सभी टुकड़ा करने के लिए टुकड़ा संचार जुड़े गतिविधि के माध्यम से किया जाता है। दो टुकड़े सीधे संवाद नहीं करना चाहिए।

यह गतिविधि के भीतर भाई के टुकड़ों के लिए समझ में आता है, लेकिन यह माता-पिता के टुकड़े के संचार के लिए ज्यादा समझ में नहीं आता है। क्या मुझे चाइल्ड फ्रैगमेंट के लिए माता-पिता के टुकड़े से बात करने के लिए गतिविधि तक सभी तरह से जाने की ज़रूरत है? अगर उत्तर एक साधारण "हां" है तो मैं ऐसा कर सकता हूं। यदि यह "नहीं" है, तो कोड डिज़ाइन कैसा दिखता है?

मैं Nested Fragment documentation में देखता हूं कि कोई पैरेंट खंड का संदर्भ प्राप्त करने के लिए getParentFragment() का उपयोग कर सकता है। तो क्या इसका मतलब यह है कि बच्चे को सीधे माता-पिता के साथ संवाद करना चाहिए? ऐसा लगता है कि पैरेंट गतिविधि के साथ संवाद करने वाले सामान्य टुकड़े के साथ क्या प्रोत्साहित किया जाता है।

+0

आपको पेरेंटफ्रैगमेंट इंस्टेंस विधि –

+2

बनाना होगा, आप अपने ऐप में ** कॉलबैक ** का उपयोग कर ऐसा कर सकते हैं। –

+0

आपके पास इवेंटबस जैसे [ओटो] (http://square.github.io/otto/) या [ग्रीनरोबोट] (https://github.com/greenrobot/EventBus) –

उत्तर

12

टिप्पणियों में राहुल शर्मा की सलाह के बाद, मैंने चाइल्ड फ्रैगमेंट से माता-पिता के टुकड़े और गतिविधि में संवाद करने के लिए इंटरफ़ेस कॉलबैक का उपयोग किया। मैं भी submitted this answer to Code Review। मैं वहां एक गैर-उत्तर ले रहा हूं (इस लेखन के समय) यह संकेत है कि इस डिजाइन पैटर्न के साथ कोई बड़ी समस्या नहीं है। ऐसा लगता है कि मुझे आधिकारिक fragment communication docs में दिए गए सामान्य मार्गदर्शन के अनुरूप होना चाहिए।

उदाहरण परियोजना

निम्न उदाहरण परियोजना उदाहरण प्रश्न में दिए गए विस्तृत करता है। इसमें ऐसे बटन हैं जो टुकड़ों से गतिविधि तक और बाल टुकड़े से माता-पिता के टुकड़े तक ऊपर संचार शुरू करते हैं।

मैं इस तरह परियोजना लेआउट सेट:

enter image description here

मुख्य गतिविधि

गतिविधि दोनों टुकड़े से श्रोताओं को लागू करता है, ताकि वह उन लोगों से संदेश प्राप्त कर सकते हैं।

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

import android.support.v4.app.FragmentTransaction; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.util.Log; 

public class MainActivity extends AppCompatActivity implements ParentFragment.OnFragmentInteractionListener, ChildFragment.OnChildFragmentToActivityInteractionListener { 

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

     FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
     ft.replace(R.id.parent_fragment_container, new ParentFragment()); 
     ft.commit(); 
    } 

    @Override 
    public void messageFromParentFragmentToActivity(String myString) { 
     Log.i("TAG", myString); 
    } 

    @Override 
    public void messageFromChildFragmentToActivity(String myString) { 
     Log.i("TAG", myString); 
    } 
} 

जनक टुकड़ा

जनक टुकड़ा बाल टुकड़ा से श्रोता को लागू करता है, ताकि वह यह से संदेश प्राप्त कर सकते हैं।

वैकल्पिक TODO: यदि अभिभावक टुकड़ा बाल टुकड़े के साथ संचार शुरू करना चाहता था, तो यह केवल इसका प्रत्यक्ष संदर्भ प्राप्त कर सकता था और फिर अपने सार्वजनिक तरीकों में से एक को कॉल कर सकता था।

import android.content.Context; 
import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentTransaction; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 


public class ParentFragment extends Fragment implements View.OnClickListener, ChildFragment.OnChildFragmentInteractionListener { 


    // **************** start interesting part ************************ 

    private OnFragmentInteractionListener mListener; 


    @Override 
    public void onClick(View v) { 
     mListener.messageFromParentFragmentToActivity("I am the parent fragment."); 
    } 

    @Override 
    public void messageFromChildToParent(String myString) { 
     Log.i("TAG", myString); 
    } 

    public interface OnFragmentInteractionListener { 
     void messageFromParentFragmentToActivity(String myString); 
    } 

    // **************** end interesting part ************************ 



    @Override 
    public void onAttach(Context context) { 
     super.onAttach(context); 
     if (context instanceof OnFragmentInteractionListener) { 
      mListener = (OnFragmentInteractionListener) context; 
     } else { 
      throw new RuntimeException(context.toString() 
        + " must implement OnFragmentInteractionListener"); 
     } 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.fragment_parent, container, false); 
     view.findViewById(R.id.parent_fragment_button).setOnClickListener(this); 
     return view; 
    } 

    @Override 
    public void onViewCreated(View view, Bundle savedInstanceState) { 
     Fragment childFragment = new ChildFragment(); 
     FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); 
     transaction.replace(R.id.child_fragment_container, childFragment).commit(); 
    } 

    @Override 
    public void onDetach() { 
     super.onDetach(); 
     mListener = null; 
    } 

} 

बाल टुकड़ा

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

import android.content.Context; 
import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 


public class ChildFragment extends Fragment implements View.OnClickListener { 


    // **************** start interesting part ************************ 

    private OnChildFragmentToActivityInteractionListener mActivityListener; 
    private OnChildFragmentInteractionListener mParentListener; 

    @Override 
    public void onClick(View v) { 
     switch (v.getId()) { 
      case R.id.child_fragment_contact_activity_button: 
       mActivityListener.messageFromChildFragmentToActivity("Hello, Activity. I am the child fragment."); 
       break; 
      case R.id.child_fragment_contact_parent_button: 
       mParentListener.messageFromChildToParent("Hello, parent. I am your child."); 
       break; 
     } 
    } 

    public interface OnChildFragmentToActivityInteractionListener { 
     void messageFromChildFragmentToActivity(String myString); 
    } 

    public interface OnChildFragmentInteractionListener { 
     void messageFromChildToParent(String myString); 
    } 

    @Override 
    public void onAttach(Context context) { 
     super.onAttach(context); 

     // check if Activity implements listener 
     if (context instanceof OnChildFragmentToActivityInteractionListener) { 
      mActivityListener = (OnChildFragmentToActivityInteractionListener) context; 
     } else { 
      throw new RuntimeException(context.toString() 
        + " must implement OnChildFragmentToActivityInteractionListener"); 
     } 

     // check if parent Fragment implements listener 
     if (getParentFragment() instanceof OnChildFragmentInteractionListener) { 
      mParentListener = (OnChildFragmentInteractionListener) getParentFragment(); 
     } else { 
      throw new RuntimeException("The parent fragment must implement OnChildFragmentInteractionListener"); 
     } 
    } 

    // **************** end interesting part ************************ 



    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.fragment_child, container, false); 
     view.findViewById(R.id.child_fragment_contact_activity_button).setOnClickListener(this); 
     view.findViewById(R.id.child_fragment_contact_parent_button).setOnClickListener(this); 
     return view; 
    } 

    @Override 
    public void onDetach() { 
     super.onDetach(); 
     mActivityListener = null; 
     mParentListener = null; 
    } 

} 
+0

महान पदों! मैं सिर्फ यह जोड़ना चाहता हूं कि आपके दोनों "वैकल्पिक TODO:" को विधिओं के साथ फ्रैगमेंट या चाइल्डफ्रैगमेंट के संदर्भ में प्राप्त किया जा सकता है: Activity.onAttachFragment (Fragment fragment) और Fragment.onAttachFragment (Fragment childFragment) – AppiDevo

+0

@Suragch द्वारा नहीं किया जा सका EventBus ??? आपका उत्तर सही है लेकिन आप इस बात से सहमत नहीं हैं कि यह पैटर्न ऐप (इवेंट बस की तुलना में) में अधिक जटिलता जोड़ता है –

+0

@ मिलादफारिडिया, हो सकता है। मैंने इवेंटबस का उपयोग नहीं किया है। यदि आप एक उत्तर जोड़ना चाहते हैं तो मुझे इसका एक उदाहरण देखने में दिलचस्पी होगी। – Suragch

3

हालांकि @ Suragch के जवाब सही है, लेकिन मैं एक और तरीका Fragments या Activity के बीच डेटा पास में जोड़ना चाहते हैं। कोई फर्क नहीं पड़ता कि यह एक Activity है या Fragment आप 3 चरणों में घटना बस के साथ डेटा पास कर सकते हैं: घटनाक्रम के लिए

public class OrderMessage { 
    private final long orderId; 
    /* Additional fields if needed */ 
    public OrderMessage(long orderId) { 
     this.orderId = orderId; 
    } 
    public long getOrderId() { 
     return orderId; 
    } 
} 

2- रजिस्टर और अपंजीकृत:

1- एक घटना (संदेश) को परिभाषित करें घटनाएं प्राप्त करने में सक्षम होने के लिए, कक्षा को ईवेंट बस के लिए पंजीकरण/पंजीकरण रद्द करना होगा। Activities और Fragments लिए सबसे अच्छी जगह onStart() और onStop()

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

@Override 
public void onStop() { 
    EventBus.getDefault().unregister(this); 
    super.onStop(); 
} 

एक घटना आपको लगता है कि घटना की सदस्यता के लिए है प्राप्त करने के लिए सक्षम होने के लिए है। ऐसा करने के लिए, अपनी कक्षा में अपनी विधियों में से किसी एक को @Subscribe एनोटेशन जोड़ें।

@Subscribe(threadMode = ThreadMode.MAIN) 
    public void onMessage(OrderMessage message){ 
     /* Do something for example: */ 
     getContractDetails(message.getOrderId()); 
    } 

3- पोस्ट एक घटना

EventBus.getDefault().post(new OrderMessage(recievedDataFromWeb.getOrderId())); 

अधिक दस्तावेज और उदाहरण Here पाया जा सकता है। अन्य पुस्तकालय भी हैं: Otto

+1

इस उत्तर को जोड़ने के लिए समय निकालने के लिए धन्यवाद। लोगों के लिए एक और विकल्प की तुलना करना उपयोगी होगा। – Suragch