নেভিগেশন কম্পোনেন্টে মাইগ্রেট করা

নেভিগেশন কম্পোনেন্ট হল একটি লাইব্রেরি যা জটিল নেভিগেশন, ট্রানজিশন অ্যানিমেশন, ডিপ লিঙ্কিং এবং আপনার অ্যাপের স্ক্রিনের মধ্যে কম্পাইল-টাইম চেক করা আর্গুমেন্ট পাসিং ম্যানেজ করতে পারে।

এই ডকুমেন্টটি নেভিগেশন কম্পোনেন্ট ব্যবহার করার জন্য আগে থেকে থাকা অ্যাপ মাইগ্রেট করার জন্য একটি সাধারণ-উদ্দেশ্য নির্দেশিকা হিসেবে কাজ করে।

উচ্চ স্তরে, মাইগ্রেশনের সাথে এইসব ধাপ জড়িত:

  1. অ্যাক্টিভিটি থেকে স্ক্রিন-নির্দিষ্ট UI লজিক সরিয়ে দিন - আপনার অ্যাপের UI লজিক অ্যাক্টিভিটি থেকে সরিয়ে দিন, যাতে প্রতিটি অ্যাক্টিভিটি শুধুমাত্র গ্লোবাল নেভিগেশন UI কম্পোনেন্টের লজিক মালিকানা পায়, যেমন Toolbar, প্রতিটি স্ক্রিনের ইমপ্লিমেন্টেশন ফ্র্যাগমেন্ট বা কাস্টম ডেস্টিনেশনে ডেলিগেট করার সময়।

  2. নেভিগেশন কম্পোনেন্ট ইন্টিগ্রেট করা - প্রতিটি অ্যাক্টিভিটির জন্য, একটি নেভিগেশন গ্রাফ তৈরি করুন যাতে সেই অ্যাক্টিভিটি দ্বারা ম্যানেজ করা এক বা একাধিক ফ্র্যাগমেন্ট থাকে। ফ্র্যাগমেন্ট ট্রানজ্যাকশনকে নেভিগেশন কম্পোনেন্ট অপারেশনের মাধ্যমে পরিবর্তন করুন।

  3. অ্যাক্টিভিটি ডেস্টিনেশন যোগ করুন - অ্যাক্টিভিটি ডেস্টিনেশন ব্যবহার করে startActivity()টি কল অ্যাকশন দিয়ে পরিবর্তন করুন।

  4. অ্যাক্টিভিটি একত্রিত করা - একাধিক অ্যাক্টিভিটি একই লেআউট শেয়ার করলে, নেভিগেশন গ্রাফ একত্রিত করুন।

পূর্বশর্ত

এই নির্দেশিকা ধরে নেয় যে আপনি ইতিমধ্যেই আপনার অ্যাপকে AndroidX লাইব্রেরি ব্যবহার করার জন্য মাইগ্রেট করেছেন। আপনি যদি তা না করে থাকেন, তাহলে AndroidX ব্যবহার করার জন্য আপনার প্রোজেক্ট মাইগ্রেট করুন।

অ্যাক্টিভিটি থেকে স্ক্রিন-নির্দিষ্ট UI লজিক সরিয়ে দিন

অ্যাক্টিভিটি হল সিস্টেম-লেভেল কম্পোনেন্ট যা আপনার অ্যাপ ও Android-এর মধ্যে গ্রাফিক্যাল ইন্টার‍্যাকশন সহজ করে তোলে। অ্যাক্টিভিটি আপনার অ্যাপের ম্যানিফেস্টে রেজিস্টার করা হয় যাতে Android জানতে পারে যে কোন অ্যাক্টিভিটি লঞ্চ করার জন্য উপলভ্য। এছাড়াও, অ্যাক্টিভিটি ক্লাস আপনার অ্যাপকে Android-এর পরিবর্তনের সাথে মানিয়ে নিতে সাহায্য করে, যেমন আপনার অ্যাপের UI ফোরগ্রাউন্ডে প্রবেশ করছে বা ছেড়ে যাচ্ছে, রোটেট করছে ইত্যাদি। অ্যাক্টিভিটি স্ক্রিনের মধ্যে স্টেট শেয়ার করার জায়গা হিসেবেও কাজ করতে পারে।

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

আপনার অ্যাপ ফ্র্যাগমেন্ট ব্যবহার না করলে, আপনাকে প্রথমে অ্যাপের প্রতিটি স্ক্রিন ফ্র্যাগমেন্ট ব্যবহার করার জন্য মাইগ্রেট করতে হবে। আপনি এই মুহূর্তে অ্যাক্টিভিটি মুছছেন না। বরং, আপনি স্ক্রিন দেখানোর জন্য ফ্র্যাগমেন্ট তৈরি করছেন এবং দায়িত্ব অনুযায়ী UI লজিককে আলাদা করছেন।

ফ্র্যাগমেন্ট এসে গেছে

ফ্র্যাগমেন্ট যোগ করার প্রসেসটি ব্যাখ্যা করার জন্য, আসুন দুটি স্ক্রিন নিয়ে গঠিত একটি অ্যাপ্লিকেশনের উদাহরণ দিয়ে শুরু করা যাক: একটি প্রোডাক্টের তালিকা স্ক্রিন এবং একটি প্রোডাক্টের বিবরণ স্ক্রিন। তালিকার স্ক্রিনে কোনও প্রোডাক্টে ক্লিক করলে ব্যবহারকারীকে প্রোডাক্টের ব্যাপারে আরও জানতে বিবরণ স্ক্রিনে নিয়ে যাওয়া হয়।

এই উদাহরণে, তালিকা ও বিবরণের স্ক্রিন বর্তমানে আলাদা অ্যাক্টিভিটি।

UI হোস্ট করার জন্য নতুন লেআউট তৈরি করুন

ফ্র্যাগমেন্টের সাথে পরিচয় করাতে, ফ্র্যাগমেন্ট হোস্ট করার অ্যাক্টিভিটির জন্য নতুন লেআউট ফাইল তৈরি করে শুরু করুন। এটি অ্যাক্টিভিটির বর্তমান কন্টেন্ট ভিউ লেআউট পরিবর্তন করে।

সহজ ভিউয়ের জন্য, আপনি FrameLayout ব্যবহার করতে পারেন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে product_list_host:

<FrameLayout
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/main_content"
   android:layout_height="match_parent"
   android:layout_width="match_parent" />

id অ্যাট্রিবিউট কন্টেন্ট বিভাগকে বোঝায় যেখানে আমরা পরে ফ্র্যাগমেন্ট যোগ করি।

এরপর, আপনার অ্যাক্টিভিটির onCreate() ফাংশনে, লেআউট ফাইল রেফারেন্স পরিবর্তন করুন আপনার অ্যাক্টিভিটির onCreate ফাংশনে এই নতুন লেআউট ফাইল পয়েন্ট করতে:

Kotlin

class ProductListActivity : AppCompatActivity() {
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        // Replace setContentView(R.layout.product_list) with the line below
        setContentView(R.layout.product_list_host)
        ...
    }
}

জাভা

public class ProductListActivity extends AppCompatActivity {
    ...
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        ...
        // Replace setContentView(R.layout.product_list); with the line below
        setContentView(R.layout.product_list_host);
        ...
    }
}

আপনি যে ফ্র্যাগমেন্ট তৈরি করতে চলেছেন, সেটির রুট ভিউ হিসেবে আগে থেকে থাকা লেআউট (এই উদাহরণে, product_list) ব্যবহার করা হয়।

ফ্র্যাগমেন্ট তৈরি করুন

আপনার স্ক্রিনের UI ম্যানেজ করতে নতুন ফ্র্যাগমেন্ট তৈরি করুন। আপনার অ্যাক্টিভিটি হোস্টের নামের সাথে সামঞ্জস্য বজায় রাখা একটি ভালো অভ্যাস। নিচের স্নিপেট ProductListFragment ব্যবহার করে, যেমন:

Kotlin

class ProductListFragment : Fragment() {
    // Leave empty for now.
}

জাভা

public class ProductListFragment extends Fragment {
    // Leave empty for now.
}

অ্যাক্টিভিটি লজিককে ফ্র্যাগমেন্টে সরানো

ফ্র্যাগমেন্টের সংজ্ঞা ঠিক করার পরে, পরবর্তী ধাপ হল এই স্ক্রিনের জন্য UI লজিককে অ্যাক্টিভিটি থেকে এই নতুন ফ্র্যাগমেন্টে সরানো। আপনি যদি অ্যাক্টিভিটি-ভিত্তিক আর্কিটেকচার থেকে আসেন, তাহলে আপনার অ্যাক্টিভিটির onCreate() ফাংশনে অনেক ভিউ ক্রিয়েশন লজিক থাকতে পারে।

এখানে UI লজিক সহ অ্যাক্টিভিটি-ভিত্তিক স্ক্রিনের একটি উদাহরণ দেওয়া হল যা আমাদের সরাতে হবে:

Kotlin

class ProductListActivity : AppCompatActivity() {

    // Views and/or ViewDataBinding references, Adapters...
    private lateinit var productAdapter: ProductAdapter
    private lateinit var binding: ProductListActivityBinding

    ...

    // ViewModels, System Services, other Dependencies...
    private val viewModel: ProductListViewModel by viewModels()

    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // View initialization logic
        DataBindingUtil.setContentView(this, R.layout.product_list_activity)

        // Post view initialization logic
        // Connect adapters
        productAdapter = ProductAdapter(productClickCallback)
        binding.productsList.setAdapter(productAdapter)

        // Initialize view properties, set click listeners, etc.
        binding.productsSearchBtn.setOnClickListener {...}

        // Subscribe to state
        viewModel.products.observe(this, Observer { myProducts ->
            ...
        })

        // ...and so on
    }
   ...
}

জাভা

public class ProductListActivity extends AppCompatActivity {

    // Views and/or ViewDataBinding references, adapters...
    private ProductAdapter productAdapter;
    private ProductListActivityBinding binding;

    ...

    // ViewModels, system services, other dependencies...
    private ProductListViewModel viewModel;

    ...

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // View initialization logic
        DataBindingUtil.setContentView(this, R.layout.product_list_activity);

        // Post view initialization logic
        // Connect adapters
        productAdapter = new ProductAdapter(productClickCallback);
        binding.productsList.setAdapter(productAdapter);

        // Initialize ViewModels and other dependencies
        ProductListViewModel viewModel = new ViewModelProvider(this).get(ProductListViewModel.java);

        // Initialize view properties, set click listeners, etc.
        binding.productsSearchBtn.setOnClickListener(v -> { ... });

        // Subscribe to state
        viewModel.getProducts().observe(this, myProducts ->
            ...
       );

       // ...and so on
   }

এছাড়াও, আপনার অ্যাক্টিভিটি হয়ত ব্যবহারকারী কখন এবং কীভাবে পরবর্তী স্ক্রিনে নেভিগেট করবেন তা কন্ট্রোল করছে, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

Kotlin

    // Provided to ProductAdapter in ProductListActivity snippet.
    private val productClickCallback = ProductClickCallback { product ->
        show(product)
    }

    fun show(product: Product) {
        val intent = Intent(this, ProductActivity::class.java)
        intent.putExtra(ProductActivity.KEY_PRODUCT_ID, product.id)
        startActivity(intent)
    }

জাভা

// Provided to ProductAdapter in ProductListActivity snippet.
private ProductClickCallback productClickCallback = this::show;

private void show(Product product) {
    Intent intent = new Intent(this, ProductActivity.class);
    intent.putExtra(ProductActivity.KEY_PRODUCT_ID, product.getId());
    startActivity(intent);
}

আপনার ফ্র্যাগমেন্টের মধ্যে, আপনি এই কাজ onCreateView() এবং onViewCreated()-এর মধ্যে ভাগ করেন, অ্যাক্টিভিটিতে শুধুমাত্র নেভিগেশন লজিক বাকি থাকে:

Kotlin

class ProductListFragment : Fragment() {

    private lateinit var binding: ProductListFragmentBinding
    private val viewModel: ProductListViewModel by viewModels()

     // View initialization logic
    override fun onCreateView(inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?): View? {
        binding = DataBindingUtil.inflate(
                inflater,
                R.layout.product_list,
                container,
                false
        )
        return binding.root
    }

    // Post view initialization logic
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // Connect adapters
        productAdapter = ProductAdapter(productClickCallback)
        binding.productsList.setAdapter(productAdapter)

        // Initialize view properties, set click listeners, etc.
        binding.productsSearchBtn.setOnClickListener {...}

        // Subscribe to state
        viewModel.products.observe(this, Observer { myProducts ->
            ...
        })

        // ...and so on
    }

    // Provided to ProductAdapter
    private val productClickCallback = ProductClickCallback { product ->
        if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
            (requireActivity() as ProductListActivity).show(product)
        }
    }
    ...
}

জাভা

public class ProductListFragment extends Fragment {

    private ProductAdapter productAdapter;
    private ProductListFragmentBinding binding;

    // View initialization logic
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
            @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {
        binding = DataBindingUtil.inflate(
                inflater,
                R.layout.product_list_fragment,
                container,
                false);
        return binding.getRoot();
    }

    // Post view initialization logic
    @Override
    public void onViewCreated(@NonNull View view,
            @Nullable Bundle savedInstanceState) {

        // Connect adapters
        binding.productsList.setAdapter(productAdapter);

        // Initialize ViewModels and other dependencies
        ProductListViewModel viewModel = new ViewModelProvider(this)
                .get(ProductListViewModel.class);

        // Initialize view properties, set click listeners, etc.
        binding.productsSearchBtn.setOnClickListener(...)

        // Subscribe to state
        viewModel.getProducts().observe(this, myProducts -> {
            ...
       });

       // ...and so on

    // Provided to ProductAdapter
    private ProductClickCallback productClickCallback = new ProductClickCallback() {
        @Override
        public void onClick(Product product) {
            if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
                ((ProductListActivity) requireActivity()).show(product);
            }
        }
    };
    ...
}

ProductListFragment-এ লক্ষ্য করুন যে লেআউট ইনফ্লেট ও কানেক্ট করার জন্য setContentView() -এ কোনও কল নেই। ফ্র্যাগমেন্টে, onCreateView() রুট ভিউ ইনিশিয়ালাইজ করে। onCreateView(), LayoutInflater-এর একটি ইনস্ট্যান্স নেয় যা লেআউট রিসোর্স ফাইলের উপর ভিত্তি করে রুট ভিউ ইনফ্লেট করতে ব্যবহার করা যেতে পারে। এই উদাহরণটি আগে থেকে থাকা product_list লেআউট আবার ব্যবহার করে, যা অ্যাক্টিভিটি ব্যবহার করেছিল, কারণ লেআউটে কোনও পরিবর্তন করার প্রয়োজন নেই।

আপনার অ্যাক্টিভিটির onStart(), onResume(), onPause() বা onStop() ফাংশনে নেভিগেশনের সাথে সম্পর্কিত নয় এমন কোনও UI লজিক থাকলে, আপনি সেগুলিকে ফ্র্যাগমেন্টে একই নামের সংশ্লিষ্ট ফাংশনে সরাতে পারেন।

হোস্ট অ্যাক্টিভিটিতে ফ্র্যাগমেন্ট শুরু করুন

আপনি ফ্র্যাগমেন্টে সব UI লজিক সরিয়ে নিয়ে গেলে, অ্যাক্টিভিটিতে শুধু নেভিগেশন লজিক থাকবে।

Kotlin

class ProductListActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.product_list_host)
    }

    fun show(product: Product) {
        val intent = Intent(this, ProductActivity::class.java)
        intent.putExtra(ProductActivity.KEY_PRODUCT_ID, product.id)
        startActivity(intent)
    }
}

জাভা

public class ProductListActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.product_list_host);
    }

    public void show(Product product) {
        Intent intent = new Intent(this, ProductActivity.class);
        intent.putExtra(ProductActivity.KEY_PRODUCT_ID, product.getId());
        startActivity(intent);
    }
}

শেষ ধাপ হল onCreate()-এ ফ্র্যাগমেন্টের একটি ইনস্ট্যান্স তৈরি করা, ঠিক কন্টেন্ট ভিউ সেট করার পরে:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.product_list_host)

    if (savedInstanceState == null) {
        val fragment = ProductListFragment()
        supportFragmentManager
                .beginTransaction()
                .add(R.id.main_content, fragment)
                .commit()
    }
}

জাভা

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.product_list_host);

    if (savedInstanceState == null) {
        ProductListFragment fragment = new ProductListFragment();
        getSupportFragmentManager()
                .beginTransaction()
                .add(R.id.main_content, fragment)
                .commit();
    }
}

এই উদাহরণে যেমন দেখানো হয়েছে, কনফিগারেশন পরিবর্তনের সময় FragmentManager অটোমেটিক ফ্র্যাগমেন্ট সেভ ও রিস্টোর করে, তাই savedInstanceState নাল হলে আপনাকে শুধু ফ্র্যাগমেন্ট যোগ করতে হবে।

ফ্র্যাগমেন্টে ইনটেন্ট এক্সট্রা পাস করুন

আপনার অ্যাক্টিভিটি কোনও ইনটেন্টের মাধ্যমে Extras পেলে, আপনি এগুলি সরাসরি ফ্র্যাগমেন্টে আর্গুমেন্ট হিসেবে পাস করতে পারবেন।

এই উদাহরণে, ProductDetailsFragment সরাসরি অ্যাক্টিভিটির ইনটেন্ট এক্সট্রা থেকে আর্গুমেন্ট পায়:

Kotlin

...

if (savedInstanceState == null) {
    val fragment = ProductDetailsFragment()

    // Intent extras and Fragment Args are both of type android.os.Bundle.
    fragment.arguments = intent.extras

    supportFragmentManager
            .beginTransaction()
            .add(R.id.main_content, fragment)
            .commit()
}

...

জাভা

...

if (savedInstanceState == null) {
    ProductDetailsFragment fragment = new ProductDetailsFragment();

    // Intent extras and fragment Args are both of type android.os.Bundle.
    fragment.setArguments(getIntent().getExtras());

    getSupportFragmentManager()
            .beginTransaction()
            .add(R.id.main_content, fragment)
            .commit();
}

...

এই পর্যায়ে, আপনি ফ্র্যাগমেন্ট ব্যবহার করার জন্য আপডেট করা প্রথম স্ক্রিনের সাথে আপনার অ্যাপ রান করার বিষয়টি টেস্ট করতে পারবেন। আপনার বাকি অ্যাক্টিভিটি-ভিত্তিক স্ক্রিন মাইগ্রেট করা চালিয়ে যান, প্রতিটি ইটারেশনের পরে পরীক্ষা করার জন্য সময় নিন।

নেভিগেশন কম্পোনেন্ট ইন্টিগ্রেট করা

ফ্র্যাগমেন্ট-ভিত্তিক আর্কিটেকচার ব্যবহার করা শুরু করার পরে, আপনি নেভিগেশন কম্পোনেন্ট ইন্টিগ্রেট করা শুরু করার জন্য প্রস্তুত।

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

নেভিগেশন গ্রাফ তৈরি করো

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

নেভিগেশন গ্রাফ তৈরি করতে, navigation নামে একটি নতুন রিসোর্স ফোল্ডার তৈরি করে শুরু করুন। গ্রাফ যোগ করতে, এই ডিরেক্টরিতে ডানদিকের বোতামে ক্লিক করুন এবং নতুন > নেভিগেশন রিসোর্স ফাইল বিকল্প বেছে নিন।

নেভিগেশন কম্পোনেন্ট একটি অ্যাক্টিভিটিকে নেভিগেশনের হোস্ট হিসেবে ব্যবহার করে এবং আপনার ব্যবহারকারীরা আপনার অ্যাপের মাধ্যমে নেভিগেট করার সময় সেই হোস্টে পৃথক ফ্র্যাগমেন্ট সোয়্যাপ করে। আপনি আপনার অ্যাপের নেভিগেশন ভিজ্যুয়ালি লেআউট করা শুরু করার আগে, আপনাকে এই গ্রাফ হোস্ট করতে চলেছে এমন অ্যাক্টিভিটির মধ্যে একটি NavHost কনফিগার করতে হবে। যেহেতু আমরা ফ্র্যাগমেন্ট ব্যবহার করছি, তাই আমরা নেভিগেশন কম্পোনেন্টের ডিফল্ট NavHost ইমপ্লিমেন্টেশন ব্যবহার করতে পারি, NavHostFragment.

NavHostFragment, হোস্ট অ্যাক্টিভিটির মধ্যে থাকা FragmentContainerView-এর মাধ্যমে কনফিগার করা হয়, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

<androidx.fragment.app.FragmentContainerView
   android:name="androidx.navigation.fragment.NavHostFragment"
   app:navGraph="@navigation/product_list_graph"
   app:defaultNavHost="true"
   android:id="@+id/main_content"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />

app:NavGraph অ্যাট্রিবিউট এই নেভিগেশন হোস্টের সাথে যুক্ত নেভিগেশন গ্রাফকে নির্দেশ করে। এই প্রপার্টি সেট করলে, তা নেভিগেশন গ্রাফকে ইনফ্লেট করে এবং NavHostFragment-এ গ্রাফ প্রপার্টি সেট করে। app:defaultNavHost অ্যাট্রিবিউট নিশ্চিত করে যে আপনার NavHostFragment সিস্টেমের 'ফিরে যান' বোতাম ইন্টারসেপ্ট করে।

আপনি যদি DrawerLayout বা BottomNavigationView-এর মতো টপ-লেভেল নেভিগেশন ব্যবহার করেন, তাহলে এই FragmentContainerView আপনার মূল কন্টেন্ট ভিউ এলিমেন্টকে পরিবর্তন করে। উদাহরণ দেখতে NavigationUI-এর মাধ্যমে UI কম্পোনেন্ট আপডেট করুন লিঙ্কে যান।

সহজ লেআউটের জন্য, আপনি এই FragmentContainerView এলিমেন্টকে রুট ViewGroup-এর চাইল্ড হিসেবে অন্তর্ভুক্ত করতে পারেন:

<FrameLayout
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_height="match_parent"
   android:layout_width="match_parent">

<androidx.fragment.app.FragmentContainerView
   android:id="@+id/main_content"
   android:name="androidx.navigation.fragment.NavHostFragment"
   app:navGraph="@navigation/product_list_graph"
   app:defaultNavHost="true"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />

</FrameLayout>

আপনি নিচে ডিজাইন ট্যাবে ক্লিক করলে, নিচে দেখানো গ্রাফের মতো একটি গ্রাফ দেখতে পাবেন। গ্রাফের উপরে বাঁদিকে, গন্তব্য বিকল্পের অধীনে, আপনি NavHost অ্যাক্টিভিটির রেফারেন্স layout_name (resource_id) হিসেবে দেখতে পাবেন।

এই গ্রাফে আপনার ফ্র্যাগমেন্ট যোগ করতে, উপরের দিকে থাকা প্লাস বোতামে ক্লিক করুন।

নেভিগেশন কম্পোনেন্ট, আলাদা আলাদা স্ক্রিনকে গন্তব্য হিসেবে উল্লেখ করে। ডেস্টিনেশন ফ্র্যাগমেন্ট, অ্যাক্টিভিটি বা কাস্টম ডেস্টিনেশন হতে পারে। আপনি নিজের গ্রাফে যেকোনও ধরনের গন্তব্য যোগ করতে পারবেন, তবে মনে রাখবেন যে অ্যাক্টিভিটি গন্তব্যকে টার্মিনাল গন্তব্য হিসেবে বিবেচনা করা হয়, কারণ আপনি কোনও অ্যাক্টিভিটি গন্তব্যে নেভিগেট করলে, আপনি একটি আলাদা নেভিগেশন হোস্ট ও গ্রাফের মধ্যে অপারেট করেন।

নেভিগেশন কম্পোনেন্ট বলতে বোঝায়, ব্যবহারকারী যেভাবে অ্যাকশন হিসেবে এক গন্তব্য থেকে অন্য গন্তব্যে যান। এছাড়াও, অ্যাকশন ট্রানজিশন অ্যানিমেশন ও পপ আচরণ সম্পর্কে বর্ণনা করতে পারে।

ফ্র্যাগমেন্ট ট্রানজ্যাকশন সরান

আপনি এখন নেভিগেশন কম্পোনেন্ট ব্যবহার করছেন, তাই একই অ্যাক্টিভিটির অধীনে ফ্র্যাগমেন্ট-ভিত্তিক স্ক্রিনের মধ্যে নেভিগেট করলে, আপনি FragmentManager ইন্টার‍্যাকশন সরিয়ে দিতে পারবেন।

আপনার অ্যাপ যদি একই অ্যাক্টিভিটি বা ড্রয়ার লেআউট বা নিচের দিকে নেভিগেশনের মতো টপ-লেভেল নেভিগেশনের অধীনে একাধিক ফ্র্যাগমেন্ট ব্যবহার করে, তাহলে আপনি সম্ভবত আপনার UI-এর মূল কন্টেন্ট বিভাগে ফ্র্যাগমেন্ট যোগ করতে বা পরিবর্তন করতে FragmentManager এবং FragmentTransactions ব্যবহার করছেন। এটি এখন আপনার গ্রাফের মধ্যে গন্তব্য লিঙ্ক করার জন্য অ্যাকশন প্রদান করে এবং তারপরে NavController ব্যবহার করে নেভিগেট করার মাধ্যমে নেভিগেশন কম্পোনেন্ট ব্যবহার করে প্রতিস্থাপন এবং সরল করা যেতে পারে।

এখানে এমন কিছু পরিস্থিতি উল্লেখ করা হল যেগুলির সম্মুখীন আপনি হতে পারেন এবং প্রতিটি পরিস্থিতির জন্য কীভাবে মাইগ্রেশন করবেন তাও উল্লেখ করা হল।

একাধিক ফ্র্যাগমেন্ট ম্যানেজ করা একটি অ্যাক্টিভিটি

আপনার যদি এমন একটি অ্যাক্টিভিটি থাকে যা একাধিক ফ্র্যাগমেন্ট ম্যানেজ করে, তাহলে আপনার অ্যাক্টিভিটি কোডটি এইরকম দেখতে হতে পারে:

Kotlin

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Logic to load the starting destination
        //  when the Activity is first created
        if (savedInstanceState == null) {
            val fragment = ProductListFragment()
            supportFragmentManager.beginTransaction()
                    .add(R.id.fragment_container, fragment, ProductListFragment.TAG)
                    .commit()
        }
    }

    // Logic to navigate the user to another destination.
    // This may include logic to initialize and set arguments on the destination
    // fragment or even transition animations between the fragments (not shown here).
    fun navigateToProductDetail(productId: String) {
        val fragment = new ProductDetailsFragment()
        val args = Bundle().apply {
            putInt(KEY_PRODUCT_ID, productId)
        }
        fragment.arguments = args

        supportFragmentManager.beginTransaction()
                .addToBackStack(ProductDetailsFragment.TAG)
                .replace(R.id.fragment_container, fragment, ProductDetailsFragment.TAG)
                .commit()
    }
}

জাভা

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Logic to load the starting destination when the activity is first created.
        if (savedInstanceState == null) {
            val fragment = ProductListFragment()
            supportFragmentManager.beginTransaction()
                    .add(R.id.fragment_container, fragment, ProductListFragment.TAG)
                    .commit();
        }
    }

    // Logic to navigate the user to another destination.
    // This may include logic to initialize and set arguments on the destination
    // fragment or even transition animations between the fragments (not shown here).
    public void navigateToProductDetail(String productId) {
        Fragment fragment = new ProductDetailsFragment();
        Bundle args = new Bundle();
        args.putInt(KEY_PRODUCT_ID, productId);
        fragment.setArguments(args);

        getSupportFragmentManager().beginTransaction()
                .addToBackStack(ProductDetailsFragment.TAG)
                .replace(R.id.fragment_container, fragment, ProductDetailsFragment.TAG)
                .commit();
    }
}

সোর্স ডেস্টিনেশনের মধ্যে, আপনি হয়ত কোনও ইভেন্টের উত্তরে নেভিগেশন ফাংশন ইনভোক করছেন, যেমন নিচে দেখানো হয়েছে:

Kotlin

class ProductListFragment : Fragment() {
    ...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // In this example a callback is passed to respond to an item clicked
        //  in a RecyclerView
        productAdapter = ProductAdapter(productClickCallback)
        binding.productsList.setAdapter(productAdapter)
    }
    ...

    // The callback makes the call to the activity to make the transition.
    private val productClickCallback = ProductClickCallback { product ->
            (requireActivity() as MainActivity).navigateToProductDetail(product.id)
    }
}

জাভা

public class ProductListFragment extends Fragment  {
    ...
    @Override
    public void onViewCreated(@NonNull View view,
            @Nullable Bundle savedInstanceState) {
    // In this example a callback is passed to respond to an item clicked in a RecyclerView
        productAdapter = new ProductAdapter(productClickCallback);
        binding.productsList.setAdapter(productAdapter);
    }
    ...

    // The callback makes the call to the activity to make the transition.
    private ProductClickCallback productClickCallback = product -> (
        ((MainActivity) requireActivity()).navigateToProductDetail(product.getId())
    );
}

শুরুর গন্তব্য এবং আপনার গন্তব্য লিঙ্ক করার অ্যাকশন সেট করতে এবং যেখানে প্রয়োজন সেখানে আর্গুমেন্ট সংজ্ঞায়িত করতে আপনার নেভিগেশন গ্রাফ আপডেট করে এটি প্রতিস্থাপন করা যেতে পারে:

<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/product_list_graph"
    app:startDestination="@id/product_list">

    <fragment
        android:id="@+id/product_list"
        android:name="com.example.android.persistence.ui.ProductListFragment"
        android:label="Product List"
        tools:layout="@layout/product_list">
        <action
            android:id="@+id/navigate_to_product_detail"
            app:destination="@id/product_detail" />
    </fragment>
    <fragment
        android:id="@+id/product_detail"
        android:name="com.example.android.persistence.ui.ProductDetailFragment"
        android:label="Product Detail"
        tools:layout="@layout/product_detail">
        <argument
            android:name="product_id"
            app:argType="integer" />
    </fragment>
</navigation>

তারপর, আপনি নিজের অ্যাক্টিভিটি আপডেট করতে পারবেন:

Kotlin

class MainActivity : AppCompatActivity() {

    // No need to load the start destination, handled automatically by the Navigation component
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

জাভা

public class MainActivity extends AppCompatActivity {

    // No need to load the start destination, handled automatically by the Navigation component
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

অ্যাক্টিভিটির জন্য আর navigateToProductDetail() পদ্ধতির প্রয়োজন নেই। পরবর্তী বিভাগে, আমরা ProductListFragment আপডেট করি যাতে পরবর্তী প্রোডাক্টের বিবরণ স্ক্রিনে নেভিগেট করতে NavController ব্যবহার করা যায়।

নিরাপদে আর্গুমেন্ট পাস করা

নেভিগেশন কম্পোনেন্টে Safe Args নামে একটি Gradle প্লাগ-ইন আছে যা গন্তব্য ও অ্যাকশনের জন্য নির্দিষ্ট করা আর্গুমেন্টে টাইপ-সেফ অ্যাক্সেসের জন্য সহজ অবজেক্ট ও বিল্ডার ক্লাস তৈরি করে।

প্লাগ-ইন প্রয়োগ করা হয়ে গেলে, আপনার নেভিগেশন গ্রাফে কোনও গন্তব্যে সংজ্ঞায়িত যেকোনও আর্গুমেন্ট, নেভিগেশন কম্পোনেন্ট ফ্রেমওয়ার্ককে একটি Arguments ক্লাস তৈরি করতে বাধ্য করে যা টার্গেট গন্তব্যে টাইপ সেফ আর্গুমেন্ট প্রদান করে। কোনও অ্যাকশন নির্ধারণ করলে, প্লাগ-ইন একটি Directions কনফিগারেশন ক্লাস তৈরি করে যা ব্যবহারকারীকে কীভাবে টার্গেট গন্তব্যে নেভিগেট করতে হবে তা NavController-কে জানাতে ব্যবহার করা যেতে পারে। কোনও অ্যাকশন এমন কোনও গন্তব্যের দিকে নির্দেশ করলে যেখানে আর্গুমেন্ট প্রয়োজন, সেক্ষেত্রে জেনারেট করা Directions ক্লাসে কনস্ট্রাক্টর পদ্ধতি অন্তর্ভুক্ত থাকে, যেখানে এইসব প্যারামিটার প্রয়োজন।

ফ্র্যাগমেন্টের মধ্যে, টার্গেট গন্তব্যে টাইপ-সেফ আর্গুমেন্ট প্রদান করতে NavController এবং জেনারেট করা Directions ক্লাস ব্যবহার করুন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

Kotlin

class ProductListFragment : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // In this example a callback is passed to respond to an item clicked in a RecyclerView
        productAdapter = ProductAdapter(productClickCallback)
        binding.productsList.setAdapter(productAdapter)
    }
    ...

    // The callback makes the call to the NavController to make the transition.
    private val productClickCallback = ProductClickCallback { product ->
        val directions = ProductListDirections.navigateToProductDetail(product.id)
        findNavController().navigate(directions)
    }
}

জাভা

public class ProductListFragment extends Fragment  {
    ...
    @Override
    public void onViewCreated(@NonNull View view,
            @Nullable Bundle savedInstanceState) {
        // In this example a callback is passed to respond to an item clicked in a RecyclerView
        productAdapter = new ProductAdapter(productClickCallback);
        binding.productsList.setAdapter(productAdapter);
    }
    ...

    // The callback makes the call to the activity to make the transition.
    private ProductClickCallback productClickCallback = product -> {
        ProductListDirections.ViewProductDetails directions =
                ProductListDirections.navigateToProductDetail(product.getId());
        NavHostFragment.findNavController(this).navigate(directions);
    };
}

টপ-লেভেল নেভিগেশন

আপনার অ্যাপ DrawerLayout ব্যবহার করলে, আপনার অ্যাক্টিভিটিতে অনেক কনফিগারেশন লজিক থাকতে পারে যা ড্রয়ার খোলা ও বন্ধ করা এবং অন্যান্য গন্তব্যে নেভিগেট করা ম্যানেজ করে।

আপনার অ্যাক্টিভিটি হয়ত এইরকম দেখতে হবে:

Kotlin

class MainActivity : AppCompatActivity(),
    NavigationView.OnNavigationItemSelectedListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val toolbar: Toolbar = findViewById(R.id.toolbar)
        setSupportActionBar(toolbar)

        val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
        val navView: NavigationView = findViewById(R.id.nav_view)
        val toggle = ActionBarDrawerToggle(
                this,
                drawerLayout,
                toolbar,
                R.string.navigation_drawer_open, 
                R.string.navigation_drawer_close
        )
        drawerLayout.addDrawerListener(toggle)
        toggle.syncState()

        navView.setNavigationItemSelectedListener(this)
    }

    override fun onBackPressed() {
        val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.closeDrawer(GravityCompat.START)
        } else {
            super.onBackPressed()
        }
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        // Handle navigation view item clicks here.
        when (item.itemId) {
            R.id.home -> {
                val homeFragment = HomeFragment()
                show(homeFragment)
            }
            R.id.gallery -> {
                val galleryFragment = GalleryFragment()
                show(galleryFragment)
            }
            R.id.slide_show -> {
                val slideShowFragment = SlideShowFragment()
                show(slideShowFragment)
            }
            R.id.tools -> {
                val toolsFragment = ToolsFragment()
                show(toolsFragment)
            }
        }
        val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
        drawerLayout.closeDrawer(GravityCompat.START)
        return true
    }
}

private fun show(fragment: Fragment) {

    val drawerLayout = drawer_layout as DrawerLayout
    val fragmentManager = supportFragmentManager

    fragmentManager
            .beginTransaction()
            .replace(R.id.main_content, fragment)
            .commit()

    drawerLayout.closeDrawer(GravityCompat.START)
}

জাভা

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        NavigationView navigationView = findViewById(R.id.nav_view);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this,
                drawer,
                toolbar,
                R.string.navigation_drawer_open,
                R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        navigationView.setNavigationItemSelectedListener(this);
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.home) {
            Fragment homeFragment = new HomeFragment();
            show(homeFragment);
        } else if (id == R.id.gallery) {
            Fragment galleryFragment = new GalleryFragment();
            show(galleryFragment);
        } else if (id == R.id.slide_show) {
            Fragment slideShowFragment = new SlideShowFragment();
            show(slideShowFragment);
        } else if (id == R.id.tools) {
            Fragment toolsFragment = new ToolsFragment();
            show(toolsFragment);
        }

        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    private void show(Fragment fragment) {

        DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);
        FragmentManager fragmentManager = getSupportFragmentManager();

        fragmentManager
                .beginTransaction()
                .replace(R.id.main_content, fragment)
                .commit();

        drawerLayout.closeDrawer(GravityCompat.START);
    }
}

আপনার প্রোজেক্টে নেভিগেশন কম্পোনেন্ট যোগ করা এবং নেভিগেশন গ্রাফ তৈরি করার পরে, আপনার গ্রাফ থেকে প্রতিটি কন্টেন্ট ডেস্টিনেশন যোগ করুন (যেমন উপরের উদাহরণ থেকে হোম, গ্যালারি, স্লাইডশো এবং টুল)। নিশ্চিত করুন যে আপনার মেনু আইটেম id ভ্যালু তাদের সংশ্লিষ্ট গন্তব্য id ভ্যালুর সাথে মেলে, নিচে দেখানো হয়েছে:

<!-- activity_main_drawer.xml -->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:showIn="navigation_view">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/home"
            android:icon="@drawable/ic_menu_camera"
            android:title="@string/menu_home" />
        <item
            android:id="@+id/gallery"
            android:icon="@drawable/ic_menu_gallery"
            android:title="@string/menu_gallery" />
        <item
            android:id="@+id/slide_show"
            android:icon="@drawable/ic_menu_slideshow"
            android:title="@string/menu_slideshow" />
        <item
            android:id="@+id/tools"
            android:icon="@drawable/ic_menu_manage"
            android:title="@string/menu_tools" />
    </group>
</menu>
<!-- activity_main_graph.xml -->
<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/main_graph"
    app:startDestination="@id/home">

    <fragment
        android:id="@+id/home"
        android:name="com.example.HomeFragment"
        android:label="Home"
        tools:layout="@layout/home" />

    <fragment
        android:id="@+id/gallery"
        android:name="com.example.GalleryFragment"
        android:label="Gallery"
        tools:layout="@layout/gallery" />

    <fragment
        android:id="@+id/slide_show"
        android:name="com.example.SlideShowFragment"
        android:label="Slide Show"
        tools:layout="@layout/slide_show" />

    <fragment
        android:id="@+id/tools"
        android:name="com.example.ToolsFragment"
        android:label="Tools"
        tools:layout="@layout/tools" />

</navigation>

আপনার মেনু এবং গ্রাফ থেকে id ভ্যালু ম্যাচ করলে, আপনি এই অ্যাক্টিভিটির জন্য NavController ওয়্যার আপ করতে পারবেন যাতে মেনু আইটেমের উপর ভিত্তি করে অটোমেটিক নেভিগেশন ম্যানেজ করা যায়। এছাড়াও, NavController, DrawerLayout খোলা ও বন্ধ করা এবং 'উপরে' ও 'ফিরে যান' বোতামের আচরণ যথাযথভাবে ম্যানেজ করে।

আপনার MainActivity তারপর আপডেট করা যেতে পারে যাতে NavController-কে Toolbar এবং NavigationView-এর সাথে কানেক্ট করা যায়।

উদাহরণ হিসেবে নিচের স্নিপেট দেখুন:

Kotlin

class MainActivity : AppCompatActivity()  {

    val drawerLayout by lazy { findViewById<DrawerLayout>(R.id.drawer_layout) }
    val navController by lazy {
      (supportFragmentManager.findFragmentById(R.id.main_content) as NavHostFragment).navController
    }
    val navigationView by lazy { findViewById<NavigationView>(R.id.nav_view) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val toolbar = findViewById<Toolbar>(R.id.toolbar)
        setSupportActionBar(toolbar)

        // Show and Manage the Drawer and Back Icon
        setupActionBarWithNavController(navController, drawerLayout)

        // Handle Navigation item clicks
        // This works with no further action on your part if the menu and destination id’s match.
        navigationView.setupWithNavController(navController)

    }

    override fun onSupportNavigateUp(): Boolean {
        // Allows NavigationUI to support proper up navigation or the drawer layout
        // drawer menu, depending on the situation
        return navController.navigateUp(drawerLayout)
    }
}

জাভা

public class MainActivity extends AppCompatActivity {

    private DrawerLayout drawerLayout;
    private NavController navController;
    private NavigationView navigationView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        drawerLayout = findViewById(R.id.drawer_layout);
        NavHostFragment navHostFragment = (NavHostFragment)
            getSupportFragmentManager().findFragmentById(R.id.main_content);
        navController = navHostFragment.getNavController();
        navigationView = findViewById(R.id.nav_view);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        // Show and Manage the Drawer and Back Icon
        NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout);

        // Handle Navigation item clicks
        // This works with no further action on your part if the menu and destination id’s match.
        NavigationUI.setupWithNavController(navigationView, navController);

    }

    @Override
    public boolean onSupportNavigateUp() {
        // Allows NavigationUI to support proper up navigation or the drawer layout
        // drawer menu, depending on the situation.
        return NavigationUI.navigateUp(navController, drawerLayout);

    }
}

আপনি BottomNavigationView-ভিত্তিক নেভিগেশন এবং মেনু-ভিত্তিক নেভিগেশন, উভয়ের ক্ষেত্রেই একই টেকনিক ব্যবহার করতে পারবেন। আরও উদাহরণের জন্য NavigationUI-এর মাধ্যমে UI কম্পোনেন্ট আপডেট করুন দেখুন।

অ্যাক্টিভিটির গন্তব্য যোগ করুন

আপনার অ্যাপের প্রতিটি স্ক্রিন নেভিগেশন কম্পোনেন্ট ব্যবহার করার জন্য ওয়্যার-আপ করা হয়ে গেলে এবং ফ্র্যাগমেন্ট-ভিত্তিক ডেস্টিনেশনের মধ্যে ট্রানজিশন করার জন্য আপনি আর FragmentTransactions ব্যবহার না করলে, পরবর্তী ধাপ হল startActivity কল বাদ দেওয়া।

প্রথমে, আপনার অ্যাপের সেইসব জায়গা শনাক্ত করুন যেখানে দুটি আলাদা নেভিগেশন গ্রাফ আছে এবং তাদের মধ্যে ট্রানজিশন করার জন্য startActivity ব্যবহার করছেন।

এই উদাহরণে দুটি গ্রাফ (A এবং B) এবং A থেকে B-তে ট্রানজিশন করার জন্য একটি startActivity() কল রয়েছে।

Kotlin

fun navigateToProductDetails(productId: String) {
    val intent = Intent(this, ProductDetailsActivity::class.java)
    intent.putExtra(KEY_PRODUCT_ID, productId)
    startActivity(intent)
}

জাভা

private void navigateToProductDetails(String productId) {
    Intent intent = new Intent(this, ProductDetailsActivity.class);
    intent.putExtra(KEY_PRODUCT_ID, productId);
    startActivity(intent);

এরপর, এগুলিকে গ্রাফ A-তে একটি অ্যাক্টিভিটি ডেস্টিনেশন দিয়ে রিপ্লেস করুন যা গ্রাফ B-এর হোস্ট অ্যাক্টিভিটিতে নেভিগেশনকে দেখায়। গ্রাফ B-এর শুরু করার গন্তব্যে পাস করার জন্য আপনার কাছে আর্গুমেন্ট থাকলে, আপনি অ্যাক্টিভিটি গন্তব্যের সংজ্ঞায় সেগুলি নির্দিষ্ট করতে পারেন।

নিম্নলিখিত উদাহরণে, গ্রাফ A একটি অ্যাক্টিভিটি ডেস্টিনেশন নির্ধারণ করে যা অ্যাকশনের সাথে product_id আর্গুমেন্ট নেয়। গ্রাফ B-তে কোনও পরিবর্তন নেই।

গ্রাফ A এবং B-এর XML উপস্থাপনা এইরকম দেখতে হতে পারে:

<!-- Graph A -->
<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/product_list_graph"
    app:startDestination="@id/product_list">

    <fragment
        android:id="@+id/product_list"
        android:name="com.example.android.persistence.ui.ProductListFragment"
        android:label="Product List"
        tools:layout="@layout/product_list_fragment">
        <action
            android:id="@+id/navigate_to_product_detail"
            app:destination="@id/product_details_activity" />
    </fragment>

    <activity
        android:id="@+id/product_details_activity"
        android:name="com.example.android.persistence.ui.ProductDetailsActivity"
        android:label="Product Details"
        tools:layout="@layout/product_details_host">

        <argument
            android:name="product_id"
            app:argType="integer" />

    </activity>

</navigation>
<!-- Graph B -->
<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"
    app:startDestination="@id/product_details">

    <fragment
        android:id="@+id/product_details"
        android:name="com.example.android.persistence.ui.ProductDetailsFragment"
        android:label="Product Details"
        tools:layout="@layout/product_details_fragment">
        <argument
            android:name="product_id"
            app:argType="integer" />
    </fragment>

</navigation>

আপনি ফ্র্যাগমেন্ট গন্তব্যে নেভিগেট করার জন্য যে পদ্ধতি ব্যবহার করেন, সেই একই পদ্ধতি ব্যবহার করে গ্রাফ B-এর হোস্ট অ্যাক্টিভিটিতে নেভিগেট করতে পারেন:

Kotlin

fun navigateToProductDetails(productId: String) {
    val directions = ProductListDirections.navigateToProductDetail(productId)
    findNavController().navigate(directions)
}

জাভা

private void navigateToProductDetails(String productId) {
    ProductListDirections.NavigateToProductDetail directions =
            ProductListDirections.navigateToProductDetail(productId);
    Navigation.findNavController(getView()).navigate(directions);

স্টার্ট ডেস্টিনেশন ফ্র্যাগমেন্টে অ্যাক্টিভিটি ডেস্টিনেশন আর্গুমেন্ট পাস করুন

আগের উদাহরণের মতো, ডেস্টিনেশন অ্যাক্টিভিটি যদি অতিরিক্ত কিছু পায়, তাহলে আপনি এগুলি সরাসরি আর্গুমেন্ট হিসেবে স্টার্ট ডেস্টিনেশনে পাস করতে পারেন, তবে আপনাকে হোস্ট অ্যাক্টিভিটির onCreate() মেথডের মধ্যে ম্যানুয়ালি হোস্টের নেভিগেশন গ্রাফ সেট করতে হবে যাতে আপনি ইনটেন্ট এক্সট্রা ফ্র্যাগমেন্টে আর্গুমেন্ট হিসেবে পাস করতে পারেন, যেমন নিচে দেখানো হয়েছে:

Kotlin

class ProductDetailsActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.product_details_host)
        val navHostFragment = supportFragmentManager.findFragmentById(R.id.main_content) as NavHostFragment
        val navController = navHostFragment.navController
        navController
                .setGraph(R.navigation.product_detail_graph, intent.extras)
    }

}

জাভা

public class ProductDetailsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.product_details_host);
        NavHostFragment navHostFragment = (NavHostFragment)
            getSupportFragmentManager().findFragmentById(R.id.main_content);
        NavController navController = navHostFragment.getNavController();
        navController
                .setGraph(R.navigation.product_detail_graph, getIntent().getExtras());
    }

}

নিম্নলিখিত উদাহরণে দেখানো হয়েছে যে কীভাবে জেনারেট করা আর্গুমেন্ট ক্লাস ব্যবহার করে Bundle ফ্র্যাগমেন্ট আর্গুমেন্ট থেকে ডেটা বের করা যায়:

Kotlin

class ProductDetailsFragment : Fragment() {

    val args by navArgs<ProductDetailsArgs>()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val productId = args.productId
        ...
    }
    ...

জাভা

public class ProductDetailsFragment extends Fragment {

    ProductDetailsArgs args;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        args = ProductDetailsArgs.fromBundle(requireArguments());
    }

    @Override
    public void onViewCreated(@NonNull View view,
            @Nullable Bundle savedInstanceState) {
       int productId = args.getProductId();
       ...
    }
    ...

অ্যাক্টিভিটি একত্রিত করুন

একাধিক অ্যাক্টিভিটি একই লেআউট শেয়ার করলে, আপনি নেভিগেশন গ্রাফ একত্রিত করতে পারবেন, যেমন একটি সিঙ্গল ফ্র্যাগমেন্ট সহ সাধারণ FrameLayout। এইসব ক্ষেত্রে, আপনি প্রতিটি নেভিগেশন গ্রাফ থেকে সব এলিমেন্ট একত্রিত করতে পারেন এবং অ্যাক্টিভিটি ডেস্টিনেশন এলিমেন্ট আপডেট করে ফ্র্যাগমেন্ট ডেস্টিনেশন করতে পারেন।

নিচের উদাহরণে আগের বিভাগের গ্রাফ A ও B একত্রিত করা হয়েছে:

একত্রিত করার আগে:

<!-- Graph A -->
<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/product_list_graph"
    app:startDestination="@id/product_list">

    <fragment
        android:id="@+id/product_list"
        android:name="com.example.android.persistence.ui.ProductListFragment"
        android:label="Product List Fragment"
        tools:layout="@layout/product_list">
        <action
            android:id="@+id/navigate_to_product_detail"
            app:destination="@id/product_details_activity" />
    </fragment>
    <activity
        android:id="@+id/product_details_activity"
        android:name="com.example.android.persistence.ui.ProductDetailsActivity"
        android:label="Product Details Host"
        tools:layout="@layout/product_details_host">
        <argument android:name="product_id"
            app:argType="integer" />
    </activity>

</navigation>
<!-- Graph B -->
<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/product_detail_graph"
    app:startDestination="@id/product_details">

    <fragment
        android:id="@+id/product_details"
        android:name="com.example.android.persistence.ui.ProductDetailsFragment"
        android:label="Product Details"
        tools:layout="@layout/product_details">
        <argument
            android:name="product_id"
            app:argType="integer" />
    </fragment>
</navigation>

একত্রিত করার পরে:

<!-- Combined Graph A and B -->
<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/product_list_graph"
    app:startDestination="@id/product_list">

    <fragment
        android:id="@+id/product_list"
        android:name="com.example.android.persistence.ui.ProductListFragment"
        android:label="Product List Fragment"
        tools:layout="@layout/product_list">
        <action
            android:id="@+id/navigate_to_product_detail"
            app:destination="@id/product_details" />
    </fragment>

    <fragment
        android:id="@+id/product_details"
        android:name="com.example.android.persistence.ui.ProductDetailsFragment"
        android:label="Product Details"
        tools:layout="@layout/product_details">
        <argument
            android:name="product_id"
            app:argType="integer" />
    </fragment>

</navigation>

মার্জ করার সময় আপনার অ্যাকশনের নাম একই রাখলে, এই প্রসেসটি নির্বিঘ্নে করা যাবে, যার ফলে আপনার আগে থেকে থাকা কোড বেসে কোনও পরিবর্তন করতে হবে না। যেমন, navigateToProductDetail এখানে একই থাকে। একমাত্র পার্থক্য হল, এই অ্যাকশন এখন অ্যাক্টিভিটি ডেস্টিনেশনের পরিবর্তে একই NavHost-এর মধ্যে ফ্র্যাগমেন্ট ডেস্টিনেশনে নেভিগেশনকে দেখায়:

Kotlin

fun navigateToProductDetails(productId: String) {
    val directions = ProductListDirections.navigateToProductDetail(productId)
    findNavController().navigate(directions)
}

জাভা

private void navigateToProductDetails(String productId) {
    ProductListDirections.NavigateToProductDetail directions =
            ProductListDirections.navigateToProductDetail(productId);
    Navigation.findNavController(getView()).navigate(directions);

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

নেভিগেশন সম্পর্কিত আরও তথ্যের জন্য, নিম্নলিখিত বিষয়গুলি দেখুন: