এমন কোনও পদ্ধতি আছে যা ফলাফলের জন্য প্রারম্ভিক খণ্ডের মতো কাজ করে?


95

আমার বর্তমানে একটি ওভারলেতে টুকরো টুকরো রয়েছে। এটি পরিষেবাতে সাইন ইন করার জন্য। ফোন অ্যাপ্লিকেশনে, ওভারলেতে আমি যে ধাপগুলি প্রদর্শন করতে চাই তার প্রতিটি সেগুলির নিজস্ব পর্দা এবং ক্রিয়াকলাপ। সাইন-ইন প্রক্রিয়াটির 3 টি অংশ রয়েছে এবং প্রত্যেকের নিজস্ব ক্রিয়াকলাপ ছিল যা স্টার্টএটিভিটি ফর রিসাল্ট () দিয়ে ডাকা হয়েছিল।

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

উত্তর:


58

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

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


11
অন্য একটি থেকে অন্য খণ্ড লোড করার সময় আপনি লক্ষ্য টুকরা সেট করতে পারেন এবং onActivityResultআপনি যদি চান তবে পিতামৃত খণ্ডনের পদ্ধতিতে কল করতে পারেন।
পিজেএল

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

4
ঠিক আছে, 'ফলাফলের জন্য প্রারম্ভিক খণ্ডটি' কল করা অর্থহীন হবে যেহেতু এটি আরও বেশি নমনীয়তা দেবে -> শিশু হিসাবে খণ্ড খণ্ডটি কেন তার পিতামাতার সম্পর্কে জানতে হবে? খণ্ডটি কেবলমাত্র তার কাজটি করার জন্য খুব পরিষ্কার পরিচ্ছন্ন হবে না এবং যে কার্যকলাপে থাকছেন না কেন তার ফলাফলটি ফিরে আসুন। বিশেষত একক ক্রিয়াকলাপের অ্যাপ্লিকেশনগুলির প্রসঙ্গে।
দানিজেলা

সম্ভাব্য স্মৃতি ফাঁস সম্পর্কে কী?
দানিজেলা

60

আপনি যদি চান, খণ্ডগুলির মধ্যে যোগাযোগের জন্য কিছু পদ্ধতি রয়েছে,

setTargetFragment(Fragment fragment, int requestCode)
getTargetFragment()
getTargetRequestCode()

এগুলি ব্যবহার করে আপনি কলব্যাক করতে পারেন।

Fragment invoker = getTargetFragment();
if(invoker != null) {
    invoker.callPublicMethod();
}

আমি এটি নিশ্চিত করি নি, তবে সম্ভবত এটি কার্যকর হয়। সুতরাং, আপনার অপব্যবহারের মাধ্যমে বিজ্ঞপ্তি রেফারেন্স দ্বারা সৃষ্ট মেমরি ফুটো সম্পর্কে যত্ন নেওয়া উচিত setTargetFragment()
nagoya0

4
এখন পর্যন্ত সেরা সমাধান! একটি ক্রিয়াকলাপ এবং টুকরো টুকরো থাকার সময় দুর্দান্ত কাজ করে যেখানে অবহিত করার জন্য সঠিক খণ্ডটি অনুসন্ধান করার চেষ্টা করা দুঃস্বপ্ন হতে পারে। ধন্যবাদ
দামিয়েন প্রকা

4
@ ব্যবহারকারীর সেভেন 7 গুলি এটি প্রতিস্থাপনের ক্ষেত্রে কাজ করবে না তবে লুকানো মামলার জন্য কাজ করা উচিত
মুহাম্মদ বাবর

4
@ নাগোয়া0 এটি আরও ভাল করে যদি আমরা লক্ষ্য খণ্ডের জন্য দুর্বল রেফারেন্স ব্যবহার করি
কোয়াংসন ৯৯১

এটি কাজ করার সময়, setTargetFragmentবর্তমানে হ্রাস করা হয়। দেখুন setResultListenerstackoverflow.com/a/61881149/2914140 এখানে।
কুলমাইন্ড

11

আমরা খণ্ডগুলির মধ্যে কেবল একই ভিউমোডেলটি ভাগ করতে পারি

শেয়ারডভিউমোডেল

import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.ViewModel

class SharedViewModel : ViewModel() {

    val stringData: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }

}

ফার্স্টফ্র্যাগমেন্ট

import android.arch.lifecycle.Observer
import android.os.Bundle
import android.arch.lifecycle.ViewModelProviders
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

class FirstFragment : Fragment() {

    private lateinit var sharedViewModel: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        activity?.run {
            sharedViewModel = ViewModelProviders.of(activity).get(SharedViewModel::class.java)
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_first, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        sharedViewModel.stringData.observe(this, Observer { dateString ->
            // get the changed String
        })

    }

}

সেকেন্ডফ্র্যাগমেন্ট

import android.arch.lifecycle.ViewModelProviders
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGrou

class SecondFragment : Fragment() {

    private lateinit var sharedViewModel: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        activity?.run {
            sharedViewModel = ViewModelProviders.of(activity).get(SharedViewModel::class.java)
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_first, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        changeString()
    }

    private fun changeString() {
        sharedViewModel.stringData.value = "Test"
    }

}

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

@ শৈলেন্দ্রপতিল ভাল লাগছে, আমি এখনই এটি ঠিক করে দেব।
লেভন পেট্রোসায়ান

7

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

খণ্ড শুরু হচ্ছে।

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Use the Kotlin extension in the fragment-ktx artifact
    setResultListener("requestKey") { key, bundle ->
        // We use a String here, but any type that can be put in a Bundle is supported
        val result = bundle.getString("bundleKey")
        // Do something with the result...
    }
}

একটি খণ্ড যা আমরা ফলাফলটি ফিরে চাই।

button.setOnClickListener {
    val result = "result"
    // Use the Kotlin extension in the fragment-ktx artifact
    setResult("requestKey", bundleOf("bundleKey" to result))
}

স্নিপেট গুগলের অফিসিয়াল ডকুমেন্টস থেকে নেওয়া হয়েছে। https://developer.android.com/training/basics/frations/pass-data-between#kotlin

এই উত্তরটি লেখার তারিখে, এই বৈশিষ্ট্যটি এখনও রয়ে গেছে alpha। আপনি এই নির্ভরতা ব্যবহার করে চেষ্টা করে দেখতে পারেন।

androidx.fragment:fragment:1.3.0-alpha05

4

আমার 2 সেন্ট।

আমি একটি পুরানো টুকরাটি নতুনের সাথে গোপন এবং প্রদর্শন / যুক্ত (বিদ্যমান / নতুন) ব্যবহার করে অদলবদল করে টুকরোগুলির মধ্যে স্যুইচ করি। সুতরাং এই উত্তরটি ডেভস যারা আমার মতো টুকরা ব্যবহার করেন তাদের পক্ষে use

তারপরে আমি onHiddenChangedপদ্ধতিটি ব্যবহার করে জানতে পারি যে পুরানো টুকরাটি নতুন থেকে ফিরে এসেছে। নীচে কোড দেখুন।

নতুন টুকরাটি ছাড়ার আগে, আমি পুরানো খণ্ডটি জিজ্ঞাসা করে বিশ্বব্যাপী প্যারামিটারে একটি ফলাফল সেট করেছিলাম। এটি একটি খুব নিষ্পাপ সমাধান।

@Override
public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);
    if (hidden) return;
    Result result = Result.getAndReset();
    if (result == Result.Refresh) {
        refresh();
    }
}

public enum Result {
    Refresh;

    private static Result RESULT;

    public static void set(Result result) {
        if (RESULT == Refresh) {
            // Refresh already requested - no point in setting anything else;
            return;
        }
        RESULT = result;
    }

    public static Result getAndReset() {
        Result result = RESULT;
        RESULT = null;
        return result;
    }
}

getAndReset()পদ্ধতি কী ?
এপিকপান্ডাফোরস

এছাড়াও নয় onResume()প্রথম টুকরা আহ্বান যখন দ্বিতীয় বরখাস্ত করা হয়?
পিজে_ফিনেগান

2

আপনার খণ্ডে আপনি getActivity () কল করতে পারেন। এটি আপনাকে সেই ক্রিয়াকলাপে অ্যাক্সেস দেবে যা খণ্ডটি তৈরি করেছে। সেখান থেকে আপনি মানগুলি সেট করতে বা মানগুলি পাস করার জন্য আপনার কাস্টমাইজ পদ্ধতিটিকে কল করতে পারেন।


1

একটি অ্যান্ড্রয়েড গ্রন্থাগার রয়েছে - ফ্লোআর যা আপনাকে ফলাফলের জন্য টুকরো টুকরো শুরু করতে দেয়।

ফলাফলের জন্য একটি খণ্ড শুরু করা হচ্ছে।

Flowr.open(RequestFragment.class)
    .displayFragmentForResults(getFragmentId(), REQUEST_CODE);

কলিং খণ্ডে ফলাফল হ্যান্ডলিং

@Override
protected void onFragmentResults(int requestCode, int resultCode, Bundle data) {
    super.onFragmentResults(requestCode, resultCode, data);

    if (requestCode == REQUEST_CODE) {
        if (resultCode == Activity.RESULT_OK) {
            demoTextView.setText("Result OK");
        } else {
            demoTextView.setText("Result CANCELED");
        }
    }
}

খণ্ডে ফলাফল নির্ধারণ করা।

Flowr.closeWithResults(getResultsResponse(resultCode, resultData));

1

ইন্টারফেস (এবং কোটলিন) ব্যবহার করে একটি সমাধান। মূল ধারণাটি হ'ল একটি কলব্যাক ইন্টারফেসকে সংজ্ঞায়িত করা, এটি আপনার ক্রিয়াকলাপে এটি প্রয়োগ করা, তারপরে আপনার খণ্ড থেকে কল করুন।

প্রথমে একটি ইন্টারফেস তৈরি করুন ActionHandler:

interface ActionHandler {
    fun handleAction(actionCode: String, result: Int)
}

এরপরে, আপনার সন্তানের কাছ থেকে এটিকে কল করুন (এই ক্ষেত্রে আপনার খণ্ড):

companion object {
    const val FRAGMENT_A_CLOSED = "com.example.fragment_a_closed"
}

fun closeFragment() {
    try {
        (activity as ActionHandler).handleAction(FRAGMENT_A_CLOSED, 1234)
    } catch (e: ClassCastException) {
        Timber.e("Calling activity can't get callback!")
    }
    dismiss()
}

শেষ অবধি, কলব্যাকটি পেতে আপনার পিতামাতার মধ্যে এটি প্রয়োগ করুন (এই ক্ষেত্রে, আপনার কার্যকলাপ):

class MainActivity: ActionHandler { 
    override fun handleAction(actionCode: String, result: Int) {
        when {
            actionCode == FragmentA.FRAGMENT_A_CLOSED -> {
                doSomething(result)
            }
            actionCode == FragmentB.FRAGMENT_B_CLOSED -> {
                doSomethingElse(result)
            }
            actionCode == FragmentC.FRAGMENT_C_CLOSED -> {
                doAnotherThing(result)
            }
        }
    }

0

ডেটা ফেরত দেওয়ার সহজতম উপায় হ'ল সেটআর্গমেন্ট ()। উদাহরণস্বরূপ, আপনার ফ্রেগমেন্ট 1 রয়েছে যা ফ্রেগমেন্ট 2 কে কল করে যা ফ্রেগমেন্ট 3, ফ্র্যাগমেন্ট 1 -> ফ্রেমনেট 2 -> ফরগমেন্ট 3

খণ্ডে 1

public void navigateToFragment2() {
    if (fragmentManager == null) return;

    Fragment2 fragment = Fragment2.newInstance();
    String tag = "Fragment 2 here";
    fragmentManager.beginTransaction()
            .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
            .add(R.id.flContent, fragment, tag)
            .addToBackStack(null)
            .commitAllowingStateLoss();
}

ফ্রেগমেন্ট 2 এ আমরা যথারীতি ফ্রেগমেন্ট 3 কল করি

private void navigateToFragment3() {
    if (fragmentManager == null) return;
    Fragment3 fragment = new Fragment3();
    fragmentManager.beginTransaction()
            .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
            .replace(R.id.flContent, fragment, tag)
            .addToBackStack(null)
            .commit();
}

যখন আমরা খণ্ড 3 এ আমাদের কাজ শেষ করি এখন আমরা এটিকে কল করি:

FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
if (fragmentManager == null) return;
fragmentManager.popBackStack();
Bundle bundle = new Bundle();
bundle.putString("bundle_filter", "data");
fragmentManager.findFragmentByTag("Fragment 2 here").setArguments(bundle);

এখন খণ্ড 2 এ আমরা সহজেই আর্গুমেন্টগুলি কল করতে পারি

@Override
public void onResume() {
    super.onResume();
    Bundle rgs = getArguments();
    if (args != null) 
        String data = rgs.getString("bundle_filter");
}

এটির সাথে সাবধানতা অবলম্বন করুন, এটি কিছু ক্ষেত্রে কার্যকর হতে পারে তবে যদি আপনার খণ্ডটির মূল যুক্তি (এই উদাহরণে 'টুকরা 2') থাকে তবে এটি খণ্ডটি তৈরি করতে ব্যবহৃত মূল আর্গুমেন্টগুলিকে ওভাররাইড করে, যা যদি কোনও বেমানান অবস্থার দিকে পরিচালিত করতে পারে তবে খণ্ডটি ধ্বংস এবং পুনরায় তৈরি করা হয়।
জুয়ান

0

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

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.