Zhuinden / simple-stack

[ACTIVE] Simple Stack, a backstack library / navigation framework for simpler navigation and state management (for fragments, views, or whatevers).
Apache License 2.0
1.36k stars 76 forks source link

The relation between simple-stack and Navigation Components #244

Closed impvd closed 3 years ago

impvd commented 3 years ago

Hi @Zhuinden , I just found your repo from your post, it was an excellent read, thanks!

I did try to comment on reddit, however Reddit archived it, and I couldn't able to comment.

Well, I must say that I'm pretty new to Android dev, let me know when I was wrong.

When I first learned about fragments, there're samples like:

class MainActivity : AppCompatActivity() {
    private val firstFragment = DetailsFragment(1)
    private val secondFragment = DetailsFragment(2)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        addFragment(firstFragment)
        addFragment(secondFragment)
        first_fragment.setOnClickListener {
            replaceFragment(firstFragment)
        }
        second_fragment.setOnClickListener {
            replaceFragment(secondFragment)
        }
    }

    private fun addFragment(f: Fragment) {
        val transaction = supportFragmentManager.beginTransaction()
        transaction.add(R.id.fragment_container, f)
        transaction.commit()
    }

    private fun replaceFragment(f : Fragment){
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.fragment_container, f)
        transaction.commit()
    }
}

Yep, it make sense, just click to change the fragment, no need to create another activity.

Later, I learned Navigation Components, to be honest, I don't think it's easy to take away. We need to create a navigation_graph.xml in the res folder, add fragments, draw the lines between fragments in AS. And finally, we need to add code like:

view.textView.setOnClickListener {
    Navigation.findNavController(view).navigate(R.id.action_firstFragment_to_secondFragment)
}

My Question

  1. From my understanding at first glance of your post, does simple-stack an alternative to Navigation Components?
  2. Does Navigation Components or simple-stack would help to reuse existing Fragments?

For the 2nd question, I believe that it's import to help making the performance better.

Zhuinden commented 3 years ago
class MainActivity : AppCompatActivity() {
    private val firstFragment = DetailsFragment(1)
    private val secondFragment = DetailsFragment(2)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        addFragment(firstFragment)
        addFragment(secondFragment)
        first_fragment.setOnClickListener {
            replaceFragment(firstFragment)
        }
        second_fragment.setOnClickListener {
            replaceFragment(secondFragment)
        }
    }

    private fun addFragment(f: Fragment) {
        val transaction = supportFragmentManager.beginTransaction()
        transaction.add(R.id.fragment_container, f)
        transaction.commit()
    }

    private fun replaceFragment(f : Fragment){
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.fragment_container, f)
        transaction.commit()
    }
}

This snippet has about 4 Fragment management errors, namely you will either lose state as you switch between fragments, or you'll get overlapping ones.


From my understanding at first glance of your post, does simple-stack an alternative to Navigation Components?

Yes, simple-stack is effectively an alternative to Navigation component.

Hypothetically it would be possible to write a custom navigator that uses Simple-Stack as the implementation of Navigation, but Navigation doesn't expose a lot of data which makes this idea a bit tricky to do.

Does Navigation Components or simple-stack would help to reuse existing Fragments?

Navigation component already also reuses fragments, it just destroys the views as you navigate. If you don't want to destroy the view, you would need to make the fragments "not be stopped" when you navigate away from that, you can do that with FragmentTransaction.show/hide in theory but Nav component does not support it without a custom navigator.

Simple-Stack lets you customize it like this and then you'd be using show/hide instead of attach/detach (when using the FragmentStateChanger).

Overall you'd be using code to navigate like

view.textView.setOnClickListener {
    backstack.goTo(SecondScreen())
}
impvd commented 3 years ago

Cool! Thanks @Zhuinden

This snippet has about 4 Fragment management errors, namely you will either lose state as you switch between fragments, or you'll get overlapping ones.

I didn't realize that! I found this snippet from One of Google search results

Out of curiosity, I found another snippet, A very large MainActivity.kt, which looks like:

fragment2go = getIntent().getStringExtra("feature");

if fragment2go == "Feature1":
    fragment = XXFragment()
else if:
    ...
    // And about dozens of else if branch from here

Technically this is a single activity multiple fragments architecture, there're lots of intent from each fragment, and it will go to another fragment by put different "feature" in the intent to trigger the MainActivity.kt.

I was wondering if maybe you could share your thoughts and feelings on it?

Zhuinden commented 3 years ago

You're pretty much never supposed to create a new Fragment instance without checking if it already exists using findFragmentByTag, refer to the article https://proandroiddev.com/the-seven-actually-10-cardinal-sins-of-android-development-491d2f64c8e0