রচনায় UI অবস্থা সংরক্ষণ করুন

আপনার রাজ্য কোথায় উত্তোলন করা হয়েছে এবং যে যুক্তির প্রয়োজন তার উপর নির্ভর করে, আপনি আপনার UI অবস্থা সংরক্ষণ এবং পুনরুদ্ধার করতে বিভিন্ন API ব্যবহার করতে পারেন। এটি সর্বোত্তমভাবে অর্জন করতে প্রতিটি অ্যাপ API-এর সংমিশ্রণ ব্যবহার করে।

কার্যকলাপ বা প্রক্রিয়া বিনোদনের কারণে যেকোনো Android অ্যাপ তার UI অবস্থা হারাতে পারে। নিম্নলিখিত ঘটনার কারণে রাষ্ট্রের এই ক্ষতি ঘটতে পারে:

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

এই পৃষ্ঠাটি UI স্টেট সঞ্চয় করার জন্য উপলব্ধ API গুলিকে সংক্ষিপ্ত করে যা আপনার স্টেট কোথায় উত্তোলন করা হয়েছে এবং যে যুক্তির প্রয়োজন তার উপর নির্ভর করে।

UI যুক্তি

যদি আপনার স্টেটটি UI-তে উত্তোলন করা হয়, হয় কম্পোজেবল ফাংশন বা প্লেইন স্টেট হোল্ডার ক্লাসে কম্পোজিশন স্কোপ করা হয়, আপনি ক্রিয়াকলাপ এবং প্রক্রিয়া বিনোদন জুড়ে অবস্থা ধরে রাখতে rememberSaveable ব্যবহার করতে পারেন।

নিম্নলিখিত স্নিপেটে, rememberSaveable একটি একক বুলিয়ান UI উপাদান অবস্থা সংরক্ষণ করতে ব্যবহৃত হয়:

@Composable
fun ChatBubble(
    message: Message
) {
    var showDetails by rememberSaveable { mutableStateOf(false) }

    ClickableText(
        text = AnnotatedString(message.content),
        onClick = { showDetails = !showDetails }
    )

    if (showDetails) {
        Text(message.timestamp)
    }
}

চিত্র 1 । আলতো চাপলে চ্যাট মেসেজ বুদবুদ প্রসারিত হয় এবং ভেঙে পড়ে।

showDetails হল একটি বুলিয়ান ভেরিয়েবল যা সঞ্চয় করে যদি চ্যাট বুদবুদটি ভেঙে যায় বা প্রসারিত হয়।

rememberSaveable সংরক্ষিত ইনস্ট্যান্স স্টেট মেকানিজমের মাধ্যমে একটি Bundle UI উপাদানের অবস্থা সংরক্ষণ করে।

এটি স্বয়ংক্রিয়ভাবে বান্ডিলে আদিম প্রকারগুলি সংরক্ষণ করতে সক্ষম। যদি আপনার স্টেট এমন একটি টাইপের মধ্যে রাখা হয় যা ডেটা ক্লাসের মতো আদিম নয়, আপনি বিভিন্ন স্টোরিং মেকানিজম ব্যবহার করতে পারেন, যেমন Parcelize টীকা ব্যবহার করা, listSaver এবং mapSaver মতো কম্পোজ API ব্যবহার করা, বা কম্পোজ রানটাইম Saver প্রসারিত করে একটি কাস্টম সেভার ক্লাস বাস্তবায়ন করা ক্লাস এই পদ্ধতিগুলি সম্পর্কে আরও জানতে রাষ্ট্রীয় ডকুমেন্টেশন সংরক্ষণের উপায়গুলি দেখুন।

নিম্নলিখিত স্নিপেটে, rememberLazyListState কম্পোজ এপিআই LazyListState সঞ্চয় করে, যা একটি LazyColumn বা LazyRow এর স্ক্রোল অবস্থা নিয়ে গঠিত, rememberSaveable ব্যবহার করে। এটি একটি LazyListState.Saver ব্যবহার করে, যা একটি কাস্টম সেভার যা স্ক্রোল অবস্থা সংরক্ষণ এবং পুনরুদ্ধার করতে সক্ষম। একটি কার্যকলাপ বা প্রক্রিয়া বিনোদনের পরে (উদাহরণস্বরূপ, ডিভাইসের অভিযোজন পরিবর্তনের মতো কনফিগারেশন পরিবর্তনের পরে), স্ক্রোল অবস্থা সংরক্ষণ করা হয়।

@Composable
fun rememberLazyListState(
    initialFirstVisibleItemIndex: Int = 0,
    initialFirstVisibleItemScrollOffset: Int = 0
): LazyListState {
    return rememberSaveable(saver = LazyListState.Saver) {
        LazyListState(
            initialFirstVisibleItemIndex, initialFirstVisibleItemScrollOffset
        )
    }
}

সর্বোত্তম অনুশীলন

rememberSaveable UI স্টেট সঞ্চয় করার জন্য একটি Bundle ব্যবহার করে, যা অন্যান্য API গুলি দ্বারা শেয়ার করা হয় যা এটিতে লেখে, যেমন আপনার কার্যকলাপে onSaveInstanceState() কল। যাইহোক, এই Bundle আকার সীমিত, এবং বড় বস্তু সংরক্ষণ করলে রানটাইমে TransactionTooLarge ব্যতিক্রম হতে পারে। এটি বিশেষ করে একক Activity অ্যাপে সমস্যাযুক্ত হতে পারে যেখানে একই Bundle অ্যাপ জুড়ে ব্যবহার করা হচ্ছে।

এই ধরনের ক্র্যাশ এড়াতে, আপনার বান্ডিলে বড় জটিল বস্তু বা বস্তুর তালিকা সংরক্ষণ করা উচিত নয়

পরিবর্তে, আইডি বা কীগুলির মতো প্রয়োজনীয় ন্যূনতম অবস্থা সঞ্চয় করুন এবং স্থায়ী স্টোরেজের মতো আরও জটিল UI অবস্থা পুনরুদ্ধার করার জন্য অন্যান্য পদ্ধতিতে অর্পণ করতে এগুলি ব্যবহার করুন৷

এই ডিজাইন পছন্দগুলি আপনার অ্যাপের জন্য নির্দিষ্ট ব্যবহারের ক্ষেত্রে এবং আপনার ব্যবহারকারীরা কীভাবে এটি আচরণ করবে তার উপর নির্ভর করে।

রাষ্ট্র পুনরুদ্ধার যাচাই করুন

আপনি যাচাই করতে পারেন যে আপনার রচনা উপাদানগুলিতে rememberSaveable সহ সংরক্ষিত অবস্থাটি সঠিকভাবে পুনরুদ্ধার করা হয়েছে যখন কার্যকলাপ বা প্রক্রিয়াটি পুনরায় তৈরি করা হয়। এটি অর্জনের জন্য নির্দিষ্ট API আছে, যেমন StateRestorationTester । আরও জানতে টেস্টিং ডকুমেন্টেশন দেখুন।

ব্যবসায়িক যুক্তি

যদি আপনার UI উপাদানের অবস্থা ViewModel এ উত্তোলন করা হয় কারণ এটি ব্যবসায়িক যুক্তি দ্বারা প্রয়োজন, আপনি ViewModel এর API ব্যবহার করতে পারেন।

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

যাইহোক, একটি ViewModel দৃষ্টান্ত সিস্টেম-সূচিত প্রক্রিয়ার মৃত্যু থেকে বাঁচতে পারে না। UI স্টেট যাতে টিকে থাকে তার জন্য, ViewModel-এর জন্য Saved State মডিউল ব্যবহার করুন, যাতে SavedStateHandle API রয়েছে।

সর্বোত্তম অনুশীলন

SavedStateHandle এছাড়াও UI স্টেট সঞ্চয় করতে Bundle প্রক্রিয়া ব্যবহার করে, তাই আপনার শুধুমাত্র সাধারণ UI উপাদান স্থিতি সঞ্চয় করতে এটি ব্যবহার করা উচিত।

স্ক্রীন UI অবস্থা , যা ব্যবসার নিয়ম প্রয়োগ করে এবং UI ব্যতীত আপনার অ্যাপ্লিকেশনের স্তরগুলি অ্যাক্সেস করার মাধ্যমে উত্পাদিত হয়, সম্ভাব্য জটিলতা এবং আকারের কারণে SavedStateHandle এ সংরক্ষণ করা উচিত নয়৷ আপনি স্থানীয় স্থায়ী স্টোরেজের মতো জটিল বা বড় ডেটা সঞ্চয় করতে বিভিন্ন প্রক্রিয়া ব্যবহার করতে পারেন। একটি প্রসেস রিক্রিয়েশনের পরে, স্ক্রীনটি পুনরুদ্ধার করা ক্ষণস্থায়ী অবস্থার সাথে পুনরায় তৈরি করা হয় যা SavedStateHandle এ সংরক্ষিত ছিল (যদি থাকে), এবং স্ক্রীন UI অবস্থা আবার ডেটা স্তর থেকে উত্পাদিত হয়।

SavedStateHandle APIs

SavedStateHandle এর UI এলিমেন্ট স্টেট সঞ্চয় করার জন্য বিভিন্ন API আছে, বিশেষ করে:

State রচনা করুন saveable()
StateFlow getStateFlow()

State রচনা করুন

MutableState হিসাবে UI উপাদানের অবস্থা পড়তে এবং লিখতে SavedStateHandle এর saveable API ব্যবহার করুন, যাতে এটি ন্যূনতম কোড সেটআপের সাথে কার্যকলাপ এবং প্রক্রিয়া বিনোদন থেকে বেঁচে থাকে।

saveable এপিআই বাক্সের বাইরে আদিম প্রকারগুলিকে সমর্থন করে এবং কাস্টম সেভারগুলি ব্যবহার করার জন্য একটি stateSaver প্যারামিটার পায়, ঠিক rememberSaveable() এর মতো।

নিম্নলিখিত স্নিপেটে, message ব্যবহারকারীর ইনপুট প্রকারগুলিকে একটি TextField এ সঞ্চয় করে:

class ConversationViewModel(
    savedStateHandle: SavedStateHandle
) : ViewModel() {

    var message by savedStateHandle.saveable(stateSaver = TextFieldValue.Saver) {
        mutableStateOf(TextFieldValue(""))
    }
        private set

    fun update(newMessage: TextFieldValue) {
        message = newMessage
    }

    /*...*/
}

val viewModel = ConversationViewModel(SavedStateHandle())

@Composable
fun UserInput(/*...*/) {
    TextField(
        value = viewModel.message,
        onValueChange = { viewModel.update(it) }
    )
}

saveable API ব্যবহার করার বিষয়ে আরও তথ্যের জন্য SavedStateHandle ডকুমেন্টেশন দেখুন।

StateFlow

UI উপাদান স্থিতি সংরক্ষণ করতে getStateFlow() ব্যবহার করুন এবং SavedStateHandle থেকে একটি প্রবাহ হিসাবে এটি ব্যবহার করুন। StateFlow শুধুমাত্র পঠিত হয়, এবং API এর জন্য আপনাকে একটি কী নির্দিষ্ট করতে হবে যাতে আপনি একটি নতুন মান নির্গত করতে ফ্লো প্রতিস্থাপন করতে পারেন। আপনার কনফিগার করা কী দিয়ে, আপনি StateFlow পুনরুদ্ধার করতে এবং সর্বশেষ মান সংগ্রহ করতে পারেন।

নিম্নলিখিত স্নিপেটে, savedFilterType হল একটি StateFlow ভেরিয়েবল যা একটি চ্যাট অ্যাপে চ্যাট চ্যানেলের তালিকায় প্রয়োগ করা একটি ফিল্টার প্রকার সংরক্ষণ করে:

private const val CHANNEL_FILTER_SAVED_STATE_KEY = "ChannelFilterKey"

class ChannelViewModel(
    channelsRepository: ChannelsRepository,
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    private val savedFilterType: StateFlow<ChannelsFilterType> = savedStateHandle.getStateFlow(
        key = CHANNEL_FILTER_SAVED_STATE_KEY, initialValue = ChannelsFilterType.ALL_CHANNELS
    )

    private val filteredChannels: Flow<List<Channel>> =
        combine(channelsRepository.getAll(), savedFilterType) { channels, type ->
            filter(channels, type)
        }.onStart { emit(emptyList()) }

    fun setFiltering(requestType: ChannelsFilterType) {
        savedStateHandle[CHANNEL_FILTER_SAVED_STATE_KEY] = requestType
    }

    /*...*/
}

enum class ChannelsFilterType {
    ALL_CHANNELS, RECENT_CHANNELS, ARCHIVED_CHANNELS
}

প্রতিবার ব্যবহারকারী একটি নতুন ফিল্টার টাইপ নির্বাচন করে, setFiltering বলা হয়। এটি _CHANNEL_FILTER_SAVED_STATE_KEY_ কী সহ সংরক্ষণ করা SavedStateHandle এ একটি নতুন মান সংরক্ষণ করে। savedFilterType হল একটি ফ্লো যা কীতে সংরক্ষিত সর্বশেষ মান নির্গত করে। filteredChannels চ্যানেল ফিল্টারিং সঞ্চালনের জন্য ফ্লোতে সাবস্ক্রাইব করা হয়েছে।

getStateFlow() API সম্পর্কে আরও তথ্যের জন্য SavedStateHandle ডকুমেন্টেশন দেখুন।

সারাংশ

নিম্নলিখিত সারণীটি এই বিভাগে কভার করা APIগুলির সংক্ষিপ্ত বিবরণ দেয় এবং UI অবস্থা সংরক্ষণ করতে কখন প্রতিটি ব্যবহার করতে হবে:

ঘটনা UI যুক্তি একটি ViewModel ব্যবসায়িক যুক্তি
কনফিগারেশন পরিবর্তন rememberSaveable স্বয়ংক্রিয়
সিস্টেম-সূচিত প্রক্রিয়া মৃত্যু rememberSaveable SavedStateHandle

ব্যবহার করার জন্য API নির্ভর করে রাষ্ট্রটি কোথায় রাখা হয়েছে এবং এর জন্য প্রয়োজনীয় যুক্তির উপর। UI লজিক ব্যবহার করা হয় এমন অবস্থার জন্য, rememberSaveable ব্যবহার করুন। ব্যবসায়িক যুক্তিতে ব্যবহৃত রাষ্ট্রের জন্য, যদি আপনি এটিকে একটি ViewModel এ ধরে রাখেন, SavedStateHandle ব্যবহার করে সংরক্ষণ করুন।

অল্প পরিমাণে UI স্টেট সঞ্চয় করার জন্য আপনার বান্ডেল API ব্যবহার করা SavedStateHandle rememberSaveable UI কে পূর্বের অবস্থায় ফিরিয়ে আনার জন্য এই তথ্যটি ন্যূনতম প্রয়োজনীয়, অন্যান্য স্টোরিং মেকানিজমের সাথে। উদাহরণস্বরূপ, যদি আপনি একটি প্রোফাইলের আইডি সংরক্ষণ করেন যা ব্যবহারকারী বান্ডেলে দেখছিলেন, আপনি ডেটা স্তর থেকে প্রোফাইলের বিবরণের মতো ভারী ডেটা আনতে পারেন।

UI অবস্থা সংরক্ষণের বিভিন্ন উপায় সম্পর্কে আরও তথ্যের জন্য, সাধারণ সংরক্ষণ UI স্টেট ডকুমেন্টেশন এবং আর্কিটেকচার গাইডের ডেটা স্তর পৃষ্ঠাটি দেখুন।

{% শব্দার্থে %} {% endverbatim %} {% শব্দার্থে %} {% endverbatim %}