ফলাফল ফেরত

Navigation 3 1.2.0 সংস্করণ থেকে, আপনি ResultEventBus API ব্যবহার করে গন্তব্যস্থল থেকে ফলাফল ফেরত আনতে পারবেন।

ResultEventBus দুটি যোগাযোগ মডেল প্রদান করে:

  • ইভেন্ট-ভিত্তিক ফলাফল : ResultEffect ব্যবহার করে ক্ষণস্থায়ী, এককালীন ইভেন্টের (যেমন একটি কনফার্মেশন স্নাকবার দেখানো বা কোনো সাইড ইফেক্ট ট্রিগার করা) জন্য।
  • স্টেট-ভিত্তিক ফলাফল : conflateAsState ব্যবহার করে কম্পোজ State হিসেবে সর্বশেষ ফলাফল পর্যবেক্ষণ করার জন্য।

ফলাফল ইভেন্ট বাস সেট আপ করুন

আপনার কম্পোজেবল ডেস্টিনেশনগুলিতে ResultEventBus উপলব্ধ করতে, আপনার NavDisplay তে পাস করা ডেকোরেটরগুলির তালিকায় rememberResultEventBusNavEntryDecorator যোগ করুন। এটি প্রতিটি ডেস্টিনেশনের কন্টেন্টকে একটি LocalResultEventBus কম্পোজিশন লোকাল প্রদান করে।

NavDisplay(
    /* ... */
    entryDecorators = listOf(
        rememberSaveableStateHolderNavEntryDecorator(),
        rememberResultEventBusNavEntryDecorator()
    )
)

ফলাফলের চাবিগুলি

ResultEventBus একটি কী ব্যবহার করে প্রতিটি ফলাফল শনাক্ত ও রাউট করে। প্রেরক এবং প্রাপক একই কী ব্যবহার করে ফলাফল মেলায়।

আপনি দুইভাবে ফলাফল কী নির্দিষ্ট করতে পারেন:

  • সুস্পষ্ট কী : আপনি একটি সুস্পষ্ট কী নির্দিষ্ট করতে পারেন (যেমন resultKey = "pickup_address" )। সাধারণ টাইপ (যেমন String , Boolean , বা প্রিমিটিভ) রিটার্ন করার সময়, অথবা যখন একাধিক গন্তব্য একই ডেটা টাইপের ভিন্ন ভিন্ন ইনস্ট্যান্স রিটার্ন করে, তখন সুস্পষ্ট কী ব্যবহার করুন।
  • টাইপ-ডিরাইভড কী : যখন আপনি কোনো সুস্পষ্ট কী নির্দিষ্ট করেন না, তখন ResultEventBus স্বয়ংক্রিয়ভাবে রেজাল্ট টাইপের KClass এর toString রিপ্রেজেন্টেশন ব্যবহার করে একটি কী তৈরি করে (যেমন Contact::class.toString() )। স্বতন্ত্র, ডোমেইন-নির্দিষ্ট ডেটা টাইপের জন্য টাইপ-ডিরাইভড কী ব্যবহার করুন।

একটি গন্তব্য থেকে ফলাফল ফেরত দিন

স্ক্রিন কম্পোজেবলগুলোকে পুনঃব্যবহারযোগ্য ও পরীক্ষাযোগ্য রাখতে, আপনার স্ক্রিন UI-এর ভেতরে সরাসরি LocalResultEventBus অ্যাক্সেস করবেন না। এর পরিবর্তে, আপনার স্ক্রিন থেকে কলব্যাক ল্যাম্বডা এক্সপোজ করুন। আপনার entryProvider এ, LocalResultEventBus.current ব্যবহার করে ফলাফল পাঠিয়ে এবং পিছনে নেভিগেট করে কলব্যাকটি হ্যান্ডেল করুন।

আপনি সুস্পষ্ট ফলাফল কী ব্যবহার করে ফলাফল পাঠাতে পারেন:

import androidx.compose.runtime.Composable
import androidx.navigation3.runtime.result.LocalResultEventBus

entry<AddressPickerRoute> {
    val resultBus = LocalResultEventBus.current

    AddressPickerScreen(
        onAddressSelected = { selectedAddress: Address ->
            resultBus.sendResult(
                resultKey = "pickup_address",
                result = selectedAddress
            )
            navigator.goBack()
        }
    )
}

আপনি টাইপ-ডিরাইভড কী ব্যবহার করেও ফলাফল পাঠাতে পারেন:

import androidx.compose.runtime.Composable
import androidx.navigation3.runtime.result.LocalResultEventBus

entry<ContactPickerRoute> {
    val resultBus = LocalResultEventBus.current

    ContactPickerScreen(
        onContactSelected = { selectedContact: Contact ->
            resultBus.sendResult(result = selectedContact)
            navigator.goBack()
        }
    )
}

ফলাফল গ্রহণ করুন

গন্তব্যস্থলগুলো ঘটনা-ভিত্তিক প্রভাব অথবা অবস্থা-ভিত্তিক পর্যবেক্ষণযোগ্য বিষয় ব্যবহার করে ফলাফল গ্রহণ করতে পারে।

এপিআই আচরণ সুপারিশকৃত ব্যবহারের ক্ষেত্রসমূহ
ResultEffect কিউড : কী-টির জন্য নির্গত সমস্ত ফলাফল ক্রমানুসারে প্রসেস করে। এককালীন ইভেন্ট এবং সাইড ইফেক্ট (যেমন একটি স্নাকবার প্রদর্শন করা বা একটি ViewModel এ ফরোয়ার্ড করা)।
conflateAsState কনফ্লেটেড : মধ্যবর্তী ফলাফলগুলো বাদ দেয় এবং কম্পোজ State হিসেবে শুধুমাত্র সর্বশেষ ফলাফলটি রাখে। হালকা UI স্টেট মডিফায়ার (যেমন সক্রিয় ফিল্টার ট্যাগ বা সিলেকশন ওভাররাইড)।

ResultEffect ব্যবহার করে এককালীন ইভেন্টগুলো পরিচালনা করুন

অ্যানালিটিক্স চালু করা, স্নাকবার প্রদর্শন করা, বা কোনো ফলাফল ViewModel এ ফরোয়ার্ড করার মতো এককালীন ইভেন্টগুলি পরিচালনা করার জন্য ResultEffect ব্যবহার করুন।

ResultEffect আগত ফলাফলের জন্য একটি কিউ (queue) রক্ষণাবেক্ষণ করে। যদি কোনো নির্দিষ্ট কী (key)-এর জন্য একাধিক ফলাফল পাঠানো হয়, তবে ResultEffect প্রতিটি ফলাফলকে পাঠানোর ক্রমানুসারে প্রসেস করে। এছাড়াও, ResultEffect একটি কো-রুটিন (coroutine) স্কোপে চলে, যা আপনাকে ইফেক্ট বডির ভেতরে সরাসরি সাসপেন্ডিং (suspending) ফাংশন কল করার সুযোগ দেয়।

আপনি একটি সুস্পষ্ট ফলাফল কী- এর সাথে সম্পর্কিত ফলাফল শুনতে পারেন:

import androidx.compose.runtime.Composable
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation3.runtime.result.ResultEffect

@Composable
fun RideSummaryScreen(
    onOpenAddressPicker: (key: String) -> Unit,
    viewModel: RideSummaryViewModel = viewModel()
) {
    ResultEffect<Address>(resultKey = "pickup_address") { address ->
        viewModel.onPickupAddressSelected(address)
    }

    ResultEffect<Address>(resultKey = "destination_address") { address ->
        viewModel.onDestinationAddressSelected(address)
    }

    RideSummaryContent(
        pickupAddress = viewModel.pickupAddress,
        destinationAddress = viewModel.destinationAddress,
        onPickPickup = { onOpenAddressPicker("pickup_address") },
        onPickDestination = { onOpenAddressPicker("destination_address") }
    )
}

আপনি টাইপ-ডিরাইভড কী ব্যবহার করেও ফলাফলের জন্য শুনতে পারেন:

import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation3.runtime.result.ResultEffect

@Composable
fun ComposeMessageScreen(
    onPickContact: () -> Unit,
    snackbarHostState: SnackbarHostState = remember { SnackbarHostState() },
    viewModel: ComposeMessageViewModel = viewModel()
) {
    ResultEffect<Contact> { contact ->
        // Suspending calls are supported directly in the effect body
        snackbarHostState.showSnackbar("Selected ${contact.name}")
        viewModel.onRecipientSelected(contact)
    }

    ComposeMessageContent(
        recipient = viewModel.recipient,
        onPickContact = onPickContact
    )
}

গন্তব্যস্থলগুলির মধ্যে চলাচল করার সময়, ResultEffect নিম্নলিখিত জীবনচক্র অনুক্রমটি অনুসরণ করে:

  1. প্রেরকের নির্গমন : প্রেরক গন্তব্য resultBus.sendResult(resultKey = "pickup_address", address) ব্যবহার করে একটি ফলাফল পাঠায় এবং ব্যাক স্ট্যাক থেকে তা পপ করে।
  2. রিসিভার কম্পোজিশনে প্রবেশ করে : রিসিভারের গন্তব্যস্থলটি সক্রিয় স্ক্রিন হয়ে যায় এবং ResultEffect ফলাফলের জন্য শোনা শুরু করে।
  3. রিসিভার ফলাফল প্রক্রিয়াকরণ করে : ResultEffect সেই কী-এর জন্য পাঠানো প্রতিটি ফলাফলের জন্য তার এফেক্ট বডি গ্রহণ ও কার্যকর করে এবং প্রেরণের ক্রমানুসারে সমস্ত এমিশন প্রক্রিয়াকরণ করে।
  4. রিসিভার কম্পোজিশন ত্যাগ করে : যখন ব্যাক স্ট্যাক থেকে রিসিভার ডেস্টিনেশনটি পপ করা হয়, তখন ResultEffect কম্পোজিশন ত্যাগ করে এবং ফলাফলের জন্য শোনা বন্ধ করে দেয়।

conflateAsState ব্যবহার করে সর্বশেষ ফলাফলকে স্টেট হিসেবে পর্যবেক্ষণ করুন।

যখন স্থানীয় UI স্টেট সরাসরি পরিবর্তন বা ফিল্টার করার জন্য আপনার শুধুমাত্র সর্বশেষ ফলাফলের মান প্রয়োজন এবং আপনি চান যে ফলাফল আপডেট হওয়ার সাথে সাথে Compose স্বয়ংক্রিয়ভাবে পুনরায় কম্পোজ করুক, তখন ResultEventBusconflateAsState কল করুন।

আপনি একটি সুস্পষ্ট ফলাফল কী-এর সাথে সম্পর্কিত ফলাফলগুলি পর্যবেক্ষণ করতে পারেন:

import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.graphics.Color
import androidx.navigation3.runtime.result.LocalResultEventBus

@Composable
fun ThemePreviewScreen(
    onOpenColorPicker: (key: String) -> Unit
) {
    val resultBus = LocalResultEventBus.current

    val primaryColor by resultBus.conflateAsState<Color>(
        resultKey = "primary_color",
        defaultValue = MaterialTheme.colorScheme.primary
    )

    val accentColor by resultBus.conflateAsState<Color>(
        resultKey = "accent_color",
        defaultValue = MaterialTheme.colorScheme.tertiary
    )

    ThemePreviewContent(
        primaryColor = primaryColor,
        accentColor = accentColor,
        onPickPrimary = { onOpenColorPicker("primary_color") },
        onPickAccent = { onOpenColorPicker("accent_color") }
    )
}

আপনি একটি টাইপ-ডিরাইভড কী ব্যবহার করেও ফলাফল পর্যবেক্ষণ করতে পারেন:

import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.navigation3.runtime.result.LocalResultEventBus

@Composable
fun FilterableProductListScreen(
    initialFilter: ProductFilter = ProductFilter.All,
    onOpenFilterPicker: () -> Unit
) {
    val resultBus = LocalResultEventBus.current

    // Observe latest filter result as Compose State, starting with initialFilter
    val activeFilter by resultBus.conflateAsState<ProductFilter>(
        defaultValue = initialFilter
    )

    ProductListContent(
        activeFilter = activeFilter,
        onOpenFilterPicker = onOpenFilterPicker
    )
}

ResultEventBus উত্তোলন করুন

ডিফল্টরূপে, rememberResultEventBusNavEntryDecorator অভ্যন্তরীণভাবে rememberResultEventBus ব্যবহার করে তার নিজস্ব ResultEventBus তৈরি করে এবং মনে রাখে।

প্রয়োজন হলে আপনি সুস্পষ্টভাবে একটি ResultEventBus তৈরি এবং হোইস্ট করতে পারেন:

  • ResultEventBus ইনস্ট্যান্সটি সরাসরি নন-কম্পোজেবল কম্পোনেন্ট বা ডিপেন্ডেন্সি ইনজেকশন গ্রাফে পাস করুন।
  • গন্তব্য হায়ারার্কির বাইরে থাকা শীর্ষ-স্তরের অ্যাপ স্কাফোল্ডিং (যেমন একটি অ্যাপ বার বা নেভিগেশন ড্রয়ার) থেকে ফলাফল পাঠান বা পর্যবেক্ষণ করুন।

ResultEventBus হোইস্ট করতে, rememberResultEventBus ব্যবহার করে এটি তৈরি করুন এবং rememberResultEventBusNavEntryDecorator(resultEventBus) -এ পাস করুন:

import androidx.compose.runtime.Composable
import androidx.navigation3.runtime.result.rememberResultEventBus
import androidx.navigation3.runtime.result.rememberResultEventBusNavEntryDecorator
import androidx.navigation3.ui.NavDisplay

// Hoist the ResultEventBus at the top level
val resultEventBus = rememberResultEventBus()

// Pass the hoisted bus to the decorator
val resultEventBusNavEntryDecorator =
    rememberResultEventBusNavEntryDecorator<NavKey>(
        resultEventBus = resultEventBus
    )

NavDisplay(
    /* ... */
    entryDecorators = listOf(
        rememberSaveableStateHolderNavEntryDecorator(),
        resultEventBusNavEntryDecorator
    )
)

ফলাফল পরিচালনা ও পরিষ্কার করুন

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

import androidx.compose.runtime.Composable
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation3.runtime.result.LocalResultEventBus
import androidx.navigation3.runtime.result.ResultEffect

@Composable
fun NotificationSettingsScreen(
    viewModel: NotificationViewModel = viewModel()
) {
    val resultBus = LocalResultEventBus.current

    ResultEffect<ConfirmationResult>(resultKey = "confirm_permission") { confirmation ->
        viewModel.onPermissionConfirmed(confirmation)

        // Clear the result after consumption to prevent re-delivery
        resultBus.removeResult(resultKey = "confirm_permission")
    }
}

আপনি সুস্পষ্ট কী ( resultBus.removeResult(resultKey) ) অথবা টাইপ-ভিত্তিক কী ( resultBus.removeResult<T>() ) ব্যবহার করে ফলাফল মুছে ফেলতে পারেন। কী মেলানোর বিষয়ে বিস্তারিত জানতে, ফলাফলের কী (Result keys ) দেখুন।

রেসিপি

বিভিন্ন ফলাফল-প্রদান কৌশল প্রদর্শনকারী সম্পূর্ণ কার্যকর কোড উদাহরণের জন্য, নিম্নলিখিত রেসিপিগুলো দেখুন: