নেস্টেড গ্রাফ

আপনার অ্যাপের ভেতরের লগইন ফ্লো, উইজার্ড বা অন্যান্য সাবফ্লো সাধারণত নেস্টেড ন্যাভিগেশন গ্রাফ হিসেবে সবচেয়ে ভালোভাবে উপস্থাপন করা যায়। এভাবে স্বয়ংসম্পূর্ণ সাবন্যাভিগেশন ফ্লোগুলোকে নেস্ট করার মাধ্যমে আপনার অ্যাপের UI-এর মূল ফ্লো বোঝা এবং পরিচালনা করা সহজ হয়।

এছাড়াও, নেস্টেড গ্রাফগুলো পুনঃব্যবহারযোগ্য। এগুলো এক ধরনের এনক্যাপসুলেশনও প্রদান করে—নেস্টেড গ্রাফের বাইরের ডেস্টিনেশনগুলো এর ভেতরের কোনো ডেস্টিনেশনে সরাসরি অ্যাক্সেস পায় না। এর পরিবর্তে, তাদের সরাসরি নেস্টেড গ্রাফটিতেই navigate() করা উচিত, যেখানে গ্রাফের বাকি অংশকে প্রভাবিত না করেই অভ্যন্তরীণ লজিক পরিবর্তন করা যায়।

উদাহরণ

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

চিত্র ১. একটি শীর্ষ-স্তরের নেভিগেশন গ্রাফ।

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

সর্বোত্তম অনুশীলন হিসেবে, ম্যাচ স্ক্রিনটিকে শীর্ষ-স্তরের নেভিগেশন গ্রাফের শুরুর গন্তব্য হিসেবে সেট করুন এবং টাইটেল ও রেজিস্টার স্ক্রিনগুলোকে একটি নেস্টেড গ্রাফে সরিয়ে নিন, যেমনটি চিত্র ১-এ দেখানো হয়েছে:

চিত্র ২। শীর্ষ-স্তরের নেভিগেশন গ্রাফটিতে এখন একটি নেস্টেড গ্রাফ রয়েছে।

ম্যাচ স্ক্রিন চালু হলে, কোনো নিবন্ধিত ব্যবহারকারী আছেন কিনা তা পরীক্ষা করুন। ব্যবহারকারী নিবন্ধিত না থাকলে, তাকে নিবন্ধন স্ক্রিনে নিয়ে যান।

শর্তসাপেক্ষ নেভিগেশন পরিস্থিতি সম্পর্কে আরও তথ্যের জন্য, শর্তসাপেক্ষ নেভিগেশন দেখুন।

রচনা করুন

Compose ব্যবহার করে একটি নেস্টেড ন্যাভিগেশন গ্রাফ তৈরি করতে, NavGraphBuilder.navigation() ফাংশনটি ব্যবহার করুন। একটি গ্রাফে ডেস্টিনেশন যোগ করার সময়, আপনি NavGraphBuilder.composable() এবং NavGraphBuilder.dialog() ফাংশনগুলোর মতোই navigation() ফাংশনটি ব্যবহার করেন।

মূল পার্থক্য হলো, navigation একটি নতুন গন্তব্যের পরিবর্তে একটি নেস্টেড গ্রাফ তৈরি করে। এরপর সেই নেস্টেড গ্রাফে গন্তব্য যোগ করার জন্য navigation() এর ল্যাম্বডার মধ্যে composable() এবং dialog() কল করা হয়।

নিচের কোড স্নিপেটটি কীভাবে Compose ব্যবহার করে চিত্র ২-এর গ্রাফটি বাস্তবায়ন করে তা বিবেচনা করুন:

// Routes
@Serializable object Title
@Serializable object Register

// Route for nested graph
@Serializable object Game

// Routes inside nested graph
@Serializable object Match
@Serializable object InGame
@Serializable object ResultsWinner
@Serializable object GameOver

NavHost(navController, startDestination = Title) {
   composable<Title> {
       TitleScreen(
           onPlayClicked = { navController.navigate(route = Register) },
           onLeaderboardsClicked = { /* Navigate to leaderboards */ }
       )
   }
   composable<Register> {
       RegisterScreen(
           onSignUpComplete = { navController.navigate(route = Game) }
       )
   }
   navigation<Game>(startDestination = Match) {
       composable<Match> {
           MatchScreen(
               onStartGame = { navController.navigate(route = InGame) }
           )
       }
       composable<InGame> {
           InGameScreen(
               onGameWin = { navController.navigate(route = ResultsWinner) },
               onGameLose = { navController.navigate(route = GameOver) }
           )
       }
       composable<ResultsWinner> {
           ResultsWinnerScreen(
               onNextMatchClicked = {
                   navController.navigate(route = Match) {
                       popUpTo(route = Match) { inclusive = true }
                   }
               },
               onLeaderboardsClicked = { /* Navigate to leaderboards */ }
           )
       }
       composable<GameOver> {
           GameOverScreen(
               onTryAgainClicked = {
                   navController.navigate(route = Match) {
                       popUpTo(route = Match) { inclusive = true }
                   }
               }
           )
       }
   }
}

সরাসরি কোনো নেস্টেড গন্তব্যে যেতে , অন্য যেকোনো গন্তব্যের মতোই একটি রাউট টাইপ ব্যবহার করুন। এর কারণ হলো, রাউট একটি গ্লোবাল ধারণা যা এমন গন্তব্য শনাক্ত করতে ব্যবহৃত হয় যেখানে যেকোনো স্ক্রিন থেকে নেভিগেট করা যায়:

navController.navigate(route = Match)

এক্সএমএল

XML ব্যবহার করার সময়, আপনি নেভিগেশন এডিটর ব্যবহার করে আপনার নেস্টেড গ্রাফ তৈরি করতে পারেন। তা করতে এই ধাপগুলো অনুসরণ করুন:

  1. নেভিগেশন এডিটরে, Shift কী চেপে ধরে রাখুন এবং নেস্টেড গ্রাফে অন্তর্ভুক্ত করতে চান এমন গন্তব্যগুলিতে ক্লিক করুন।
  2. কনটেক্সট মেনু খুলতে রাইট-ক্লিক করুন এবং 'Move to Nested Graph > New Graph' নির্বাচন করুন। গন্তব্যস্থলগুলো একটি নেস্টেড গ্রাফের মধ্যে আবদ্ধ থাকে। চিত্র ২-এ নেভিগেশন এডিটরে একটি নেস্টেড গ্রাফ দেখানো হয়েছে:

    চিত্র ২. নেভিগেশন এডিটরে নেস্টেড গ্রাফ
  3. নেস্টেড গ্রাফটিতে ক্লিক করুন। অ্যাট্রিবিউটস প্যানেলে নিম্নলিখিত অ্যাট্রিবিউটগুলো প্রদর্শিত হবে:

    • টাইপ করুন , যেটিতে "নেস্টেড গ্রাফ" রয়েছে
    • ID , যেখানে নেস্টেড গ্রাফের জন্য সিস্টেম-নির্ধারিত একটি আইডি থাকে। আপনার কোড থেকে নেস্টেড গ্রাফটিকে রেফারেন্স করার জন্য এই আইডিটি ব্যবহৃত হয়।
  4. নেস্টেড গ্রাফটির গন্তব্যগুলো দেখতে সেটির উপর ডাবল-ক্লিক করুন।

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

    <?xml version="1.0" encoding="utf-8"?>
    <navigation xmlns:app="http://schemas.android.com/apk/res-auto"
       xmlns:tools="http://schemas.android.com/tools"
       xmlns:android="http://schemas.android.com/apk/res/android"
       app:startDestination="@id/mainFragment">
       <fragment
           android:id="@+id/mainFragment"
           android:name="com.example.cashdog.cashdog.MainFragment"
           android:label="fragment_main"
           tools:layout="@layout/fragment_main" >
           <action
               android:id="@+id/action_mainFragment_to_sendMoneyGraph"
               app:destination="@id/sendMoneyGraph" />
           <action
               android:id="@+id/action_mainFragment_to_viewBalanceFragment"
               app:destination="@id/viewBalanceFragment" />
       </fragment>
       <fragment
           android:id="@+id/viewBalanceFragment"
           android:name="com.example.cashdog.cashdog.ViewBalanceFragment"
           android:label="fragment_view_balance"
           tools:layout="@layout/fragment_view_balance" />
       <navigation android:id="@+id/sendMoneyGraph" app:startDestination="@id/chooseRecipient">
           <fragment
               android:id="@+id/chooseRecipient"
               android:name="com.example.cashdog.cashdog.ChooseRecipient"
               android:label="fragment_choose_recipient"
               tools:layout="@layout/fragment_choose_recipient">
               <action
                   android:id="@+id/action_chooseRecipient_to_chooseAmountFragment"
                   app:destination="@id/chooseAmountFragment" />
           </fragment>
           <fragment
               android:id="@+id/chooseAmountFragment"
               android:name="com.example.cashdog.cashdog.ChooseAmountFragment"
               android:label="fragment_choose_amount"
               tools:layout="@layout/fragment_choose_amount" />
       </navigation>
    </navigation>
    
  6. আপনার কোডে, রুট গ্রাফকে নেস্টেড গ্রাফের সাথে সংযোগকারী অ্যাকশনটির রিসোর্স আইডি পাস করুন:

কোটলিন

view.findNavController().navigate(R.id.action_mainFragment_to_sendMoneyGraph)

জাভা

Navigation.findNavController(view).navigate(R.id.action_mainFragment_to_sendMoneyGraph);
  1. ডিজাইন ট্যাবে ফিরে যেতে, রুট-এ ক্লিক করে মূল গ্রাফে ফিরে যান।

অন্যান্য নেভিগেশন গ্রাফগুলিকে অন্তর্ভুক্ত করে উল্লেখ করুন

আপনার গ্রাফ কাঠামোকে মডিউলারাইজ করার আরেকটি উপায় হলো প্যারেন্ট নেভিগেশন গ্রাফে একটি <include> এলিমেন্ট ব্যবহার করে একটি গ্রাফের মধ্যে অন্য একটি গ্রাফ অন্তর্ভুক্ত করা । এর ফলে অন্তর্ভুক্ত গ্রাফটিকে সম্পূর্ণ আলাদা একটি মডিউল বা প্রজেক্টে সংজ্ঞায়িত করা যায়, যা পুনঃব্যবহারযোগ্যতা সর্বোচ্চ করে তোলে।

নিচের কোড স্নিপেটটি দেখায় কিভাবে আপনি <include> ব্যবহার করতে পারেন:

<!-- (root) nav_graph.xml -->
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/fragment">

    <include app:graph="@navigation/included_graph" />

    <fragment
        android:id="@+id/fragment"
        android:name="com.example.myapplication.BlankFragment"
        android:label="Fragment in Root Graph"
        tools:layout="@layout/fragment_blank">
        <action
            android:id="@+id/action_fragment_to_second_graph"
            app:destination="@id/second_graph" />
    </fragment>

    ...
</navigation>
<!-- included_graph.xml -->
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/second_graph"
    app:startDestination="@id/includedStart">

    <fragment
        android:id="@+id/includedStart"
        android:name="com.example.myapplication.IncludedStart"
        android:label="fragment_included_start"
        tools:layout="@layout/fragment_included_start" />
</navigation>