android / architecture-components-samples

Samples for Android Architecture Components.
https://d.android.com/arch
Apache License 2.0
23.45k stars 8.28k forks source link

findNavController().navigate(R.id.action) always destroy my current fragment #749

Closed kadaluarsa closed 4 years ago

kadaluarsa commented 5 years ago

Well I have some case and need to keep my current fragment even I open some new fragment, but when I put findNavController().navigate(R.id.someaction) in my click listener, its always destroy my current fragment, I already search on StackOverflow but im not found any solution for this :( Thank you

pablichjenkov commented 5 years ago

Why you care about current Fragment destruction? You should not have data in your Fragment but in a ViewModel associated with it instead. If your Fragment gets destroyed due to any configuration change you will lose your state data anyways. The stateless your Fragment is, the better. Fragments should only care about its View logic and the Lifecycle events. Other logic don't belong there.

kadaluarsa commented 5 years ago

Because I have recyclerview of product at fragment A and when I click findNavController().navigate(R.id.actionFragAtoFragB) to open detail of product, the problem is when I'm on fragment B and then back to fragment A the scroll position of recyclerview got reset because the Fragment A has been destroyed when I move to Fragment B

hoc081098 commented 5 years ago

My app https://github.com/hoc081098/ComicApp work well with Navkgation Component

pablichjenkov commented 5 years ago

@kadaluarsa I see your point. There is definitely some use cases where not destroying the fragment data will improve the performance. Your case is one of them. I think you can save your current recyclerView position in your ViewModel and when your fragment is recreated back, then set that position again. Of-course is not perfect since the user may experience a little jump. There is an issue open for this already. If you watch 2019 Android Summit recently. Ian Lakes gave a talk about the future of Fragments. They are planning to save the state of the Fragments in back stack.

0rp3u commented 5 years ago

You telling me the fragment is getting destroyed or is the fragment's view getting destroyed? Every time you navigate back to a fragment it's view gets recreated but not the fragment instance. verify if on destroy is being called and if you are not instantiating the adapter multiple time because you instantiate it in onCreateView or on one of the subsequent lifecycle callbacks.

joezorry commented 5 years ago

@kadaluarsa If you set an id to the recycler view and parent views the scroll state should be automatically re-created even if the view is getting destroyed.

The ids is the only way the framework can save the view state :)

ianhanniballake commented 4 years ago

Fragments already save the view state of Fragments on the back stack. If you're handling configuration changes and process death (i.e., testing with 'Don't keep activities') correctly, you'll also handle being on the back stack without issues.

sam43 commented 4 years ago

Not even a convincing solution I got for the issue. Whenever a component released for android by google is not up to the mark always. Those components or feature covers only half of the test cases. I don't think it is necessary to destroy the current fragment to navigate to another with navController. I think this is a valid issue to be sorted out.

robin2046 commented 4 years ago

Not even a convincing solution I got for the issue. Whenever a component released for android by google is not up to the mark always. Those components or feature covers only half of the test cases. I don't think it is necessary to destroy the current fragment to navigate to another with navController. I think this is a valid issue to be sorted out.

True. And combined with the live data observers, which I don't want it to be called many times in onCreateView, even make the logic more of a mess.

ekoo commented 3 years ago

I have same issue with you @kadaluarsa , to fix that you must initialize adapter outside fragment lifecycle, for example

class MyFragment : Fragment() {

private val myViewModel by viewModel<MyViewModel>()
private val myAdapter = MyAdapter()

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

    Log.d("checkListData", myAdapter.currentList.toString())
    myViewModel.someListData.observe(viewLifecycleOwner){ listData ->
        myAdapter.submitList(listData)
    }
}

}

damiancioo commented 3 years ago

What if we use WebView and don't want to reload a page everytime someone is returning to it?

r020477888 commented 3 years ago

What if we use WebView and don't want to reload a page everytime someone is returning to it?

Have you found a solution? I have same problem.

MartinCazares commented 3 years ago

It does feel like a half baked implementation for navigation, or at least is missing that specific fairly common case. I've been using a hack that have worked fairly well for my cases, even tho I'm aware that this is a bit dirty solution I decided to use:

startActivity(Context, Activity(that should've been a fragment))

in those specific cases. This way I prevent the previous fragment from being destroyed since the lifecycle goes up to "onStop" step only and doesn't destroy the fragment. Again, I'm using this walk around only for those specific cases, other than that I still rely on the navigation component itself and the Single Activity philosophy...

freddy24 commented 1 year ago

What if we use WebView and don't want to reload a page everytime someone is returning to it?

have you found a solution?

lzxshare commented 1 year ago

Unfortunately, this issue has been closed,they never listen to developers' opinons,I am so disappointed with Google's capriciousness

karan-for-you commented 11 months ago

I navigate via Navigation Library from Fragment A to B to choose an itemview from RecyclerView in Fragment B, how do I not let A destroy itself when B is opened and when item is selected from B and tt gets displayed in A.

dxshindeo commented 8 months ago

@kadaluarsa If you set an id to the recycler view and parent views the scroll state should be automatically re-created even if the view is getting destroyed.

The ids is the only way the framework can save the view state :)

What? Either what you said is plain wrong or something else is up, because after I have scrolled this view down a bit, go to another fragment, then come back to this one (with navController.navigate(my_destination_id)) - the scrollview's position is reset, which we don't want it to be.

<?xml version="1.0" encoding="utf-8"?>
<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/aaa"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.core.widget.NestedScrollView
        android:id="@+id/nestedScrollview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/wrapperNestedScrollviewContent"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/test"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="500dp"
                android:layout_marginBottom="500dp"
                android:text="test fragment"
                android:textColor="@color/white"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

        </androidx.constraintlayout.widget.ConstraintLayout>

    </androidx.core.widget.NestedScrollView>

</androidx.constraintlayout.widget.ConstraintLayout>