Why onViewCreated is called twice in android app using navigation components
Asked Answered
A

2

21

I have a simple application with one activity and around 4 fragments. I am using android navigation components. Starting from my splash fragment to next fragments every time fragment is changed, OnCreateview and onViewCreated is called twice, Once when the fragment is initially created and 2nd when i use findnavController.navigate(). I don`t know why it is called twice, can any one specify reason for this. This is my splash class.

class SplashFragment : Fragment(), SocketConnection.SocketCallbacks {

    lateinit var binding: SplashFragmentBinding


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Timber.d("on View created")
        SocketConnection.getInstance.socketConnectionListener(this)

    }


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        Timber.d("on create view")
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_splash, container, false)
        return binding.root
    }

    override fun onResume() {
        super.onResume()
        Timber.d("On resume")
        activity?.setupBackButton(false)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Timber.d("On create")
        setHasOptionsMenu(false)
    }
    
    override fun onConnection(param: String) {
        Timber.d("Items received")
        findNavController().navigate(R.id.action_splashFragment_to_privacyFragment, bundle)        
    }

This is xml of MainActivity

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



 <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>

This is my nav graph

<?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/splashFragment">
    <fragment
        android:id="@+id/splashFragment"
        android:name="com.appname.ui.SplashFragment"
        android:label="fragment_splash"
        tools:layout="@layout/fragment_splash">
        <action
            android:id="@+id/action_splashFragment_to_voiceChatFragment"
            app:destination="@id/voiceChatFragment"
            app:launchSingleTop="true"
            app:popUpTo="@id/nav_graph"
            app:popUpToInclusive="true" />
        <action
            android:id="@+id/action_splashFragment_to_registerFragment2"
            app:destination="@id/registerFragment2"
            app:launchSingleTop="true"
            app:popUpTo="@id/nav_graph"
            app:popUpToInclusive="true" />
        <action
            android:id="@+id/action_splashFragment_to_privacyFragment"
            app:destination="@id/privacyFragment"
            app:launchSingleTop="true"
            app:popUpTo="@id/nav_graph"
            app:popUpToInclusive="true" />
    </fragment>

    <fragment
        android:id="@+id/registerFragment2"
        android:name="com.appname.ui.RegisterFragment"
        android:label="fragment_register"
        tools:layout="@layout/fragment_register" >
        <action
            android:id="@+id/action_registerFragment2_to_voiceChatFragment"
            app:destination="@id/voiceChatFragment"
            app:popUpTo="@id/nav_graph"
            app:popUpToInclusive="true"
            app:launchSingleTop="true" />
    </fragment>
    <fragment
        android:id="@+id/privacyFragment"
        android:name="com.appname.ui.PrivacyFragment"
        android:label="PrivacyFragment" >
        <action
            android:id="@+id/action_privacyFragment_to_registerFragment2"
            app:destination="@id/registerFragment2"
            app:popUpTo="@id/nav_graph"
            app:popUpToInclusive="true"
            app:launchSingleTop="true" />
        <action
            android:id="@+id/action_privacyFragment_to_voiceChatFragment"
            app:destination="@id/voiceChatFragment"
            app:popUpTo="@id/nav_graph"
            app:popUpToInclusive="true"
            app:launchSingleTop="true" />
    </fragment>
    <fragment
        android:id="@+id/voiceChatFragment"
        android:name="com.appname.ui.VoiceChatFragment"
        android:label="VoiceChatFragment" />
    <fragment
        android:id="@+id/profileFragment"
        android:name="com.appname.ui.ProfileFragment"
        android:label="ProfileFragment" />
</navigation>

I have seen many question like this but they are all related to fragment manager. But I am using android navigation components. I am unable to identify why is called twice. Can anyone point me to the right direction or point out the issue is provided code.

Abstention answered 18/10, 2020 at 14:12 Comment(4)
is it happening when you come to previous fragment on pressing back button? Please note when you come back fragment will get recreated so it will call onCreateView , onViewCreated method.Outlast
I think you didn`t understand the question correctly. OnCreateView is called twice without pressing back button or on any other event. Its called twice, once when fragment initially creates and again just after findNavController.navigate event.Abstention
did you find an answer to this? - i am seeing a similar problemBret
I used this code line AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) to disable night mode in the onCreate/Activity. When I removed this code, twice call problem is fixed. May be it helps you.Mango
C
24

You should set the navigation graph once either in the layout or in the activity. If by mistake it has set at both the places it will create the startDestination fragment twice.

//In the host fragment
app:navGraph="@navigation/<your navigation graph>"

OR

//In the activity
findNavController().graph = <your navigation graph>
Caz answered 12/2, 2021 at 11:0 Comment(0)
S
5

Not sure if it solves the problem, but I was struggling with something similar. In my approach I was trying to implement navigation using NavigationAdvancedSample to save back stacks managed by bottom navigation (https://github.com/android/architecture-components-samples/tree/master/NavigationAdvancedSample). If you use similar approach, you can check if setting app:navGraph="@navigation/nav_graph in FragmentContainerView is necessary. In my case, removing it solved the problem because I set navigation graphs in main activity using setupWithNavController method from BottomNavigationView.

Sanguineous answered 5/12, 2020 at 19:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.