Skip to content
Season edited this page Dec 8, 2023 · 1 revision

Butterfly

Butterfly is a versatile component-based navigation framework based on Coroutine + Annotation + Ksp. Not only does it support navigation for Activity, Fragment, and DialogFragment, but it also supports navigation for Compose pages.

Butterfly supports configuring startup modes for Fragment and Composite navigation, including Standard mode navigation ClearTop clears stack top mode navigation and SingleTop reuse mode navigation.

Butterfly provides a unified fallback stack for managing all types of page navigation, using standard fallback APIs to reduce developer workload.

Butterfly also provides a powerful framework for inter component communication, allowing for true component decoupling without any dependencies between components.

Basic Usage

1.Page navigation

Using Butterfly to navigate a page only requires two steps. Add a @Destination annotation to the page that needs to be navigated, and then use the navigate method to complete the navigation.

@Destination("test/activity")
class TestActivity : AppCompatActivity()

@Destination("test/fragment")
class TestFragment : Fragment()

@Destination("test/dialog")
class TestDialogFragment : DialogFragment()

@Destination("test/compose")
@Composable
fun TestScreen() {}

//navigate
Butterfly.of(context).navigate("test/xxx")

//Navigate and get the return data
Butterfly.of(context).navigate("test/xxx") { result ->
    if (result.isSuccess) {
        val bundle = result.getOrDefault(Bundle.EMPTY)
        val str by bundle.params<String>()
        binding.tvResult.text = str
    }
}

//pop back
Butterfly.of(context).popBack()

//pop back and return data
Butterfly.of(this).popBack("result" to "result value: 123")

2.Component communication

Butterfly uses @evade and @EvadeImpl annotations to communicate between components, and can communicate between components without dependencies at all.

For example, two components, Home and Dashboard, Dashboard component require calling methods in component Home:

//Define the Api corresponding to Home in the component dashboard and add @Evade annotation
@Evade
interface DashboardCallHomeApi {
    fun showHome(fragmentManager: FragmentManager, container: Int)
}


//Implement the corresponding Api in the component Home and add the @EvadeImpl annotation
@EvadeImpl
class DashboardCallHomeApiImpl {  //The implementation class name must end with Impl
    val TAG = "home_tag"

    //The implementation of HomeApi requires the same method name and method parameters
    fun showHome(fragmentManager: FragmentManager, container: Int) {
        val homeFragment = HomeFragment()
        fragmentManager.beginTransaction()
            .replace(container, homeFragment, TAG)
            .commit()
    }
}

//Then you can call the interface in the component Home in the component dashboard:
val dashboardCallHomeApi = Butterfly.evade<DashboardCallHomeApi>()
dashboardCallHomeApi.showHome(supportFragmentManager, R.id.container)