কম্পোজেবলের জীবনচক্র

এই পৃষ্ঠায়, আপনি একটি কম্পোজেবলের জীবনচক্র সম্পর্কে শিখবেন এবং কীভাবে কম্পোজ সিদ্ধান্ত নেয় যে একটি কম্পোজেবল পুনর্গঠনের প্রয়োজন আছে কিনা।

জীবনচক্র ওভারভিউ

ম্যানেজিং স্টেট ডকুমেন্টেশনে উল্লিখিত হিসাবে, একটি রচনা আপনার অ্যাপের UI বর্ণনা করে এবং কম্পোজেবল চালানোর মাধ্যমে তৈরি করা হয়। একটি রচনা হল কম্পোজেবলের একটি ট্রি-কাঠামো যা আপনার UI বর্ণনা করে।

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

একটি রচনা শুধুমাত্র একটি প্রাথমিক রচনা দ্বারা উত্পাদিত এবং পুনর্গঠন দ্বারা আপডেট করা যেতে পারে। একটি রচনা সংশোধন করার একমাত্র উপায় হল পুনর্গঠনের মাধ্যমে।

একটি কম্পোজেবলের জীবনচক্র দেখানো ডায়াগ্রাম

চিত্র 1. কম্পোজিশনে কম্পোজেবলের জীবনচক্র। এটি রচনায় প্রবেশ করে, 0 বা তার বেশি বার পুনর্গঠিত হয় এবং রচনাটি ছেড়ে যায়।

Recomposition সাধারণত একটি State<T> অবজেক্টে পরিবর্তনের মাধ্যমে ট্রিগার হয়। কম্পোজ এইগুলিকে ট্র্যাক করে এবং কম্পোজিশনের সমস্ত কম্পোজেবল চালায় যেগুলি সেই নির্দিষ্ট State<T> পড়ে, এবং যে কোনও কম্পোজেবল যাকে তারা বলে যেগুলিকে এড়িয়ে যাওয়া যায় না।

যদি একটি কম্পোজেবলকে একাধিকবার বলা হয়, তবে একাধিক দৃষ্টান্ত রচনায় স্থাপন করা হয়। কম্পোজিশনে প্রতিটি কলের নিজস্ব জীবনচক্র রয়েছে।

@Composable
fun MyComposable() {
    Column {
        Text("Hello")
        Text("World")
    }
}

পূর্ববর্তী কোড স্নিপেটে উপাদানগুলির অনুক্রমিক বিন্যাস দেখানো চিত্র

চিত্র 2. রচনায় MyComposable প্রতিনিধিত্ব। যদি একটি কম্পোজেবলকে একাধিকবার বলা হয়, তবে একাধিক দৃষ্টান্ত রচনায় স্থাপন করা হয়। একটি ভিন্ন রঙ থাকার একটি উপাদান এটি একটি পৃথক উদাহরণ হচ্ছে নির্দেশ করে.

কম্পোজিশনে কম্পোজেবলের অ্যানাটমি

কম্পোজিশনে একটি কম্পোজেবলের উদাহরণ তার কল সাইট দ্বারা চিহ্নিত করা হয়। কম্পোজ কম্পাইলার প্রতিটি কল সাইটকে স্বতন্ত্র হিসাবে বিবেচনা করে। একাধিক কল সাইট থেকে কম্পোজেবল কল করা কম্পোজিশনে কম্পোজেবলের একাধিক উদাহরণ তৈরি করবে।

যদি একটি পুনর্গঠনের সময় একটি কম্পোজেবল আগের কম্পোজিশনের থেকে ভিন্ন কম্পোজেবলকে কল করে, তাহলে কম্পোজ শনাক্ত করবে কোন কম্পোজেবলগুলিকে কল করা হয়েছিল বা বলা হয়নি এবং যে কম্পোজেবলগুলিকে উভয় কম্পোজিশনে কল করা হয়েছিল, তাদের ইনপুটগুলি পরিবর্তিত না হলে কম্পোজ তাদের পুনরায় কম্পোজ করা এড়াবে। .

তাদের কম্পোজেবলের সাথে পার্শ্ব প্রতিক্রিয়া যুক্ত করার জন্য পরিচয় সংরক্ষণ করা অত্যন্ত গুরুত্বপূর্ণ, যাতে প্রতিটি পুনর্গঠনের জন্য পুনরায় আরম্ভ করার পরিবর্তে তারা সফলভাবে সম্পূর্ণ করতে পারে।

নিম্নলিখিত উদাহরণ বিবেচনা করুন:

@Composable
fun LoginScreen(showError: Boolean) {
    if (showError) {
        LoginError()
    }
    LoginInput() // This call site affects where LoginInput is placed in Composition
}

@Composable
fun LoginInput() { /* ... */ }

@Composable
fun LoginError() { /* ... */ }

উপরের কোড স্নিপেটে, LoginScreen শর্তসাপেক্ষে LoginError কে কম্পোজেবল বলবে এবং সর্বদা LoginInput কম্পোজেবল বলবে। প্রতিটি কলের একটি অনন্য কল সাইট এবং উত্স অবস্থান রয়েছে, যা কম্পাইলার এটিকে অনন্যভাবে সনাক্ত করতে ব্যবহার করবে।

চিত্রটি দেখানো হচ্ছে কিভাবে পূর্ববর্তী কোডটি পুনরায় সংকলন করা হয় যদি showError পতাকা সত্যে পরিবর্তিত হয়। LoginError composable যোগ করা হয়েছে, কিন্তু অন্যান্য composables recomposed করা হয় না।

চিত্র 3. কম্পোজিশনে LoginScreen উপস্থাপনা যখন অবস্থার পরিবর্তন হয় এবং একটি পুনর্গঠন ঘটে। একই রঙ মানে এটি পুনর্গঠন করা হয়নি।

যদিও LoginInput প্রথম কল করা থেকে দ্বিতীয় বলা হয়েছে, LoginInput দৃষ্টান্তটি পুনর্গঠন জুড়ে সংরক্ষণ করা হবে। অতিরিক্তভাবে, যেহেতু LoginInput কোনো পরামিতি নেই যা পুনর্গঠন জুড়ে পরিবর্তিত হয়েছে, তাই LoginInput এ কলটি রচনা দ্বারা এড়িয়ে যাবে।

স্মার্ট পুনর্গঠন সাহায্য করার জন্য অতিরিক্ত তথ্য যোগ করুন

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

@Composable
fun MoviesScreen(movies: List<Movie>) {
    Column {
        for (movie in movies) {
            // MovieOverview composables are placed in Composition given its
            // index position in the for loop
            MovieOverview(movie)
        }
    }
}

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

তালিকার নীচে একটি নতুন উপাদান যোগ করা হলে পূর্ববর্তী কোডটি কীভাবে পুনর্গঠন করা হয় তা দেখানো চিত্র। তালিকার অন্যান্য আইটেমগুলি অবস্থান পরিবর্তন করেনি এবং পুনর্গঠন করা হয়নি।

চিত্র 4. তালিকার নীচে একটি নতুন উপাদান যোগ করা হলে কম্পোজিশনে MoviesScreen প্রতিনিধিত্ব। কম্পোজিশনের MovieOverview কম্পোজেবল পুনরায় ব্যবহার করা যেতে পারে। MovieOverview একই রঙের অর্থ হল কম্পোজেবলটি পুনরায় তৈরি করা হয়নি।

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

@Composable
fun MovieOverview(movie: Movie) {
    Column {
        // Side effect explained later in the docs. If MovieOverview
        // recomposes, while fetching the image is in progress,
        // it is cancelled and restarted.
        val image = loadNetworkImage(movie.url)
        MovieHeader(image)

        /* ... */
    }
}

তালিকার শীর্ষে একটি নতুন উপাদান যুক্ত হলে পূর্ববর্তী কোডটি কীভাবে পুনর্গঠন করা হয় তা দেখানো চিত্র। তালিকার প্রতিটি অন্যান্য আইটেম অবস্থান পরিবর্তন করে এবং পুনরায় রচনা করতে হবে।

চিত্র 5. তালিকায় একটি নতুন উপাদান যুক্ত হলে রচনাটিতে MoviesScreen প্রতিনিধিত্ব। MovieOverview কম্পোজেবল পুনরায় ব্যবহার করা যাবে না এবং সমস্ত পার্শ্ব প্রতিক্রিয়া পুনরায় চালু হবে। MovieOverview একটি ভিন্ন রঙের অর্থ হল কম্পোজেবলটি পুনর্গঠন করা হয়েছে।

আদর্শভাবে, আমরা MovieOverview ইন্সট্যান্সের পরিচয়টিকে movie পরিচয়ের সাথে সংযুক্ত হিসাবে ভাবতে চাই যা এটিকে পাস করা হয়েছে। আমরা যদি মুভির তালিকা পুনঃক্রম করি, আদর্শভাবে আমরা একইভাবে কম্পোজিশন ট্রিতে দৃষ্টান্তগুলিকে ভিন্ন মুভির দৃষ্টান্তের সাথে কম্পোজযোগ্য প্রতিটি MovieOverview পুনর্বিন্যাস করার পরিবর্তে পুনরায় সাজাতে পারি। কম্পোজ আপনাকে রানটাইম বলতে একটি উপায় প্রদান করে যে আপনি গাছের একটি প্রদত্ত অংশ সনাক্ত করতে কোন মানগুলি ব্যবহার করতে চান: key কম্পোজযোগ্য।

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

@Composable
fun MoviesScreenWithKey(movies: List<Movie>) {
    Column {
        for (movie in movies) {
            key(movie.id) { // Unique ID for this movie
                MovieOverview(movie)
            }
        }
    }
}

উপরের সাথে, তালিকার উপাদানগুলি পরিবর্তিত হলেও, রচনা MovieOverview পৃথক কলগুলিকে স্বীকৃতি দেয় এবং সেগুলি পুনরায় ব্যবহার করতে পারে।

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

চিত্র 6. তালিকায় একটি নতুন উপাদান যোগ করা হলে কম্পোজিশনে MoviesScreen প্রতিনিধিত্ব। যেহেতু MovieOverview কম্পোজেবলের অনন্য কী রয়েছে, তাই কম্পোজ শনাক্ত করে যে কোন MovieOverview দৃষ্টান্তগুলি পরিবর্তিত হয়নি এবং সেগুলি পুনরায় ব্যবহার করতে পারে; তাদের পার্শ্ব প্রতিক্রিয়া নির্বাহ অব্যাহত থাকবে।

কিছু কম্পোজেবলে key কম্পোজেবলের জন্য অন্তর্নির্মিত সমর্থন রয়েছে। উদাহরণস্বরূপ, LazyColumn items DSL-এ একটি কাস্টম key নির্দিষ্ট করে গ্রহণ করে।

@Composable
fun MoviesScreenLazy(movies: List<Movie>) {
    LazyColumn {
        items(movies, key = { movie -> movie.id }) { movie ->
            MovieOverview(movie)
        }
    }
}

ইনপুট পরিবর্তন না হলে এড়িয়ে যাওয়া

পুনর্গঠনের সময়, কিছু যোগ্য কম্পোজেবল ফাংশন তাদের সম্পাদন সম্পূর্ণভাবে এড়িয়ে যেতে পারে যদি তাদের ইনপুটগুলি পূর্ববর্তী রচনা থেকে পরিবর্তিত না হয়।

একটি সংমিশ্রণযোগ্য ফাংশন এড়িয়ে যাওয়ার জন্য যোগ্য যদি না :

  • ফাংশনের একটি নন- Unit রিটার্ন টাইপ আছে
  • ফাংশনটি @NonRestartableComposable বা @NonSkippableComposable দিয়ে টীকা করা হয়েছে
  • একটি প্রয়োজনীয় পরামিতি একটি অ-স্থিতিশীল ধরনের

একটি পরীক্ষামূলক কম্পাইলার মোড আছে, স্ট্রং স্কিপিং , যা শেষ প্রয়োজনীয়তাকে শিথিল করে।

একটি প্রকারকে স্থিতিশীল হিসাবে বিবেচনা করার জন্য এটি নিম্নলিখিত চুক্তি মেনে চলতে হবে:

  • দুই দৃষ্টান্তের জন্য equals ফলাফল চিরকাল একই দুই দৃষ্টান্তের জন্য একই হবে.
  • টাইপের কোনো পাবলিক প্রপার্টি পরিবর্তন হলে কম্পোজিশনকে অবহিত করা হবে।
  • সমস্ত সরকারী সম্পত্তির ধরনও স্থিতিশীল।

কিছু গুরুত্বপূর্ণ সাধারণ প্রকার রয়েছে যা এই চুক্তির মধ্যে পড়ে যেগুলি রচনা কম্পাইলার স্থিতিশীল হিসাবে বিবেচনা করবে, যদিও সেগুলি @Stable টীকা ব্যবহার করে স্পষ্টভাবে স্থিতিশীল হিসাবে চিহ্নিত করা হয়নি:

  • সমস্ত আদিম মান প্রকার: Boolean , Int , Long , Float , Char , ইত্যাদি
  • স্ট্রিংস
  • সমস্ত ফাংশন প্রকার (ল্যাম্বডাস)

এই সব ধরনের স্থিতিশীল চুক্তি অনুসরণ করতে সক্ষম কারণ তারা অপরিবর্তনীয়। যেহেতু অপরিবর্তনীয় প্রকারগুলি কখনই পরিবর্তিত হয় না, তাদের কখনই পরিবর্তনের রচনাকে অবহিত করতে হয় না, তাই এই চুক্তিটি অনুসরণ করা অনেক সহজ।

একটি উল্লেখযোগ্য প্রকার যা স্থিতিশীল কিন্তু পরিবর্তনযোগ্য তা হল কম্পোজের MutableState প্রকার। যদি একটি মান একটি MutableState এ রাখা হয়, তাহলে রাষ্ট্রীয় বস্তুটিকে সামগ্রিকভাবে স্থিতিশীল বলে মনে করা হয় কারণ Compose-কে State .value সম্পত্তিতে কোনো পরিবর্তনের বিষয়ে অবহিত করা হবে।

যখন কম্পোজেবলে প্যারামিটার হিসাবে পাস করা সমস্ত প্রকার স্থিতিশীল থাকে, তখন UI ট্রিতে কম্পোজযোগ্য অবস্থানের উপর ভিত্তি করে সমতার জন্য প্যারামিটারের মান তুলনা করা হয়। পূর্ববর্তী কল থেকে সমস্ত মান অপরিবর্তিত থাকলে পুনর্গঠন বাদ দেওয়া হয়।

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

যদি কম্পোজ অনুমান করতে না পারে যে একটি টাইপ স্থিতিশীল, কিন্তু আপনি কম্পোজকে এটিকে স্থিতিশীল হিসাবে বিবেচনা করতে বাধ্য করতে চান, এটিকে @Stable টীকা দিয়ে চিহ্নিত করুন।

// Marking the type as stable to favor skipping and smart recompositions.
@Stable
interface UiState<T : Result<T>> {
    val value: T?
    val exception: Throwable?

    val hasError: Boolean
        get() = exception != null
}

উপরের কোড স্নিপেটে, যেহেতু UiState একটি ইন্টারফেস, তাই কম্পোজ সাধারণত এই প্রকারটিকে স্থিতিশীল নয় বলে বিবেচনা করতে পারে। @Stable টীকা যোগ করার মাধ্যমে, আপনি রচনাকে বলবেন যে এই প্রকারটি স্থিতিশীল, কম্পোজকে স্মার্ট পুনর্গঠনের পক্ষে অনুমতি দেয়। এর মানে হল যে কম্পোজ তার সমস্ত বাস্তবায়নকে স্থিতিশীল হিসাবে বিবেচনা করবে যদি ইন্টারফেসটি প্যারামিটার টাইপ হিসাবে ব্যবহার করা হয়।

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