অবৈধ অরগমেন্ট এক্সেপশন: নেভিগেশন গন্তব্য এক্সএক্সএক্সএক্স এই নেভকন্ট্রোলারের কাছে অজানা


138

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

java.lang.IllegalArgumentException: navigation destination XXX
is unknown to this NavController

এই নির্দিষ্টটি বাদে অন্য প্রতিটি নেভিগেশন সূক্ষ্মভাবে কাজ করে।

এর findNavController()অ্যাক্সেস পেতে আমি ফ্র্যাগমেন্টের ফাংশন ব্যবহার করি NavController

যে কোন ধরণের সাহায্য গ্রহন করা হবে.


আরও ভাল বোঝার জন্য দয়া করে কিছু কোড সরবরাহ করুন।
অ্যালেক্স

12
এই অত্যন্ত আমার ঘটছে।
ইউরি পেরেজ বেল্ট্রি

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

উত্তর:


75

আমার ক্ষেত্রে, ব্যবহারকারী খুব দ্রুত দু'বার একই ভিউতে ক্লিক করলে, এই ক্রাশটি ঘটবে। তাই একাধিক তাত্পর্য ক্লিকগুলি রোধ করতে আপনার কিছু প্রকারের যুক্তি প্রয়োগ করা দরকার ... যা খুব বিরক্তিকর, তবে এটি প্রয়োজনীয় বলে মনে হয়।

আপনি এটি প্রতিরোধ করার জন্য এখানে আরও পড়তে পারেন: অ্যান্ড্রয়েড প্রতিরোধকারী একটি বোতামে ডাবল ক্লিক করুন

3/19/2019 সম্পাদনা করুন : আরও কিছুটা স্পষ্ট করার জন্য, এই ক্রাশটি কেবল "খুব একই সময়ে দু'বার খুব দ্রুত একই ভিউতে ক্লিক করে" কেবলমাত্র পুনরুত্পাদনযোগ্য নয়। বিকল্পভাবে, আপনি কেবল দুটি আঙ্গুল ব্যবহার করতে পারেন এবং একই সাথে দুটি (বা আরও) ভিউ ক্লিক করতে পারেন, যেখানে প্রতিটি দৃশ্যের নিজস্ব ন্যাভিগেশন থাকে যা তারা সম্পাদন করবে। আপনার আইটেমগুলির একটি তালিকা থাকলে এটি করা বিশেষত সহজ। একাধিক ক্লিক প্রতিরোধের উপরের তথ্যটি এই কেসটিকে পরিচালনা করবে।

4/16/2020 সম্পাদনা করুন : আপনি যদি উপরের স্ট্যাক ওভারফ্লো পোস্টটি পড়ে খুব খারাপভাবে আগ্রহী না হন তবে আমি আমার নিজের (কোটলিন) সমাধানটি দীর্ঘকাল ধরে ব্যবহার করছি including

OnSingleClickListener.kt

class OnSingleClickListener : View.OnClickListener {

    private val onClickListener: View.OnClickListener

    constructor(listener: View.OnClickListener) {
        onClickListener = listener
    }

    constructor(listener: (View) -> Unit) {
        onClickListener = View.OnClickListener { listener.invoke(it) }
    }

    override fun onClick(v: View) {
        val currentTimeMillis = System.currentTimeMillis()

        if (currentTimeMillis >= previousClickTimeMillis + DELAY_MILLIS) {
            previousClickTimeMillis = currentTimeMillis
            onClickListener.onClick(v)
        }
    }

    companion object {
        // Tweak this value as you see fit. In my personal testing this
        // seems to be good, but you may want to try on some different
        // devices and make sure you can't produce any crashes.
        private const val DELAY_MILLIS = 200L

        private var previousClickTimeMillis = 0L
    }

}

ViewExt.kt

fun View.setOnSingleClickListener(l: View.OnClickListener) {
    setOnClickListener(OnSingleClickListener(l))
}

fun View.setOnSingleClickListener(l: (View) -> Unit) {
    setOnClickListener(OnSingleClickListener(l))
}

HomeFragment.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    settingsButton.setOnSingleClickListener {
        // navigation call here
    }
}

23
একই সাথে 2 টি আঙুল ব্যবহার এবং 2 টি দর্শন ক্লিক করার বিষয়ে সম্পাদনা! এটাই আমার পক্ষে মূল বিষয় এবং সহজেই এই সমস্যাটির অনুলিপি করতে আমাকে সহায়তা করেছিল। সেই তথ্য দিয়ে দুর্দান্ত আপডেটিং।
রিচার্ড লে ম্যাসুরিয়ার

ডিবাগ পর্বের সময় আমি ক্লিক করতে গিয়েছিলাম যখন অ্যাপ্লিকেশনটি কার্যকর হওয়া চালিয়ে যাওয়ার অপেক্ষায় আটকে ছিল। আইডিই
মার্কোতে

1
এর জন্য ধন্যবাদ. আমাকে কয়েকটি ক্র্যাশ এবং কিছু মাথা স্ক্র্যাচ করে
বাঁচিয়েছে

58

currentDestinationনেভিগেট কল করার আগে চেক করুন সহায়ক হতে পারে।

উদাহরণস্বরূপ, যদি আপনার নেভিগেশন গ্রাফে দুটি খণ্ড গন্তব্য থাকে fragmentAএবং fragmentBএবং কেবলমাত্র একটি থেকে ক্রিয়া fragmentAথাকে fragmentB। কলিং navigate(R.id.action_fragmentA_to_fragmentB)পরিণাম ডেকে আনবে IllegalArgumentExceptionযখন আপনি ইতিমধ্যে ছিল fragmentB। এর জন্য আপনাকে সর্বদা currentDestinationনেভিগেট করার আগে পরীক্ষা করা উচিত ।

if (navController.currentDestination?.id == R.id.fragmentA) {
    navController.navigate(R.id.action_fragmentA_to_fragmentB)
}

3
আমার কাছে একটি অনুসন্ধান অ্যাপ্লিকেশন রয়েছে যা যুক্তিযুক্ত ক্রিয়া সহ নেভিগেট করে। সুতরাং এটি বর্তমানের অবস্থান থেকে নিজেই নেভিগেট করতে পারে। আমি নাভোকন্ট্রোলার.কোর্নডেস্টেশন == নাভোকন্ট্রোলার.গ্রাফিক.নোড ব্যতীত একই কাজটি শেষ করেছি। যদিও এটিকে কিছুটা নোংরা অনুভূত হয়েছিল এবং আমার মনে হয় আমার এটি করা উচিত নয়।
শান মায়বুশ

84
গ্রন্থাগার আমাদের এই চেক করতে বাধ্য করা উচিত নয়, এটি সত্যই হাস্যকর ulous
ড্যানিলোডিকিউইরোজ

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

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

1
এমনকি আইওএস-এ যদিও কখনও কখনও আপনি একাধিক বার বোতাম টিপলে একাধিক ভিউকন্ট্রোলার চাপ দেয়। অনুমান করুন অ্যান্ড্রয়েড এবং আইওএস উভয়েরই এই সমস্যা রয়েছে।
coolcool1994

47

আপনি ন্যাভিগেশন নিয়ামকের বর্তমান গন্তব্যে অনুরোধিত ক্রিয়াটি চেক করতে পারেন।

আপডেট আপডেট নিরাপদ নেভিগেশনের জন্য বিশ্ব পদক্ষেপের ব্যবহার যুক্ত করেছে।

fun NavController.navigateSafe(
        @IdRes resId: Int,
        args: Bundle? = null,
        navOptions: NavOptions? = null,
        navExtras: Navigator.Extras? = null
) {
    val action = currentDestination?.getAction(resId) ?: graph.getAction(resId)
    if (action != null && currentDestination?.id != action.destinationId) {
        navigate(resId, args, navOptions, navExtras)
    }
}

1
এই সমাধানটি'র currentDestinationকর্ম তালিকার বাইরে নির্ধারিত কোনও ক্রয়ের জন্য কাজ করবে না । বলুন আপনার কাছে একটি গ্লোবাল ক্রিয়া সংজ্ঞায়িত হয়েছে এবং নেভিগেট করতে সেই ক্রিয়াটি ব্যবহার করুন। এটি ব্যর্থ হবে কারণ ক্রিয়াটি বর্তমানের অবস্থান <<> তালিকায় সংজ্ঞায়িত হয়নি। চেক যুক্ত করার মতো currentDestination?.getAction(resId) != null || currentDestination?.id != resIdএটি সমাধান করা উচিত তবে প্রতিটি ক্ষেত্রে এটি কভার নাও হতে পারে।
wchristiansen

@ ওয়ারিশিয়ানসেন, নোটের জন্য আপনাকে ধন্যবাদ আমি বিশ্বব্যাপী ক্রিয়াকলাপগুলির সাথে কোড আপডেট করেছি
অ্যালেক্স নটস

@ অ্যালেক্সনাটস দুর্দান্ত উত্তর। আমি মনে করি আপনি মুছে ফেলতে পারবেন ?: graph.getAction(resId)-> currentDestination?.getAction(resId)বৈশ্বিক বা অ-গ্লোবাল উভয় ক্রিয়াকলাপের জন্য একটি ক্রিয়া ফিরিয়ে দেবেন (আমি এটি পরীক্ষা করেছি)। এছাড়াও, ভালো হতে যদি আপনি নিরাপদ args ব্যবহার করা হবে -> বরং মধ্যে পাস navDirections: NavDirectionsচেয়ে resIdএবং argsআলাদাভাবে।
Wess

@ অ্যালেক্সনটস নোট করুন এই সমাধানটি বর্তমান গন্তব্য হিসাবে একই গন্তব্যটিতে নেভিগেট করা সমর্থন করে না। বান্ডিল ওয়াইয়ের সাথে এক্স গন্তব্য এক্স থেকে বান্ডিল জেডের সাথে গন্তব্য এক্সে নেভিগেট করা সম্ভব নয়।
Wess

18

আপনার যদি খণ্ড খ এর ভিউপ্যাজারের সাথে একটি খণ্ড A থাকে এবং আপনি বি থেকে সিতে নেভিগেট করার চেষ্টা করেন তবে এটিও ঘটতে পারে

যেহেতু ভিউপিজারে খণ্ডগুলি A এর গন্তব্য নয়, আপনার গ্রাফটি জানতে পারবে না আপনি বি তে আছেন you

সি তে নেভিগেট করার জন্য বি এডিরিকেশনগুলি ব্যবহার করার একটি সমাধান হতে পারে


এই ক্ষেত্রে, ক্র্যাশ প্রতিবার ঘটে না তবে কেবল বিরল ঘটে। কীভাবে সমাধান করবেন?
শ্রীকর রেড্ডি

আপনি নাগ্রাফের ভিতরে একটি গ্লোবাল অ্যাকশন যুক্ত করতে পারেন এবং এটিকে নেভিগেট করতে ব্যবহার করতে পারেন
আব্রাহাম ম্যাথিউ

1
যেহেতু বি এর সঠিক পিতা-মাতার সম্পর্কে সচেতন হওয়ার দরকার নেই, তাই ইন্টারফেসের মাধ্যমে অ্যাডেরিকেশনগুলি ব্যবহার করা ভাল (parentFragment as? XActionListener)?.Xaction()এবং নোট করুন যদি আপনি কার্যকর হন তবে এই ফাংশনটিকে স্থানীয় পরিবর্তনশীল হিসাবে ধরে রাখতে পারেন
hmac

আমার একই সমস্যা রয়েছে বলে আপনি কি দয়া করে একটি নমুনা কোড ভাগ করে নিতে পারেন
ইখিলোয়া ইমোখাই

যে কোনও একটি নমুনা কোড প্লিজ করতে পারে, আমি একই সমস্যাটিতে আটকে আছি। একটি খণ্ড এবং তারপরে একটি ট্যাবফ্র্যাগমেন্ট রয়েছে
উসমান জাফর

13

ক্র্যাশ প্রতিরোধে আমি যা করেছি তা হ'ল:

আমি একটি BaseFragment আছে, সেখানে আমি এই জুড়েছেন funতা নিশ্চিত করার জন্য destinationদ্বারা পরিচিত হয় currentDestination:

fun navigate(destination: NavDirections) = with(findNavController()) {
    currentDestination?.getAction(destination.actionId)
        ?.let { navigate(destination) }
}

আমি SafeArgs প্লাগইন ব্যবহার করছি তা লক্ষণীয়


12

আমার ক্ষেত্রে আমি নেভিগেট করার জন্য কাস্টম ব্যাক বোতামটি ব্যবহার করছিলাম। আমি onBackPressed()নিম্নলিখিত কোড স্থির মধ্যে কল

findNavController(R.id.navigation_host_fragment).navigateUp()

এর ফলে IllegalArgumentExceptionঘটেছিল। navigateUp()স্থিতিশীলভাবে পদ্ধতিটি ব্যবহার করার জন্য আমি এটি পরিবর্তন করার পরে , আমার আর ক্র্যাশ হয়নি।


অনব্যাকপ্রেসড এবং এটির মধ্যে পার্থক্য কী তা আমি পাই না, তবুও সিস্টেমের পিছনের বোতামটি আটকে এবং এটি ওভাররাইড করে এবং এর পরিবর্তে পাগল বলে মনে হয়
ড্যানিয়েল উইলসন

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

আমার জন্য কাজ করে না ... তবুও একই ত্রুটি হচ্ছে।
ওটিজিই

5

টিএল; ডিআর আপনার navigateকলগুলি try-catch(সরল উপায়ে) দিয়ে মুড়িয়ে রাখুন , বা নিশ্চিত করুন যে কেবলমাত্র একটি কল আসবেnavigate স্বল্প সময়ের মধ্যে । এই সমস্যা সম্ভবত দূরে যাবে না। আপনার অ্যাপে আরও বড় কোড স্নিপেট অনুলিপি করুন এবং চেষ্টা করুন।

হ্যালো. উপরের কয়েকটি দরকারী প্রতিক্রিয়ার ভিত্তিতে, আমি আমার সমাধানটি ভাগ করতে চাই যা বাড়ানো যেতে পারে।

আমার অ্যাপ্লিকেশনটিতে এই ক্র্যাশটির কারণ কোডটি এখানে রয়েছে:

@Override
public void onListItemClicked(ListItem item) {
    Bundle bundle = new Bundle();
    bundle.putParcelable(SomeFragment.LIST_KEY, item);
    Navigation.findNavController(recyclerView).navigate(R.id.action_listFragment_to_listItemInfoFragment, bundle);
}

বাগটি সহজেই উপস্থাপনের একটি উপায় হ'ল আইটেমের তালিকায় একাধিক আঙুল দিয়ে ট্যাপ করা যেখানে প্রতিটি আইটেম ক্লিক করে নতুন স্ক্রিনে নেভিগেশনে সমাধান হয় (মূলত লোকেরা উল্লিখিত একই - খুব অল্প সময়ের মধ্যে দু'একটি ক্লিক ক্লিক করে) )। আমি লক্ষ্য করেছি যে:

  1. প্রথম অনুরোধ navigateসর্বদা সূক্ষ্ম কাজ করে;
  2. navigateপদ্ধতির দ্বিতীয় এবং সমস্ত অনুরোধগুলি সমাধান করে IllegalArgumentException

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

public class NavigationHandler {

public static void navigate(View view, @IdRes int destination) {
    navigate(view, destination, /* args */null);
}

/**
 * Performs a navigation to given destination using {@link androidx.navigation.NavController}
 * found via {@param view}. Catches {@link IllegalArgumentException} that may occur due to
 * multiple invocations of {@link androidx.navigation.NavController#navigate} in short period of time.
 * The navigation must work as intended.
 *
 * @param view        the view to search from
 * @param destination destination id
 * @param args        arguments to pass to the destination
 */
public static void navigate(View view, @IdRes int destination, @Nullable Bundle args) {
    try {
        Navigation.findNavController(view).navigate(destination, args);
    } catch (IllegalArgumentException e) {
        Log.e(NavigationHandler.class.getSimpleName(), "Multiple navigation attempts handled.");
    }
}

}

এবং এইভাবে উপরের কোডটি কেবল একটি লাইনে পরিবর্তিত হয়:

Navigation.findNavController(recyclerView).navigate(R.id.action_listFragment_to_listItemInfoFragment, bundle);

এটি:

NavigationHandler.navigate(recyclerView, R.id.action_listFragment_to_listItemInfoFragment, bundle);

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

কোন চিন্তা স্বাগত!

ঠিক কী কারণে দুর্ঘটনা ঘটে

মনে রাখবেন যে আমরা যখন পদ্ধতি ব্যবহার করি তখন আমরা একই ন্যাভিগেশন গ্রাফ, নেভিগেশন কন্ট্রোলার এবং ব্যাক-স্ট্যাকের সাথে কাজ করি Navigation.findNavController

আমরা এখানে সর্বদা একই নিয়ামক এবং গ্রাফ পাই। যখন navigate(R.id.my_next_destination)গ্রাফ বলা হয় এবং ব্যাক-স্ট্যাক প্রায় তত্ক্ষণাত্ পরিবর্তন হয় যখন ইউআই এখনও আপডেট হয় না। শুধু পর্যাপ্ত দ্রুত নয়, তবে এটি ঠিক আছে। ব্যাক-স্ট্যাক পরিবর্তনের পরে নেভিগেশন সিস্টেমটি দ্বিতীয় navigate(R.id.my_next_destination)কলটি গ্রহণ করে । যেহেতু ব্যাক-স্ট্যাক পরিবর্তিত হয়েছে আমরা এখন স্ট্যাকের শীর্ষ খণ্ডের তুলনায় অপারেটিং করি। শীর্ষ খণ্ডটি হ'ল খণ্ডটি যা আপনি ব্যবহার করে নেভিগেট R.id.my_next_destinationকরেন তবে এটিতে আইডি সহ পরবর্তী কোনও গন্তব্য থাকে না R.id.my_next_destination। সুতরাং আপনি আইডিটির IllegalArgumentExceptionকারণে পান যে খণ্ডটি সম্পর্কে কিছুই জানে না।

এই সঠিক ত্রুটি NavController.javaপদ্ধতিতে পাওয়া যাবে findDestination


4

আমার ক্ষেত্রে, সমস্যাটি তখনই ঘটেছিল যখন আমি আমার viewpagerসন্তানের একটি শিশু হিসাবে কোনও খণ্ডের ভিতরে পুনরায় ব্যবহার করেছি viewpagerviewpagerনেভিগেশন এক্সএমএল- তে ফ্রেগমেন্ট (যা প্যারেন্ট টুকরা ছিল) যোগ করা হয়েছিল, তবে viewpagerঅভিভাবক খণ্ডটিতে ক্রিয়াটি যুক্ত করা হয়নি ।

nav.xml
//reused fragment
<fragment
    android:id="@+id/navigation_to"
    android:name="com.package.to_Fragment"
    android:label="To Frag"
    tools:layout="@layout/fragment_to" >
    //issue got fixed when i added this action to the viewpager parent also
    <action android:id="@+id/action_to_to_viewall"
        app:destination="@+id/toViewAll"/>
</fragment>
....
// viewpager parent fragment
<fragment
    android:id="@+id/toViewAll"
    android:name="com.package.ViewAllFragment"
    android:label="to_viewall_fragment"
    tools:layout="@layout/fragment_view_all">

নীচের মতামত হিসাবে পিতামাতার ভিউপেজ খণ্ডে ক্রিয়া যুক্ত করে সমস্যাটি স্থির করে:

nav.xml
//reused fragment
<fragment
    android:id="@+id/navigation_to"
    android:name="com.package.to_Fragment"
    android:label="To Frag"
    tools:layout="@layout/fragment_to" >
    //issue got fixed when i added this action to the viewpager parent also
    <action android:id="@+id/action_to_to_viewall"
        app:destination="@+id/toViewAll"/>
</fragment>
....
// viewpager parent fragment
<fragment
    android:id="@+id/toViewAll"
    android:name="com.package.ViewAllFragment"
    android:label="to_viewall_fragment"
    tools:layout="@layout/fragment_view_all"/>
    <action android:id="@+id/action_to_to_viewall"
        app:destination="@+id/toViewAll"/>
</fragment>

4

আজ

Def নেভিগেশন সংস্করণ = "২.২.১"

বিষয়টি এখনও বিদ্যমান। কোটলিন সম্পর্কে আমার পদ্ধতিটি হ'ল:

// To avoid "java.lang.IllegalArgumentException: navigation destination is unknown to this NavController", se more https://stackoverflow.com/q/51060762/6352712
fun NavController.navigateSafe(
    @IdRes destinationId: Int,
    navDirection: NavDirections,
    callBeforeNavigate: () -> Unit
) {
    if (currentDestination?.id == destinationId) {
        callBeforeNavigate()
        navigate(navDirection)
    }
}

fun NavController.navigateSafe(@IdRes destinationId: Int, navDirection: NavDirections) {
    if (currentDestination?.id == destinationId) {
        navigate(navDirection)
    }
}

4

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

এটি পরে দেখার জন্য খণ্ডে একটি ট্যাগ সেট করে।

/**
 * Returns true if the navigation controller is still pointing at 'this' fragment, or false if it already navigated away.
 */
fun Fragment.mayNavigate(): Boolean {

    val navController = findNavController()
    val destinationIdInNavController = navController.currentDestination?.id
    val destinationIdOfThisFragment = view?.getTag(R.id.tag_navigation_destination_id) ?: destinationIdInNavController

    // check that the navigation graph is still in 'this' fragment, if not then the app already navigated:
    if (destinationIdInNavController == destinationIdOfThisFragment) {
        view?.setTag(R.id.tag_navigation_destination_id, destinationIdOfThisFragment)
        return true
    } else {
        Log.d("FragmentExtensions", "May not navigate: current destination is not the current fragment.")
        return false
    }
}

R.id.tag_navigation_destination_id এটি কেবলমাত্র একটি আইডি যা আপনার আইডিএসএক্সএমএল যুক্ত করতে হবে এটি নিশ্চিত করার জন্য এটি অনন্য। <item name="tag_navigation_destination_id" type="id" />

বাগ এবং সমাধান সম্পর্কিত আরও তথ্য navigateSafe(...)এবং "ভয়ঙ্কর" ঠিক করা "... এ নাভাকন্ট্রোলারের সাথে অজানা"


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


হ্যাঁ, আমি উত্তরটি আপডেট করেছি
ফ্রাঙ্ক

ট্যাগটি কোথা থেকে আসছে এবং কেন এটি দরকার? আমার এমন সমস্যা হয়েছে যেখানে নেভিগেশন উপাদানটিতে প্রকৃত আইডি এর সাথে মেলে না R.id
রিজেবোশ 13

R.id.tag_navigation_destination_idএটি কেবলমাত্র একটি আইডি যা আপনার আইডিএসএক্সএমএল যুক্ত করতে হবে এটি নিশ্চিত করার জন্য এটি অনন্য। <item name="tag_navigation_destination_id" type="id" />
ফ্র্যাঙ্ক

3

আমার ক্ষেত্রে, আমার কাছে একাধিক ন্যাভ গ্রাফ ফাইল ছিল এবং আমি 1 এনএভি গ্রাফের অবস্থান থেকে অন্য এনএল গ্রাফের কোনও গন্তব্যে যাওয়ার চেষ্টা করছিলাম।

এটির জন্য আমাদের ২ য় নেভ গ্রাফটি এই জাতীয় 1 টিতে অন্তর্ভুক্ত করতে হবে

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

এবং এটি আপনার ক্রিয়ায় যুক্ত করুন:

<action
        android:id="@+id/action_fragment_to_second_graph"
        app:destination="@id/second_graph" />

কোথায় second_graph:

<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">

দ্বিতীয় গ্রাফে

আরও তথ্য এখানে


2

আমার ক্ষেত্রে বাগটি কার্যকর হয়েছিল কারণ আমার একটি স্প্ল্যাশ স্ক্রিনের পরে Single Topএবং Clear Taskবিকল্পগুলি সক্ষম করার সাথে নেভিগেশন অ্যাকশন ছিল ।


1
তবে ক্লিয়ারটাস্ক অবমূল্যায়ন করা হয়েছে, পরিবর্তে আপনার পপআপ () ব্যবহার করা উচিত।
জেরি ওকাফোর

@ Po10cio এই পতাকাগুলির কোনওটিরই দরকার নেই, আমি এটি সরিয়েছি এবং এটি স্থির হয়ে গেছে।
ইউরি পেরেজ বেল্ট্রি

2

আমি একই ত্রুটি পেয়েছি কারণ আমি একটি নেভিগেশন ড্রয়ার এবং getSupportFragmentManager().beginTransaction().replace( )একই সাথে আমার কোডের কোথাও ব্যবহার করেছি।

আমি এই শর্তটি ব্যবহার করে ত্রুটি থেকে মুক্তি পেয়েছি (গন্তব্য কিনা তা পরীক্ষা করে):

if (Navigation.findNavController(v).getCurrentDestination().getId() == R.id.your_destination_fragment_id)
Navigation.findNavController(v).navigate(R.id.your_action);

আমার ক্ষেত্রে আগের ত্রুটিটি ট্রিগার হয়েছিল যখন আমি নেভিগেশন ড্রয়ারের বিকল্পগুলিতে ক্লিক করছি। মূলত উপরের কোডটি ত্রুটিটি আড়াল করেছিল, কারণ আমার কোডে কোথাও আমি getSupportFragmentManager().beginTransaction().replace( )শর্তটি ব্যবহার করে নেভিগেশন ব্যবহার করেছি -

 if (Navigation.findNavController(v).getCurrentDestination().getId() ==
  R.id.your_destination_fragment_id) 

কখনও পৌঁছে যায়নি কারণ (Navigation.findNavController(v).getCurrentDestination().getId()সর্বদা বাড়ির খণ্ডগুলিতে পোজ দিচ্ছিল। Navigation.findNavController(v).navigate(R.id.your_action)আপনার সমস্ত নেভিগেশন ক্রিয়াকলাপের জন্য আপনাকে অবশ্যই গ্রাফ নিয়ামক ফাংশনটি ব্যবহার করতে পারেন বা নাভ করতে হবে।


1

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

https://developer.android.com/topic/libraries/architecture/navigation/navigation-conditional


1

ক্লাসের কিছু নাম পরিবর্তনের পরে আমি এই ব্যতিক্রমটি ধরলাম। উদাহরণস্বরূপ: আমি নামক ক্লাস ছিল FragmentAসঙ্গে @+is/fragment_aগৌণ গ্রাফ এবং FragmentBসঙ্গে @+id/fragment_b। তারপর আমি মোছা FragmentAএবং নতুন নামকরণ FragmentBকরা FragmentA। সুতরাং যে নোড পর FragmentAএখনও গৌণ গ্রাফে থাকলেন, android:nameএর FragmentBএর নোড নাম দেওয়া হয় path.to.FragmentA। আমার একই android:nameএবং পৃথক দুটি নোড ছিল এবং android:idআমার যে ক্রিয়াটি প্রয়োজন তা মুছে ফেলা শ্রেণীর নোডে সংজ্ঞায়িত করা হয়েছিল।


1

আমি যখন দুবার পিছনের বোতাম টিপতাম তখন তা আমার কাছে ঘটে। প্রথমে, আমি বিরত KeyListenerএবং ওভাররাইড করি KeyEvent.KEYCODE_BACK। আমি OnResumeফ্রেগমেন্টের জন্য নামকরণ করা ফাংশনটিতে নীচের কোডটি যুক্ত করেছি এবং তারপরে এই প্রশ্ন / সমস্যাটি সমাধান করা হবে।

  override fun onResume() {
        super.onResume()
        view?.isFocusableInTouchMode = true
        view?.requestFocus()
        view?.setOnKeyListener { v, keyCode, event ->
            if (event.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BACK) {
                activity!!.finish()
                true
            }
            false
        }
    }

যখন এটি আমার সাথে দ্বিতীয়বার হয়, এবং এর স্থিতিটি প্রথমটির মতো হয়, আমি দেখতে পেলাম যে আমি সম্ভবত adsurdফাংশনটি ব্যবহার করব । আসুন এই পরিস্থিতি বিশ্লেষণ করা যাক।

  1. প্রথমত, ফ্রেগমেন্টএ ফ্রেগমেন্টবিতে নেভিগেট করে, ফ্রেগমেন্টবি ফ্রেগমেন্টএতে নেভিগেট করে, তারপরে ব্যাক বোতাম টিপুন ... ক্রাশটি উপস্থিত হয়।

  2. দ্বিতীয়ত, ফ্রেগমেন্টএ ফ্রেগমেন্টবিতে নেভিগেট করে, তারপরে ফ্রেগমেন্টবি ফ্রেগমেন্টসিতে নেভিগেট করে, ফ্রেগমেন্টসি ফ্রেগমেন্টএতে নেভিগেট করে, তারপরে পিছনে বোতাম টিপুন ... ক্র্যাশটি উপস্থিত হয়।

সুতরাং আমি মনে করি পিছনের বোতামটি টিপানোর সময়, ফ্র্যাগমেন্টএ ফ্র্যাগমেন্টবি বা ফ্রেগমেন্টসিতে ফিরে আসবে, তারপরে এটি লগইন ঝামেলা সৃষ্টি করে। পরিশেষে আমি দেখতে পেয়েছি যে নামের ফাংশনটি popBackStackনেভিগেট না করে পিছনে ব্যবহার করা যেতে পারে।

  NavHostFragment.findNavController(this@TeacherCloudResourcesFragment).
                        .popBackStack(
                            R.id.teacher_prepare_lesson_main_fragment,false
                        )

এখনও অবধি সমস্যাটি সত্যিই সমাধান হয়েছে।


1

দেখে মনে হচ্ছে ব্যাকস্ট্যাকের ফ্রেমমেন্ট ম্যানেজারের নিয়ন্ত্রণ এবং নেভিগেশন আর্কিটেকচার নিয়ন্ত্রণ ব্যাকস্ট্যাকের কারণেও এই সমস্যা দেখা দিতে পারে।

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

// Handle back button press
        view.findViewById<ImageButton>(R.id.back_button).setOnClickListener {
            fragmentManager?.popBackStack()
        }

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

পূর্বে : ডি / ক্যামেরাএক্স বেসিক: কারেন্টডেস্ট ?: androidx.navication.fraament.FraamentNavigator$Destination@b713195

এর পরে : ডি / ক্যামেরাএক্স বেসিক: কারেন্টডেস্ট ?: androidx.navication.fraament.FraamentNavigator$Destination@9807d8f

ক্যামেরাএক্সের বেসিক নমুনার আপডেট হওয়া সংস্করণটি এ জাতীয় ফেরত নেভিগেশন ব্যবহার করে:

 // Handle back button press
        view.findViewById<ImageButton>(R.id.back_button).setOnClickListener {
            Navigation.findNavController(requireActivity(), R.id.fragment_container).navigateUp()
        }

এটি সঠিকভাবে কাজ করে এবং লগগুলি একই আইডিটি দেখায় যখন মূল খণ্ডে ফিরে আসে।

পূর্বে : ডি / ক্যামেরাএক্স বেসিক: কারেন্টডেস্ট ?: androidx.navication.fraament.FraamentNavigator$Destination@b713195

এর পরে : ডি / ক্যামেরাএক্স বেসিক: কারেন্টডেস্ট ?: androidx.navication.fraament.FraamentNavigator$Destination@b713195

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


এটি প্রশংসনীয় মনে হচ্ছে, আমি আরও তদন্ত করব। কেউ কি এই দাবি যাচাই বা প্রমাণ করতে সক্ষম হয়েছে?
জেরি ওকাফোর

@ জেরিওকাফর - আমি এমন একটি অ্যাপে এটি পরীক্ষা করেছি যে আমি ক্যামেরাএক্স নমুনার উপর ভিত্তি করে কাজ করছি এবং এটি যাচাই করেছি তবে অন্য কেউ এটিও দেখেছেন কিনা ভাল লাগবে। আমি একই অ্যাপ্লিকেশনটিতে এক জায়গায় 'ব্যাক নেভিগেশন' মিস করেছি তাই সম্প্রতি এটি আবার ঠিক করে ফেলেছে।
মিক

1

একটি হাস্যকর উপায় কিন্তু খুব শক্তিশালী: কেবল এটিকে কল করুন:

view?.findNavController()?.navigateSafe(action)

কেবল এই এক্সটেনশনটি তৈরি করুন:

fun NavController.navigateSafe(
    navDirections: NavDirections? = null
) {
    try {
        navDirections?.let {
            this.navigate(navDirections)
        }
    }
    catch (e:Exception)
    {
        e.printStackTrace()
    }
}

1

এই সমস্যার অনেক কারণ থাকতে পারে। আমার ক্ষেত্রে আমি এমভিভিএম মডেলটি ব্যবহার করছিলাম এবং আমি যখন বুলিয়ান সত্য তখন নেভিগেশনের জন্য একটি বুলিয়ান পর্যবেক্ষণ করছিলাম -> নেভিগেট অন্য কিছু করবেন না এবং এটি ভাল কাজ করছিল তবে এখানে একটি ভুল ছিল was

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


1

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

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

GitHub

বিষয়টির বিবরণ নিবন্ধ


1

আপনি যদি খুব দ্রুত ক্লিক করেন তবে এটি নাল এবং ক্রাশের কারণ হবে।

আমরা এটিতে সহায়তা করতে আরএক্সবাইন্ডিং লিব ব্যবহার করতে পারি। এটি হওয়ার আগে আপনি ক্লিকের উপর থ্রোটল এবং সময়কাল যুক্ত করতে পারেন।

 RxView.clicks(view).throttleFirst(duration, TimeUnit.MILLISECONDS)
            .subscribe(__ -> {
            });

অ্যান্ড্রয়েডে থ্রোটলিং সম্পর্কিত এই নিবন্ধগুলি সাহায্য করতে পারে। চিয়ার্স!


1

আপনি যদি একটি পুনর্ব্যবহারযোগ্য পর্যালোচনা ব্যবহার করছেন তবে কেবল আপনার ক্লিকের উপর একটি ক্লিক শ্রোতা কুলডাউন যুক্ত করুন এবং আপনার পুনর্ব্যবহারযোগ্য এক্সএমএল ফাইল ব্যবহারের ক্ষেত্রেও android:splitMotionEvents="false"


1
আমার নীচের উত্তরগুলি দেখুন
ক্রেজি

1

এই টুইটার থ্রেডে ইয়ান লেকের পরামর্শ নিয়ে চিন্তা করার পরে আমি নিম্নলিখিত পদ্ধতির সাথে হাজির হয়েছি। রয়ে NavControllerWrapperযেমন সংজ্ঞা দিয়েছে:

class NavControllerWrapper constructor(
  private val navController: NavController
) {

  fun navigate(
    @IdRes from: Int,
    @IdRes to: Int
  ) = navigate(
    from = from,
    to = to,
    bundle = null
  )

  fun navigate(
    @IdRes from: Int,
    @IdRes to: Int,
    bundle: Bundle?
  ) = navigate(
    from = from,
    to = to,
    bundle = bundle,
    navOptions = null,
    navigatorExtras = null
  )

  fun navigate(
    @IdRes from: Int,
    @IdRes to: Int,
    bundle: Bundle?,
    navOptions: NavOptions?,
    navigatorExtras: Navigator.Extras?
  ) {
    if (navController.currentDestination?.id == from) {
      navController.navigate(
        to,
        bundle,
        navOptions,
        navigatorExtras
      )
    }
  }

  fun navigate(
    @IdRes from: Int,
    directions: NavDirections
  ) {
    if (navController.currentDestination?.id == from) {
      navController.navigate(directions)
    }
  }

  fun navigateUp() = navController.navigateUp()

  fun popBackStack() = navController.popBackStack()
}

তারপরে নেভিগেশন কোডে:

val navController = navControllerProvider.getNavController()
navController.navigate(from = R.id.main, to = R.id.action_to_detail)

1

তাত্ক্ষণিকভাবে নিয়ন্ত্রণে ক্লিক করার জন্য বয়লারপ্লেট কোডের পরিবর্তে নেভিগেটের আগে চেক রেখে আমি একই সমস্যার সমাধান করেছি

 if (findNavController().currentDestination?.id == R.id.currentFragment) {
        findNavController().navigate(R.id.action_current_next)}
/* Here R.id.currentFragment is the id of current fragment in navigation graph */

এই উত্তর অনুযায়ী

https://stackoverflow.com/a/56168225/7055259


0

আমার সাথে এটি ঘটেছিল, আমার সমস্যাটি ছিল আমি কোনও এফএবি ক্লিক করছি tab item fragment। আমি ট্যাব আইটেম খণ্ডের একটি থেকে নেভিগেট করার চেষ্টা করছিলাম another fragment

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

উদা:

containing fragment -> tab layout fragment -> tab item fragment -> another fragment

সমাধানটি হ'ল ট্যাব বিন্যাস থেকে টুকরো টুকরো টুকরো টুকরো সহ প্রস্থান: পথ: container fragment -> another fragment

অসুবিধা:

  • নাভ গ্রাফ আর ব্যবহারকারীর প্রবাহকে নির্ভুলভাবে উপস্থাপন করে না।

0

আমার ক্ষেত্রে আমি 50% ক্ষেত্রে অন্য থ্রেড থেকে নেভিগেট করার চেষ্টা করার সময় সেই ত্রুটিটি পেয়েছি। মূল থ্রেডে কোড চালান সহায়তা করে

requireActivity().runOnUiThread {
    findNavController().navigate(...)
}

আমি এটিতে আরও ভোট দেখতে চাই, প্রশংসনীয় মনে হলেও আমি এটি যাচাই করতে পারি না।
জেরি ওকাফোর

0

আমার ক্ষেত্রে এটি ঘটেছিল যখন আমি ঘটনাক্রমে +ক্রিয়াকলাপের জন্য একটি অ্যাকশন গন্তব্য যুক্ত করেছি এবং ক্রাশটি তখনই ঘটেছিল যখন আমি একই খণ্ডে একাধিকবার গিয়েছিলাম।

 <action
        android:id="@+id/action_to_profileFragment"
        app:destination="@+id/profileFragment" />

সমাধানটি হ'ল +অ্যাকশন গন্তব্য থেকে সরানো , কেবল @id/profileFragmentপরিবর্তে ব্যবহার করুন@+id/profileFragment

 <action
        android:id="@+id/action_to_profileFragment"
        app:destination="@id/profileFragment" />

0

আপডেট @ অ্যালেক্স বাদাম সমাধান

যদি নির্দিষ্ট খণ্ডের জন্য কোনও পদক্ষেপ না থাকে এবং খণ্ডটিতে নেভিগেট করতে চান

fun NavController.navigateSafe(
@IdRes actionId: Int, @IdRes fragmentId: Int, args: Bundle? = null,
navOptions: NavOptions? = null, navExtras: Navigator.Extras? = null) 
{
  if (actionId != 0) {
      val action = currentDestination?.getAction(actionId) ?: graph.getAction(actionId)
      if (action != null && currentDestination?.id != action.destinationId) {
          navigate(actionId, args, navOptions, navExtras)
    }
    } else if (fragmentId != 0 && fragmentId != currentDestination?.id)
        navigate(fragmentId, args, navOptions, navExtras)
}


0

আমি খণ্ডের জন্য এই এক্সটেনশন ফাংশনটি তৈরি করেছি:

fun Fragment.safeNavigate(
    @IdRes actionId: Int,
    @Nullable args: Bundle? = null,
    @Nullable navOptions: NavOptions? = null,
    @Nullable navigatorExtras: Navigator.Extras? = null
) {
    NavHostFragment.findNavController(this).apply {
        if (currentDestination?.label == this@safeNavigate::class.java.simpleName) {
            navigate(actionId, args, navOptions, navigatorExtras)
        }
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.