লাইফসাইকেল-অ্যাওয়ার কম্পোনেন্ট সহ Kotlin কোরুটিন ব্যবহার করা

Kotlin coroutines একটি API প্রদান করে যা আপনাকে অ্যাসিঙ্ক্রোনাস কোড লিখতে দেয়। Kotlin coroutines-এর মাধ্যমে, আপনি একটি CoroutineScope নির্ধারণ করতে পারবেন, যা আপনার coroutines কখন রান করা উচিত তা ম্যানেজ করতে সাহায্য করে। প্রতিটি অ্যাসিঙ্ক্রোনাস অপারেশন একটি নির্দিষ্ট স্কোপের মধ্যে চলে।

লাইফসাইকেল-অ্যাওয়ার কম্পোনেন্ট আপনার অ্যাপে লজিক্যাল স্কোপের জন্য কোরুটিনের ক্ষেত্রে ফার্স্ট-ক্লাস সহায়তা প্রদান করে। এই ডকুমেন্ট থেকে জানতে পারবেন যে কীভাবে লাইফসাইকেল-অ্যাওয়ার কম্পোনেন্টের সাথে কোরুটিন কার্যকরভাবে ব্যবহার করবেন।

ডিপেন্ডেন্সি যোগ করুন

এই বিষয়ে বর্ণিত বিল্ট-ইন কোরুটিন স্কোপ Lifecycle API-তে অন্তর্ভুক্ত। এইসব স্কোপ ব্যবহার করার সময় উপযুক্ত ডিপেন্ডেন্সি যোগ করতে ভুলবেন না।

  • Compose-এ ViewModel ইউটিলিটির জন্য, implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version") ব্যবহার করুন।
  • Compose-এ লাইফসাইকেল ইউটিলিটির জন্য, implementation("androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version") ব্যবহার করুন।

লাইফসাইকেল-অ্যাওয়ার কোরুটিন স্কোপ

Compose ও লাইফসাইকেল লাইব্রেরি নিম্নলিখিত বিল্ট-ইন স্কোপ প্রদান করে যা আপনি নিজের অ্যাপে ব্যবহার করতে পারবেন।

ViewModelScope

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

আপনি ViewModel-এর viewModelScope প্রপার্টির মাধ্যমে ViewModel-এর CoroutineScope অ্যাক্সেস করতে পারবেন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

class MyViewModel: ViewModel() {
    init {
        viewModelScope.launch {
            // Coroutine that will be canceled when the ViewModel is cleared.
        }
    }
}

আরও উন্নত ব্যবহারের ক্ষেত্রে, ডিফল্ট viewModelScope-এর পরিবর্তে আপনি সরাসরি ViewModel-এর কনস্ট্রাক্টরে কাস্টম CoroutineScope পাস করতে পারেন। এই পদ্ধতি আরও বেশি নিয়ন্ত্রণ ও নমনীয়তা প্রদান করে, বিশেষ করে:

  • পরীক্ষা: এটি আপনাকে একটি TestScope ইনজেক্ট করতে দেয়, যা সময় নিয়ন্ত্রণ করা এবং ইউনিট টেস্টে কোরুটিন আচরণ যাচাই করা সহজ করে তোলে।

  • কাস্টম কনফিগারেশন: ViewModel কাজ শুরু করার আগেই আপনি নির্দিষ্ট CoroutineDispatcher (যেমন, ভারী কম্পিউটেশনের জন্য Dispatchers.Default) বা কাস্টম CoroutineExceptionHandler-এর মাধ্যমে স্কোপ কনফিগার করতে পারবেন।

কম্পোজিশন-বাউন্ড স্কোপ

অ্যানিমেশন, নেটওয়ার্ক কল বা টাইমারের মতো পার্শ্ব প্রতিক্রিয়া কম্পোজেবলের লাইফসাইকেলে স্কোপ করতে হবে। এইভাবে, যখন কোনও কম্পোজেবল স্ক্রিন ছেড়ে চলে যায় (কম্পোজিশন থেকে বেরিয়ে যায়), তখন মেমরি লিক প্রতিরোধ করতে যেকোনও চলমান কোরুটিন অটোমেটিক বাতিল হয়ে যায়।

কম্পোজিশন স্কোপিং ডিক্লেরেটিভভাবে ম্যানেজ করার জন্য Compose LaunchedEffect API প্রদান করে।

LaunchedEffect একটি CoroutineScope তৈরি করে যা আপনাকে সাসপেন্ড ফাংশন রান করতে দেয়। স্কোপটি কম্পোজেবলের কম্পোজিশন লাইফসাইকেলের সাথে যুক্ত, হোস্ট অ্যাক্টিভিটির লাইফসাইকেলের সাথে নয়।

  • Enter: কম্পোজেবল কম্পোজিশনে প্রবেশ করলে কোরুটিন শুরু হয়।
  • Exit: কম্পোজ করার উপযুক্ত আইটেম কম্পোজিশন থেকে বেরিয়ে গেলে, Coroutine বাতিল হয়ে যায়।
  • আবার চালু করুন: LaunchedEffect-এ পাস করা কোনও কী পরিবর্তন হলে, আগে থেকে থাকা কোরুটিন বাতিল হয়ে যায় এবং নতুন একটি চালু হয়।

নিম্নলিখিত উদাহরণে দেখানো হয়েছে যে কীভাবে LaunchedEffect ব্যবহার করে পালসিং অ্যানিমেশন তৈরি করা যায়। কম্পোজিশনে কম্পোজেবলের উপস্থিতির সাথে কো-রুটিন যুক্ত থাকে এবং কনফিগারেশন পরিবর্তনের সাথে সাথে প্রতিক্রিয়া জানায়:

// Allow the pulse rate to be configured, so it can be sped up if the user is running
// out of time
var pulseRateMs by remember { mutableLongStateOf(3000L) }
val alpha = remember { Animatable(1f) }
LaunchedEffect(pulseRateMs) { // Restart the effect when the pulse rate changes
    while (isActive) {
        delay(pulseRateMs) // Pulse the alpha every pulseRateMs to alert the user
        alpha.animateTo(0f)
        alpha.animateTo(1f)
    }
}

LaunchedEffect সম্পর্কে আরও তথ্যের জন্য, Compose-এ সাইড-এফেক্ট দেখুন।

লাইফসাইকেল-অ্যাওয়ার ফ্লো কালেকশন

Jetpack Compose-এ নিরাপদে ফ্লো সংগ্রহ করতে, collectAsStateWithLifecycle API ব্যবহার করুন। এই একটি ফাংশন Flow-কে Compose State অবজেক্টে কনভার্ট করে এবং আপনার জন্য লাইফসাইকেল সাবস্ক্রিপশন অটোমেটিক ম্যানেজ করে। ডিফল্ট হিসেবে, লাইফসাইকেল STARTED হলে সংগ্রহ শুরু হয় এবং লাইফসাইকেল STOPPED হলে বন্ধ হয়। এই ডিফল্ট অ্যাকশন ওভাররাইড করতে, আপনার পছন্দের লাইফসাইকেল পদ্ধতির সাথে minActiveState প্যারামিটার পাস করুন, যেমন Lifecycle.State.RESUMED।

নিম্নলিখিত উদাহরণ থেকে বোঝা যাবে যে কীভাবে একটি কম্পোজেবলে ViewModel-এর StateFlow সংগ্রহ করতে হয়:

@Composable
private fun ConversationScreen(
    conversationViewModel: ConversationViewModel = viewModel()
) {

    val messages by conversationViewModel.messages.collectAsStateWithLifecycle()

    ConversationScreen(
        messages = messages,
        onSendMessage = { message: Message -> conversationViewModel.sendMessage(message) }
    )
}

@Composable
private fun ConversationScreen(
    messages: List<Message>,
    onSendMessage: (Message) -> Unit
) {

    MessagesList(messages, onSendMessage)
    /* ... */
}

একাধিক ফ্লোয়ের সমান্তরাল সংগ্রহ

Compose-এ, আপনি একাধিক স্টেট ভেরিয়েবল ঘোষণা করে সমান্তরালভাবে একাধিক ফ্লো সংগ্রহ করতে পারবেন। যেহেতু collectAsStateWithLifecycle তার নিজস্ব অন্তর্নিহিত স্কোপ ম্যানেজ করে, তাই সমান্তরাল সংগ্রহ অটোমেটিক ম্যানেজ করা হয়:

@Composable
fun DashboardScreen(viewModel: DashboardViewModel = viewModel()) {
    // Both flows are collected safely in parallel and will emit updates when either changes, the composables will recompose
    val userData by viewModel.userFlow.collectAsStateWithLifecycle()
    val feedData by viewModel.feedFlow.collectAsStateWithLifecycle()

    // ...
}

Flows ব্যবহার করে অ্যাসিঙ্ক্রোনাসভাবে ভ্যালু গণনা করুন

আপনাকে যখন অ্যাসিঙ্ক্রোনাসভাবে ভ্যালু গণনা করতে হবে, তখন stateIn অপারেটরের সাথে StateFlow ব্যবহার করুন।

নিম্নলিখিত স্নিপেট একটি স্ট্যান্ডার্ড Flow ব্যবহার করে যা StateFlow-এ কনভার্ট করা হয়েছে। কনফিগারেশনে হওয়া পরিবর্তন ম্যানেজ করার জন্য UI অদৃশ্য হয়ে যাওয়ার পরে WhileSubscribed(5000) প্যারামিটার সাবস্ক্রিপশনকে পাঁচ সেকেন্ডের জন্য অ্যাক্টিভ রাখে।

val uiState: StateFlow<Result> = flow {
    emit(repository.fetchData())
}
.stateIn(
    scope = viewModelScope,
    started = SharingStarted.WhileSubscribed(5_000),
    initialValue = Result.Loading
)

সংগ্রহ করা ভ্যালু Compose State-এ কনভার্ট করতে collectAsStateWithLifecycle ব্যবহার করুন, যাতে ডেটা পরিবর্তন হলে আপনার UI রিয়্যাক্টিভভাবে আপডেট হতে পারে।

স্টেট সম্পর্কে আরও জানতে, স্টেট ও Jetpack Compose দেখুন।

অতিরিক্ত রিসোর্স

কন্টেন্ট দেখে

নমুনা