একটি ডায়ালগফ্র্যাগমেন্ট থেকে একটি খণ্ডে কলব্যাক করুন


159

প্রশ্ন: কীভাবে একজন ডায়ালগফ্র্যাগমেন্ট থেকে অন্য একটি খণ্ডে কলব্যাক তৈরি করে। আমার ক্ষেত্রে, জড়িত ক্রিয়াকলাপটি ডায়ালগফ্রেগমেন্ট সম্পর্কে সম্পূর্ণ অসচেতন হওয়া উচিত।

আমার আছে বিবেচনা করুন

public class MyFragment extends Fragment implements OnClickListener

তারপরে কোন এক সময় আমি করতে পারি

DialogFragment dialogFrag = MyDialogFragment.newInstance(this);
dialogFrag.show(getFragmentManager, null);

যেখানে মাই ডায়ালগফ্রেগমেন্টের মতো দেখাচ্ছে

protected OnClickListener listener;
public static DialogFragment newInstance(OnClickListener listener) {
    DialogFragment fragment = new DialogFragment();
    fragment.listener = listener;
    return fragment;
}

তবে ডায়ালগফ্রেগমেন্টটি তার জীবনকাল থেকে বিরতি দিয়ে আবার শুরু করলে শ্রোতার আশেপাশের কোনও নিশ্চয়তা নেই। একটি খণ্ডে কেবলমাত্র গ্যারান্টি হ'ল সেটেগমেন্টস এবং গেটআরগমেন্টগুলির মাধ্যমে কোনও বান্ডিলের মধ্য দিয়ে।

ক্রিয়াকলাপটি রেফারেন্স করার একটি উপায় আছে যদি এটি শ্রোতা হওয়া উচিত:

public Dialog onCreateDialog(Bundle bundle) {
    OnClickListener listener = (OnClickListener) getActivity();
    ....
    return new AlertDialog.Builder(getActivity())
        ........
        .setAdapter(adapter, listener)
        .create();
}

তবে আমি চাই না যে ক্রিয়াকলাপগুলি ইভেন্টগুলি শোন, আমার একটি খণ্ড দরকার। সত্যই, এটি কোনও জাভা অবজেক্ট হতে পারে যা অনক্লিকলিস্টনার প্রয়োগ করে।

ডায়ালগফ্র্যাগমেন্টের মাধ্যমে একটি অ্যালার্টডায়ালগ উপস্থাপন করে এমন একটি খণ্ডের দৃ concrete় উদাহরণ বিবেচনা করুন। এটিতে হ্যাঁ / না বোতাম রয়েছে। আমি এই বোতাম টিপুনগুলি এটি তৈরি করা টুকরোটিতে কীভাবে পাঠাতে পারি?


আপনি উল্লেখ করেছেন "তবে ডায়ালগফ্রেগমেন্টটি তার জীবনকাল থেকে বিরতি দিয়ে আবার শুরু করলে শ্রোতার আশেপাশের কোনও নিশ্চয়তা নেই।" আমি ভেবেছিলাম অনডেট্রয়ে () চলাকালীন খণ্ডের রাজ্যটি ধ্বংস হয়ে যায়? আপনার অবশ্যই সঠিক হতে হবে, তবে এখন কীভাবে ফ্রেগমেন্ট স্টেটটি ব্যবহার করবেন সে সম্পর্কে আমি কিছুটা বিভ্রান্ত। আপনার উল্লিখিত সমস্যাটি আমি কীভাবে পুনরুত্পাদন করব, শ্রোতা আশেপাশে নেই?
শান

OnClickListener listener = (OnClickListener) getParentFragment();পরিবর্তে আপনি ডায়ালগফ্র্যাগমেন্টে কেন কেবল ব্যবহার করতে পারবেন না তা আমি দেখতে পাচ্ছি না এবং আপনার মূল টুকরাটি আপনি যেমন করেছেন ঠিক তেমন ইন্টারফেসটি প্রয়োগ করে।
kiruwka

এখানে একটি সম্পর্কহীন প্রশ্নের উত্তর কিন্তু এটা আপনাকে দেখাতে কীভাবে এই একটি পরিষ্কার ভাবে সম্পন্ন করা হয় stackoverflow.com/questions/28620026/...
user2288580

উত্তর:


190

ক্রিয়াকলাপ জড়িত ডায়ালগফ্র্যাগমেন্ট সম্পর্কে সম্পূর্ণ অজানা।

খণ্ড বিভাগ:

public class MyFragment extends Fragment {
int mStackLevel = 0;
public static final int DIALOG_FRAGMENT = 1;

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

    if (savedInstanceState != null) {
        mStackLevel = savedInstanceState.getInt("level");
    }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt("level", mStackLevel);
}

void showDialog(int type) {

    mStackLevel++;

    FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction();
    Fragment prev = getActivity().getFragmentManager().findFragmentByTag("dialog");
    if (prev != null) {
        ft.remove(prev);
    }
    ft.addToBackStack(null);

    switch (type) {

        case DIALOG_FRAGMENT:

            DialogFragment dialogFrag = MyDialogFragment.newInstance(123);
            dialogFrag.setTargetFragment(this, DIALOG_FRAGMENT);
            dialogFrag.show(getFragmentManager().beginTransaction(), "dialog");

            break;
    }
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch(requestCode) {
            case DIALOG_FRAGMENT:

                if (resultCode == Activity.RESULT_OK) {
                    // After Ok code.
                } else if (resultCode == Activity.RESULT_CANCELED){
                    // After Cancel code.
                }

                break;
        }
    }
}

}

ডায়ালগফ্রেগমেন্ট শ্রেণি:

public class MyDialogFragment extends DialogFragment {

public static MyDialogFragment newInstance(int num){

    MyDialogFragment dialogFragment = new MyDialogFragment();
    Bundle bundle = new Bundle();
    bundle.putInt("num", num);
    dialogFragment.setArguments(bundle);

    return dialogFragment;

}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {

    return new AlertDialog.Builder(getActivity())
            .setTitle(R.string.ERROR)
            .setIcon(android.R.drawable.ic_dialog_alert)
            .setPositiveButton(R.string.ok_button,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, getActivity().getIntent());
                        }
                    }
            )
            .setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                    getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_CANCELED, getActivity().getIntent());
                }
            })
            .create();
}
}

100
আমি মনে করি এখানে চাবিটি setTargetFragmentএবং getTargetFragment। এর ব্যবহারটি onActivityResultকিছুটা অস্পষ্ট। ফ্রেগমেন্ট কলারে নিজের নির্দিষ্ট পদ্ধতিটি ঘোষণা করা এবংঅ্যাক্টিভিটিস রেজাল্টের পুনরায় পরিকল্পনা করার পরিবর্তে এটি ব্যবহার করা ভাল। তবে এর সমস্ত শব্দার্থবিজ্ঞান point
চিরকালীন

2
স্ট্যাক লেভেল ভেরিয়েবল ব্যবহার হয় না?
নাম প্রদর্শন করুন

6
এটি কি কনফিগার চেঞ্জ-রোটেশনে বেঁচে থাকবে?
ম্যাক্সরুনার

3
এটি ব্যবহৃত। দ্রষ্টব্য: ঘোরানো বা ঘুম বাঁচার জন্য স্ট্যাক স্তরটি প্রয়োজন ছিল না। অ্যাক্টিভিটিআরসাল্টের পরিবর্তে, আমার খণ্ডটি ডায়ালগেরসাল্টহ্যান্ডলার # হ্যান্ডেলডায়ালোগ্রিজাল্ট (আমি তৈরি একটি ইন্টারফেস) প্রয়োগ করে। @ মাইকোড, ইন্টেন্টে যুক্ত হওয়া ডায়লগের বাছাইয়ের মানটি প্রদর্শন করা এবং তারপরে আপনারঅ্যাক্টিভিটিআরসাল্টের ভিতরে পড়তে দুর্দান্ত সহায়তা করবে। উদ্দেশ্যগুলি প্রাথমিকভাবে অস্পষ্ট।
ক্রিস বেটি

7
@ অন্তঃসত্তা, আপনার আপত্তি সম্পূর্ণ যুক্তিসঙ্গত, তবে আমি মনে করি যে onctivityResult () এর মান হ'ল এটি যে কোনও খণ্ডে উপস্থিত থাকার গ্যারান্টিযুক্ত, সুতরাং যে কোনও খণ্ডটি পিতামাতার হিসাবে ব্যবহার করা যেতে পারে। যদি আপনি নিজের ইন্টারফেস তৈরি করেন এবং পিতা-মাতার টুকরোটি এটি প্রয়োগ করে থাকে তবে শিশুটি কেবল সেই বাবা-মায়ের সাথে ব্যবহার করা যেতে পারে যা সেই ইন্টারফেসটি প্রয়োগ করে। যদি আপনি পরে আরও বেশি পরিমাণে শিশুকে ব্যবহার শুরু করেন তবে সেই ইন্টারফেসে বাচ্চাকে সংযুক্ত করা আপনাকে হতাশ করতে পারে। অ্যাক্টিভিটিআরসাল্ট () ইন্টারফেসটি "বিল্ট-ইন" ব্যবহার করতে কোনও অতিরিক্ত সংযোগের প্রয়োজন হয় না, সুতরাং এটি আপনাকে আরও কিছুটা নমনীয়তা দেয়।
ডালবারিয়া

78

টার্গেটফ্রেগমেন্ট সমাধানটি কথোপকথনের খণ্ডগুলির জন্য সর্বোত্তম বিকল্প বলে মনে হয় না কারণ এটি IllegalStateExceptionঅ্যাপ্লিকেশন নষ্ট হয়ে যায় এবং পুনরায় তৈরি করার পরে এটি তৈরি করতে পারে । এই ক্ষেত্রে FragmentManagerলক্ষ্য খণ্ডটি খুঁজে পেতে পারেনি এবং আপনি IllegalStateExceptionএই জাতীয় বার্তা সহ একটি পাবেন :

"কী অ্যান্ড্রয়েডের জন্য খণ্ডটি আর বিদ্যমান নেই: টার্গেট_স্টেট: সূচক 1"

দেখে মনে হচ্ছে Fragment#setTargetFragment()এটি কোনও শিশু এবং পিতা-মাতার টুকরাটির মধ্যে যোগাযোগের জন্য নয়, বরং ভাইবোন-অংশগুলির মধ্যে যোগাযোগের জন্য।

সুতরাং বিকল্প উপায় হ'ল ChildFragmentManagerঅভিভাবক খণ্ডগুলি ব্যবহার করে এরপরে ক্রিয়াকলাপগুলি ব্যবহার করে ডায়লগের টুকরো তৈরি করা FragmentManager:

dialogFragment.show(ParentFragment.this.getChildFragmentManager(), "dialog_fragment");

এবং একটি ইন্টারফেস ব্যবহার করে, onCreateপদ্ধতিতে DialogFragmentআপনি পিতামণ্ডার খণ্ডটি পেতে পারেন:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    try {
        callback = (Callback) getParentFragment();
    } catch (ClassCastException e) {
        throw new ClassCastException("Calling fragment must implement Callback interface");
    }
}

এই পদক্ষেপের পরে আপনার কলব্যাক পদ্ধতিতে কল করা কেবলমাত্র বাকি।

ইস্যু সম্পর্কে আরও তথ্যের জন্য, আপনি লিঙ্কটি দেখতে পারেন: https://code.google.com/p/android/issues/detail?id=54520


2
এটি অপি 23-তে যুক্ত করা অনটচ (প্রসঙ্গে প্রসঙ্গ) এর সাথেও কাজ করে
সান্তা টেক্লাদো

1
এটির গ্রহণযোগ্য উত্তর হওয়া উচিত। বর্তমান গৃহীত উত্তরগুলি বগি এবং খণ্ডগুলি এই জাতীয় ব্যবহারের জন্য নয়।
NecipAllef

3
@ আহমাদফাদলি সমস্যা এখানে টুকরো টুকরো মধ্যে যোগাযোগের জন্য সঠিক প্রসঙ্গ (পিতা বা মাতা) পেতে। আপনি যদি ক্রিয়াকলাপের শিশু হিসাবে কথোপকথন খণ্ডটি ব্যবহার করেন তবে কোনও বিভ্রান্তি হওয়া উচিত নয়। কলব্যাক পুনরুদ্ধার করতে ক্রিয়াকলাপের ফ্রেগমেন্টম্যানেজার এবং getActivity () যথেষ্ট।
ওগুজ ওজকান

1
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। এটি স্পষ্টভাবে ব্যাখ্যা করা হয়েছে এবং বিস্তারিতভাবে বলা হয়েছে, এটি কেবল লোকদের কাছে নিক্ষিপ্ত কোড নয়।
ভিনস

1
@ লুকক্রস প্যারেন্টফ্র্যাগমেন্টটি সেই টুকরা যা ডায়ালগফ্র্যাগমেন্ট তৈরি করে (যা দেখায় ()) তবে মনে হচ্ছে চাইল্ডফ্র্যাগমেন্ট ম্যানেজার পুনর্গঠন / স্ক্রিনের আবর্তনে বেঁচে নেই ...
iwat0qs

34

এই জিনিসটি করতে আমি এই সাধারণ পদক্ষেপগুলি অনুসরণ করেছি followed

  1. DialogFragmentCallbackInterfaceকিছু পদ্ধতির মত ইন্টারফেস তৈরি করুন callBackMethod(Object data)। যা আপনি কল করতে হবে ডেটা পাস।
  2. এখন আপনি DialogFragmentCallbackInterfaceআপনার খণ্ডের মতো ইন্টারফেস প্রয়োগ করতে পারেনMyFragment implements DialogFragmentCallbackInterface
  3. সময় DialogFragmentসৃষ্টি আপনার আবাহন টুকরা সেট MyFragmentলক্ষ্য টুকরা যিনি সৃষ্টি যেমন DialogFragmentব্যবহার myDialogFragment.setTargetFragment(this, 0)চেক setTargetFragment (অসম্পূর্ণ অংশ টুকরা, int- এ requestCode)

    MyDialogFragment dialogFrag = new MyDialogFragment();
    dialogFrag.setTargetFragment(this, 1); 
  4. আপনার টার্গেট টুকরা অবজেক্টটি DialogFragmentকল করে getTargetFragment()এটিতে কাস্ট করুন DialogFragmentCallbackInterfaceN

    DialogFragmentCallbackInterface callback = 
               (DialogFragmentCallbackInterface) getTargetFragment();
    callback.callBackMethod(Object data);

    সবই শেষ! কেবলমাত্র নিশ্চিত করুন যে আপনি এই ইন্টারফেসটি আপনার খণ্ডে প্রয়োগ করেছেন।


4
এটি সেরা উত্তর হওয়া উচিত। দুর্দান্ত উত্তর
মোঃ সাজেদুল করিম

উভয় উত্স এবং গন্তব্য টুকরা জন্য একই ফ্র্যাগমেন্ট ম্যানেজার ব্যবহার নিশ্চিত করুন, অন্যথায় getTargetFraਮੈਂਟ কাজ করবে না। সুতরাং যদি আপনি চাইল্ডফ্রেগমেন্ট ম্যানেজারটি ব্যবহার করেন তবে উত্স খণ্ডটি শিশু খণ্ড ব্যবস্থাপক দ্বারা প্রতিশ্রুতিবদ্ধ না হওয়ায় এটি কাজ করবে না। এই 2 টি টুকরোটিকে পিতামাতার / সন্তুর টুকরো না করে ভাইয়ের টুকরা হিসাবে ভাবা ভাল।
Thupten

সত্যই, 2 ভাইবোন খণ্ডের মধ্যে যোগাযোগ করার সময় কেবলমাত্র টার্গেট টুকরো টুকরো ব্যবহার করা ভাল। শ্রোতা না পেয়ে, আপনি দুর্ঘটনাক্রমে খণ্ড 2 এ ফ্রেগমেন্ট 1 ফাঁস করা এড়াতে পারেন। লক্ষ্য খণ্ড ব্যবহার করার সময়, শ্রোতা / কলব্যাক ব্যবহার করবেন না। কেবল onActivityResult(request code, resultcode, intent)টুকরা 1 এ ফলাফল ফেরত দিতে ব্যবহার করুন । ফ্রেগমেন্ট 1 setTargetFragment()এবং ফ্রেগমেন্ট 2 থেকে ব্যবহার করুন getTargetFragment()। অভিভাবক / সন্তানের টুকরো টুকরো টুকরো বা ক্রিয়াকলাপে ক্রিয়াকলাপটি ব্যবহার করার সময়, আপনি শ্রোতা বা কলব্যাক ব্যবহার করতে পারেন যেহেতু শিশু খণ্ডে পিতামাতার ফাঁস হওয়ার কোনও আশঙ্কা নেই।
Thupten

@ আপনি যখন "লিক" বলছেন তখন কি আপনার বোঝানো মেমরি ফুটো বা "ফাঁস বাস্তবায়নের বিশদ"? আমি মনে করি না বিজয়ের উত্তরটি রিটার্নের মূল্যের জন্য অ্যাক্টিভিটিস রিসাল্টিকে ব্যবহার করার চেয়ে স্মৃতি আর ফাঁস করবে। উভয় নিদর্শন লক্ষ্য টুকরা রেফারেন্স রাখা হবে। যদি আপনি বাস্তবায়নের বিশদটি ফাঁস করতে চান তবে আমি মনে করি যে তার প্যাটার্নটিঅ্যাক্টিভিটি রেজাল্টের চেয়ে আরও ভাল। কলব্যাক পদ্ধতিটি সুস্পষ্ট (সঠিকভাবে নাম দেওয়া থাকলে)। আপনি ফিরে পাওয়া সমস্ত যদি ঠিক থাকে এবং বাতিল হয় তবে প্রথম খণ্ডটির অর্থ কী তা বোঝাতে হবে।
tir38

34

হয়তো কিছুটা দেরি হয়ে গেছে, তবে আমি যেমন করেছি ঠিক একই প্রশ্নে অন্য মানুষকে সহায়তা করতে পারে।

আপনি ব্যবহার করতে পারেন setTargetFragmentউপর Dialogদেখানোর আগে, এবং ডায়ালগে আপনি কল করতে পারেন getTargetFragmentরেফারেন্স জন্য।


এখানে আরেকটি প্রশ্নের উত্তর হয় কিন্তু এটি আপনার প্রশ্নের জন্য প্রযোজ্য এবং একটি পরিষ্কার সমাধান: stackoverflow.com/questions/28620026/...
user2288580

IllegalStateException আমাকে
ক্রস লুক

19

যোগাযোগ অন্য টুকরা সঙ্গে নির্দেশিকা টুকরা উচিত বলে সংশ্লিষ্ট সক্রিয়তার মাধ্যমে যোগাযোগ

প্রায়শই আপনি একটি ফ্রেগমেন্টের সাথে অন্যটির সাথে যোগাযোগ করতে চান, উদাহরণস্বরূপ কোনও ব্যবহারকারীর ইভেন্টের উপর ভিত্তি করে সামগ্রী পরিবর্তন করতে change সম্পর্কিত সমস্ত ক্রিয়াকলাপের মাধ্যমে সমস্ত খণ্ড-টু-খণ্ড যোগাযোগ করা হয়। দুটি খণ্ডের সরাসরি যোগাযোগ করা উচিত নয়।


1
অভ্যন্তরীণ টুকরোগুলি সম্পর্কে যেমন, অন্য খণ্ডের মধ্যে একটি খণ্ড কীভাবে হোস্ট টুকরাটিতে যোগাযোগ করা উচিত
রবি

@ রবি: প্রতিটি খণ্ডকে সেই ক্রিয়াকলাপের সাথে যোগাযোগ করা উচিত যা getActivity () কল করে সমস্ত অংশে সাধারণ ।
এডওয়ার্ড ব্রে

1
@ ক্রিস: যদি টুকরোগুলি চলমান যোগাযোগের প্রয়োজন হয় তবে প্রতিটি উপযুক্ত খণ্ডকে প্রয়োগের জন্য একটি ইন্টারফেস নির্ধারণ করুন। ক্রিয়াকলাপের কাজটি তখন তাদের অংশের অংশগুলিতে ইন্টারফেস পয়েন্টার সহ টুকরো সরবরাহের মধ্যে সীমাবদ্ধ। এর পরে, টুকরোগুলি ইন্টারফেসের মাধ্যমে নিরাপদে "সরাসরি" যোগাযোগ করতে পারে।
এডওয়ার্ড ব্রে

3
আমি ভাবি যে খণ্ডগুলির ব্যবহারগুলি সরাসরি খণ্ড যোগাযোগ না ভাঙার মূল ধারণাটি প্রসারিত হয়েছে। যেমন কোনও নেভিগেশন ড্রয়ারে ক্রিয়াকলাপের প্রতিটি তাত্ক্ষণিক শিশু খণ্ড মোটামুটি একটি কার্যকলাপ হিসাবে কাজ করে as সুতরাং ক্রিয়াকলাপের মাধ্যমে একটি ডায়লগফ্র্যাগমেন্ট যোগাযোগের মতো একটি অংশ থাকা পঠনযোগ্যতা / নমনীয়তা আইএমওকে ক্ষতি করে। বাস্তবে এটি পুনরায় ব্যবহারযোগ্য উপায়ে ক্রিয়াকলাপ এবং টুকরা উভয়কেই কাজ করার মঞ্জুরি দেওয়ার জন্য ডায়লগফ্র্যাগমেন্টটি এনপ্যাপুলেট করার কোনও দুর্দান্ত উপায় বলে মনে হয় না।
স্যাম

16
আমি জানি এটি পুরানো, তবে অন্য কেউ যদি এখানে আসেন তবে আমার মনে হয় যে ডায়ালগফ্র্যাগমেন্টটি তৈরি এবং পরিচালনা নির্ধারণের জন্য যখন একটি খণ্ড যুক্তির "মালিকানাধীন" যুক্তিটি ব্যবহার করে তখন সেই নথিতে যে মামলাটি প্রযোজ্য তা প্রযোজ্য না। ক্রিয়াকলাপটি খণ্ড থেকে ক্রিয়াকলাপে সংযোগের একগুচ্ছ তৈরি করার জন্য এ ধরণের উদ্ভট ঘটনা যখন ক্রিয়াকলাপটি কেন নিশ্চিত হয় না যে কোনও ডায়ালগ কেন তৈরি হচ্ছে বা কোন পরিস্থিতিতে এটি খারিজ করা উচিত isn't এ ছাড়া ডায়ালগফ্রেগমেন্টটি অতি সাধারণ, এবং এটি কেবলমাত্র ব্যবহারকারীকে অবহিত করতে এবং সম্ভাব্য প্রতিক্রিয়া জানাতেই বিদ্যমান exists
ক্রিস

12

interfaceআপনার নিজের খণ্ড শ্রেণিতে একটি সংজ্ঞায়িত করা উচিত এবং সেই ইন্টারফেসটিকে এর মূল কার্যকলাপে প্রয়োগ করা উচিত । বিবরণ এখানে রূপরেখা আছে http://developer.android.com/guide/components/fragments.html#EventCallbacks । কোডটি দেখতে অনুরূপ হবে:

টুকরা:

public static class FragmentA extends DialogFragment {

    OnArticleSelectedListener mListener;

    // Container Activity must implement this interface
    public interface OnArticleSelectedListener {
        public void onArticleSelected(Uri articleUri);
    }

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

কার্যক্রম:

public class MyActivity extends Activity implements OnArticleSelectedListener{

    ...
    @Override
    public void onArticleSelected(Uri articleUri){

    }
    ...
}

1
আমি মনে করি আপনি খুব শীঘ্রই ডকস স্কিম করেছেন। এই উভয় কোড বিভাগই FragmentAহ'ল এবং তিনি ধরে OnArticleSelectedListenerনিচ্ছেন যে কোনও ক্রিয়াকলাপ হ'ল একটি ফ্রেগমেন্ট নয় যে তাকে শুরু করেছিল him
চিরকালীন

2
আপনি খারাপ অভ্যাস করার চেষ্টা করছেন তা আমি বিবেচনা করব। অ্যান্ড্রয়েড নির্দেশিকা সুপারিশ করে যে সমস্ত টুকরা টুকর টুকরো যোগাযোগ ক্রিয়াকলাপের মাধ্যমে হয় (প্রতি বিকাশকারী / অ্যান্ড্রয়েড / ট্রেনিং / বেসিক্স / ফ্রেমস / )) through আপনি যদি সত্যিই এই সমস্ত কিছু পরিচালনা MyFragmentকরতে চান তবে আপনি নিয়মিত ব্যবহার করতে যেতে চানAlertDialog
জেমস ম্যাকক্র্যাকেন

1
আমি মনে করি খণ্ডগুলি একে অপরের সাথে সরাসরি কথা বলার সাথে উদ্বেগটি হ'ল যে কোনও কোনও বিন্যাসে সমস্ত টুকরোগুলি লোড করা যায় না এবং উদাহরণ হিসাবে তারা দেখায় যে খণ্ডে স্যুইচ করা প্রয়োজন হতে পারে। কোনও খণ্ড থেকে ডায়ালগ খণ্ড খোলার কথা বলার সময় আমি এই উদ্বেগটি বৈধ বলে মনে করি না।

আমি আমার ক্রিয়াকলাপের জন্য এটি প্রয়োগ করেছি। প্রশ্ন: এই সমাধানটি কি এত বাড়ানো যেতে পারে যে কোনও খণ্ড এই সংলাপটি ইনস্ট্যান্ট করতে পারে?
বিল মোটে

1
এটি একটি স্থাপত্য দৃষ্টিকোণ থেকে একটি ভাল অনুশীলন, এবং যেমন গ্রহণযোগ্য উত্তর হওয়া উচিত। অ্যাক্টিভিটিআরসাল্ট ব্যবহার করে স্প্যাগেটি আর্কিটেকচার বাড়ে
ব্রুনো ক্যারিয়ার

4

শ্রোতাকে কোনও খণ্ডে সেট করার সঠিক উপায়টি এটি সংযুক্ত হওয়ার সাথে সাথে সেট করে । আমার যে সমস্যাটি হয়েছিল তা হচ্ছিল যে অনাটচফ্রেগমেন্ট () কখনই কল করা হয়নি। কিছু তদন্তের পরে আমি বুঝতে পারি যে আমি getChildFragmentManager এর পরিবর্তে getFragmentManager ব্যবহার করছিলাম

এখানে আমি এটি কীভাবে করছি:

MyDialogFragment dialogFragment = MyDialogFragment.newInstance("title", "body");
dialogFragment.show(getChildFragmentManager(), "SOME_DIALOG");

এটিআটাচ ফ্রেমে এটি সংযুক্ত করুন:

@Override
public void onAttachFragment(Fragment childFragment) {
    super.onAttachFragment(childFragment);

    if (childFragment instanceof MyDialogFragment) {
        MyDialogFragment dialog = (MyDialogFragment) childFragment;
        dialog.setListener(new MyDialogFragment.Listener() {
            @Override
            public void buttonClicked() {

            }
        });
    }
}

3

সরকারী ডকুমেন্টেশন অনুযায়ী:

অসম্পূর্ণ অংশ # setTargetFragment

এই খণ্ডটির জন্য targetচ্ছিক লক্ষ্য। এটি ব্যবহার করা যেতে পারে, উদাহরণস্বরূপ, যদি এই খণ্ডটি অন্য কোনও দ্বারা শুরু করা হয়, এবং যখন সম্পন্ন হয় তখন প্রথমটিকে কোনও ফলাফল দিতে চায়। এখানে সেট করা লক্ষ্যটি ফ্র্যাগমেন্টম্যানেজার # পুটফ্রেগমেন্টের মাধ্যমে দৃষ্টান্ত জুড়ে ধরে রাখা হয়েছে।

অসম্পূর্ণ অংশ # getTargetFragment

টার্গেটফ্র্যাগমেন্ট (ফ্রেগমেন্ট, ইনট) দ্বারা সেট করা টার্গেটের টুকরাটি ফিরিয়ে দিন।

সুতরাং আপনি এটি করতে পারেন:

// In your fragment

public class MyFragment extends Fragment implements OnClickListener {
    private void showDialog() {
        DialogFragment dialogFrag = MyDialogFragment.newInstance(this);
        // Add this
        dialogFrag.setTargetFragment(this, 0);
        dialogFrag.show(getFragmentManager, null);
    }
    ...
}

// then

public class MyialogFragment extends DialogFragment {
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        // Then get it
        Fragment fragment = getTargetFragment();
        if (fragment instanceof OnClickListener) {
            listener = (OnClickListener) fragment;
        } else {
            throw new RuntimeException("you must implement OnClickListener");
        }
    }
    ...
}

আপনি আপনার ব্যাখ্যা করতে পারেন?
ইলমাজ

এক্ষেত্রে আমাদের "মাইফ্রেগমেন্ট" "মায়ালোগফ্র্যাগমেন্ট" এর সাথে সম্পর্কিত হওয়া দরকার এবং "খণ্ড" এটি করার পদ্ধতি সরবরাহ করে। আমি সরকারী দস্তাবেজের বিবরণ যুক্ত করেছি, এটি আমার চেয়ে আরও স্পষ্টভাবে বলা উচিত।
সুপারিও

2

আমিও একই ধরণের সমস্যার মুখোমুখি হয়েছি। আমি যে সমাধানটি খুঁজে পেয়েছি তা হ'ল:

  1. আপনার ডায়ালগফ্রেগমেন্টে একটি ইন্টারফেস ঘোষণা করুন ঠিক যেমনটি জেমস ম্যাকক্র্যাকেন উপরে ব্যাখ্যা করেছেন।

  2. আপনার ক্রিয়াকলাপে ইন্টারফেসটি প্রয়োগ করুন (খণ্ড না! এটি একটি ভাল অনুশীলন নয়)।

  3. আপনার ক্রিয়াকলাপের কলব্যাক পদ্ধতি থেকে আপনার খণ্ডে একটি প্রয়োজনীয় পাবলিক ফাংশন কল করুন যা আপনি করতে চান এমন কাজটি করে does

সুতরাং, এটি একটি দ্বি-পদক্ষেপ প্রক্রিয়াতে পরিণত হয়: ডায়ালগফ্রেগমেন্ট -> ক্রিয়াকলাপ এবং তারপরে ক্রিয়াকলাপ -> খণ্ড


1

আমি ফ্রেগমেন্ট লাইভওয়ালফিল্টারফ্র্যাগমেন্ট (ফ্র্যাগমেন্ট গ্রহণ করে) এর ফ্রেগমেন্ট ড্যাশবোর্ড লাইভওয়াল (কলিং ফ্রেগমেন্ট) এর ফলাফল পাচ্ছি ... এর মতো ...

 LiveWallFilterFragment filterFragment = LiveWallFilterFragment.newInstance(DashboardLiveWall.this ,"");

 getActivity().getSupportFragmentManager().beginTransaction(). 
 add(R.id.frame_container, filterFragment).addToBackStack("").commit();

কোথায়

public static LiveWallFilterFragment newInstance(Fragment targetFragment,String anyDummyData) {
        LiveWallFilterFragment fragment = new LiveWallFilterFragment();
        Bundle args = new Bundle();
        args.putString("dummyKey",anyDummyData);
        fragment.setArguments(args);

        if(targetFragment != null)
            fragment.setTargetFragment(targetFragment, KeyConst.LIVE_WALL_FILTER_RESULT);
        return fragment;
    }

setResult কল্ট ফলের মত ফিরে

private void setResult(boolean flag) {
        if (getTargetFragment() != null) {
            Bundle bundle = new Bundle();
            bundle.putBoolean("isWorkDone", flag);
            Intent mIntent = new Intent();
            mIntent.putExtras(bundle);
            getTargetFragment().onActivityResult(getTargetRequestCode(),
                    Activity.RESULT_OK, mIntent);
        }
    }

onActivityResult

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode == Activity.RESULT_OK) {
            if (requestCode == KeyConst.LIVE_WALL_FILTER_RESULT) {

                Bundle bundle = data.getExtras();
                if (bundle != null) {

                    boolean isReset = bundle.getBoolean("isWorkDone");
                    if (isReset) {

                    } else {
                    }
                }
            }
        }
    }

1

আপডেট করা হয়েছে:

আমি আমার গিস্ট কোডের উপর ভিত্তি করে একটি লাইব্রেরি তৈরি করেছি যা ব্যবহার করে @CallbackFragmentএবং আপনার জন্য thoseালাই তৈরি করে @Callback

https://github.com/zeroarst/callbackframent

এবং উদাহরণটি আপনাকে উদাহরণ দেয় যা একটি খণ্ড থেকে অন্য খণ্ডে কলব্যাক প্রেরণ করে।

পুরানো উত্তর:

আমি একটি BaseCallbackFragmentএবং টীকা দিয়েছি @FragmentCallback। এটি বর্তমানে প্রসারিত হয়েছে Fragment, আপনি এটিকে পরিবর্তন করতে পারেন DialogFragmentএবং কাজ করবে। এটি নিম্নলিখিত আদেশের সাথে প্রয়োগগুলি পরীক্ষা করে: getTargetFraament ()> getParentFraament ()> প্রসঙ্গ (ক্রিয়াকলাপ)।

তারপরে আপনাকে কেবল এটি প্রসারিত করতে হবে এবং আপনার ইন্টারফেসগুলি আপনার খণ্ডগুলিতে ঘোষণা করতে হবে এবং এটিকে টীকা দেবে এবং বেস খণ্ডটি বাকী অংশটি করবে। mandatoryআপনি খণ্ডটি কলব্যাকটি প্রয়োগ করতে বাধ্য করতে চান কিনা তা নির্ধারণ করার জন্য টীকাতেও আপনার পরামিতি রয়েছে ।

public class EchoFragment extends BaseCallbackFragment {

    private FragmentInteractionListener mListener;

    @FragmentCallback
    public interface FragmentInteractionListener {
        void onEcho(EchoFragment fragment, String echo);
    }
}

https://gist.github.com/zeroarst/3b3f32092d58698a4568cdb0919c9a93


1

কোটলিনের ছেলেরা এখানে আমরা যাই!

সুতরাং আমাদের যে সমস্যাটি রয়েছে তা হ'ল আমরা একটি ক্রিয়াকলাপ তৈরি করেছি MainActivity, সেই ক্রিয়াকলাপের উপর আমরা একটি খণ্ড FragmentAতৈরি করেছি এবং এখন আমরা FragmentAকল করার উপরে একটি ডায়ালগ খণ্ড তৈরি করতে চাই FragmentB। আমরা কীভাবে FragmentBপিছন থেকে FragmentAনা পেরে ফলাফল পেতে পারি MainActivity?

বিঃদ্রঃ:

  1. FragmentAএকটি শিশু টুকরা MainActivity। তৈরি করা টুকরোগুলি পরিচালনা করতে FragmentAআমরা ব্যবহার করব childFragmentManagerযা করে!
  2. FragmentAএকটি পিতা বা মাতা টুকরা হয় FragmentB, অ্যাক্সেস করতে FragmentAভিতর থেকে FragmentBআমরা ব্যবহার করবে parenFragment

এই বলে, ভিতরে FragmentA,

class FragmentA : Fragment(), UpdateNameListener {
    override fun onSave(name: String) {
        toast("Running save with $name")
    }

    // call this function somewhere in a clickListener perhaps
    private fun startUpdateNameDialog() {
        FragmentB().show(childFragmentManager, "started name dialog")
    }
}

এখানে ডায়ালগ খণ্ড রয়েছে FragmentB

class FragmentB : DialogFragment() {

    private lateinit var listener: UpdateNameListener

    override fun onAttach(context: Context) {
        super.onAttach(context)
        try {
            listener = parentFragment as UpdateNameListener
        } catch (e: ClassCastException) {
            throw ClassCastException("$context must implement UpdateNameListener")
        }
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return activity?.let {
            val builder = AlertDialog.Builder(it)
            val binding = UpdateNameDialogFragmentBinding.inflate(LayoutInflater.from(context))
            binding.btnSave.setOnClickListener {
                val name = binding.name.text.toString()
                listener.onSave(name)
                dismiss()
            }
            builder.setView(binding.root)
            return builder.create()
        } ?: throw IllegalStateException("Activity can not be null")
    }
}

এখানে ইন্টারফেসটি দুটিকে সংযুক্ত করছে।

interface UpdateNameListener {
    fun onSave(name: String)
}

এটাই.


1
আমি এই দস্তাবেজটি অনুসরণ করেছি: developer.android.com/guide/topics/ui/dialogs এবং এটি কার্যকর হয়নি। তোমাকে অনেক ধন্যবাদ. আমি আশা করি এই প্যারেন্টফ্র্যাগমেন্ট বিষয়টি প্রতিবার প্রত্যাশার মতো কাজ করে :)
উমুতটেকিন

1
শ্রোতাদের অনুলিপি ভিতরে ডেটে সেট করতে ভুলবেন না :)
বেকবট

@ বেকাবোট মন্তব্যটির জন্য ধন্যবাদ। আমি কিছু গবেষণা করেছি এবং এটি শ্রোতাদের বন্ধ করার প্রয়োজন নেই বলে মনে হয়। stackoverflow.com/a/37031951/10030693
Ssenyonjo

0

আমি এটি RxAndroid এর সাথে মার্জিত উপায়ে সমাধান করেছি। ডায়ালগফ্রেগমেন্টের কনস্ট্রাক্টরে একটি পর্যবেক্ষক পান এবং পর্যবেক্ষণযোগ্য হিসাবে গ্রাহক হন এবং কলব্যাক কল করার সময় মানটিকে চাপ দিন। তারপরে, আপনার খণ্ডে পর্যবেক্ষকের একটি অভ্যন্তরীণ শ্রেণি তৈরি করুন, একটি উদাহরণ তৈরি করুন এবং এটি ডায়ালগফ্র্যাগমেন্টের নির্মাত্রে পাস করুন। আমি মেমরি ফাঁস এড়াতে পর্যবেক্ষকগুলিতে WeakReferences ব্যবহার করেছি। কোডটি এখানে:

BaseDialogFragment.java

import java.lang.ref.WeakReference;

import io.reactivex.Observer;

public class BaseDialogFragment<O> extends DialogFragment {

    protected WeakReference<Observer<O>> observerRef;

    protected BaseDialogFragment(Observer<O> observer) {
        this.observerRef = new WeakReference<>(observer);
   }

    protected Observer<O> getObserver() {
    return observerRef.get();
    }
}

DatePickerFragment.java

public class DatePickerFragment extends BaseDialogFragment<Integer>
    implements DatePickerDialog.OnDateSetListener {


public DatePickerFragment(Observer<Integer> observer) {
    super(observer);
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    // Use the current date as the default date in the picker
    final Calendar c = Calendar.getInstance();
    int year = c.get(Calendar.YEAR);
    int month = c.get(Calendar.MONTH);
    int day = c.get(Calendar.DAY_OF_MONTH);

    // Create a new instance of DatePickerDialog and return it
    return new DatePickerDialog(getActivity(), this, year, month, day);
}

@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
        if (getObserver() != null) {
            Observable.just(month).subscribe(getObserver());
        }
    }
}

MyFragment.java

//Show the dialog fragment when the button is clicked
@OnClick(R.id.btn_date)
void onDateClick() {
    DialogFragment newFragment = new DatePickerFragment(new OnDateSelectedObserver());
    newFragment.show(getFragmentManager(), "datePicker");
}
 //Observer inner class
 private class OnDateSelectedObserver implements Observer<Integer> {

    @Override
    public void onSubscribe(Disposable d) {

    }

    @Override
    public void onNext(Integer integer) {
       //Here you invoke the logic

    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onComplete() {

    }
}

আপনি উত্স কোডটি এখানে দেখতে পাবেন: https://github.com/andresuarezz26/carpoolingapp


1
অ্যান্ড্রয়েড সম্পর্কে মজার বিষয় হ'ল জীবনচক্র বলে কিছু আছে। বেস খণ্ড বা কথোপকথন খণ্ডকে জীবনচক্রের ইভেন্টগুলির থেকে রাষ্ট্র (এবং তাদের সংযোগ) সংরক্ষণ করতে সক্ষম হওয়া দরকার। কলব্যাক বা পর্যবেক্ষককে সিরিয়ালযুক্ত করা যায় না এবং তাই এখানে একই সমস্যা রয়েছে।
জিডাঙ্গার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.