[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7447":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":17,"compositeScore":19,"rankGlobal":10,"rankLanguage":10,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":21,"hasPages":21,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":31,"readmeContent":32,"aiSummary":33,"trendingCount":16,"starSnapshotCount":16,"syncStatus":34,"lastSyncTime":35,"discoverSource":36},7447,"Cicerone","terrakok\u002FCicerone","terrakok","🚦 Cicerone is a lightweight library that makes the navigation in an Android app easy.","",null,"Kotlin",2578,209,50,15,0,1,3,28.97,"Other",false,"master",[24,25,26,27,28,29,30],"android","bottom-navigation","cicerone","fragments","jetpack-navigation","multistack","navigation","2026-06-12 02:01:39","# Cicerone\n[![Maven Central](https:\u002F\u002Fimg.shields.io\u002Fmaven-central\u002Fv\u002Fcom.github.terrakok\u002Fcicerone)](https:\u002F\u002Frepo1.maven.org\u002Fmaven2\u002Fcom\u002Fgithub\u002Fterrakok\u002Fcicerone\u002F)\n[![License: MIT](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLicense-MIT-yellow.svg)](https:\u002F\u002Fopensource.org\u002Flicenses\u002FMIT)  \n\n[![Android Arsenal](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FAndroid%20Arsenal-Cicerone-green.svg?style=true)](https:\u002F\u002Fandroid-arsenal.com\u002Fdetails\u002F1\u002F4700)\n[![Android Weekly](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FAndroid%20Weekly-250-green.svg)](http:\u002F\u002Fandroidweekly.net\u002Fissues\u002Fissue-250)\n[![Android Weekly](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FAndroid%20Weekly-271-green.svg)](http:\u002F\u002Fandroidweekly.net\u002Fissues\u002Fissue-271)  \n\n\u003Ctable>\n    \u003Ctr>\n        \u003Ctd>\n            \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fterrakok\u002FCicerone\u002Fraw\u002Fmaster\u002Fmedia\u002Fnavigation.gif\" width=\"256\"\u002F>\n        \u003C\u002Ftd>\n        \u003Ctd>\n            \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fterrakok\u002FCicerone\u002Fraw\u002Fmaster\u002Fmedia\u002Finsta_tabs.gif\" width=\"256\"\u002F>\n        \u003C\u002Ftd>\n        \u003Ctd>\n            \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fterrakok\u002FCicerone\u002Fraw\u002Fmaster\u002Fmedia\u002Fanimations.gif\" width=\"256\"\u002F>\n        \u003C\u002Ftd>\n    \u003C\u002Ftr>\n    \u003Ctr>\n        \u003Ctd>\n            Power navigation\n        \u003C\u002Ftd>\n        \u003Ctd>\n            Multibackstack\n        \u003C\u002Ftd>\n        \u003Ctd>\n            Result listeners\n        \u003C\u002Ftd>\n    \u003C\u002Ftr>\n\u003C\u002Ftable>\n\nCicerone (a guide who gives information about antiquities and places of interest to sightseers) is a lightweight library that makes the navigation in an Android app easy.  \nIt was designed to be used with the MVP\u002FMVVM\u002FMVI patterns but will work great with any architecture.\n\n## Main advantages\n+ Is not tied to Fragments\n+ Not a framework (very lightweight)\n+ Short navigation calls (no builders)\n+ Static typed checks for screen parameters!\n+ Lifecycle-safe!\n+ Functionality is simple to extend\n+ Suitable for Unit Testing\n\n## Additional features\n+ Opening several screens inside single call (for example: deeplink)\n+ Provides `FragmentFactory` if it needed\n+ `add` or `replace` strategy for opening next screen (see `router.navigateTo` last parameter)\n+ Implementation of parallel navigation (Instagram like)\n+ Predefined navigator ready for Single-Activity apps\n+ Predefined navigator ready for setup transition animation\n\n## How to add Cicerone to your application\nAdd the dependency in your build.gradle:\n```kotlin\ndependencies {\n    \u002F\u002FCicerone\n    implementation(\"com.github.terrakok:cicerone:X.X.X\")\n}\n```\n\nInitialize the library (for example in your Application class):\n```kotlin\nclass App : Application() {\n    private val cicerone = Cicerone.create()\n    val router get() = cicerone.router\n    val navigatorHolder get() = cicerone.getNavigatorHolder()\n\n    override fun onCreate() {\n        super.onCreate()\n        INSTANCE = this\n    }\n\n    companion object {\n        internal lateinit var INSTANCE: App\n            private set\n    }\n}\n```\n\n## How does it work?\n\u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fterrakok\u002FCicerone\u002Fblob\u002Fmaster\u002Fmedia\u002FCiceroneDiagram.png\" alt=\"CiceroneDiagram.png\" width=\"800\"\u002F>\n\nThe `Presenter` calls the navigation method of `Router`.\n\n```kotlin\nclass SamplePresenter(\n    private val router: Router\n) : Presenter\u003CSampleView>() {\n\n    fun onOpenNewScreen() {\n        router.navigateTo(SomeScreen())\n    }\n\n    fun onBackPressed() {\n        router.exit()\n    }\n}\n```\n\n`Router` converts the navigation call to the set of commands and sends them to `CommandBuffer`.\n\n`CommandBuffer` checks whether there are the `_\"active\"_ Navigator`:\n- If yes, it passes the commands to the Navigator. `Navigator` will process them to achive the desired transition.\n- If no, then `CommandBuffer` saves the commands in a queue, and will apply them as soon as a new `_\"active\"_ Navigator` will appear.\n\n```kotlin\nfun executeCommands(commands: Array\u003Cout Command>) {\n    navigator?.applyCommands(commands) ?: pendingCommands.add(commands)\n}\n```\n\n`Navigator` processes the navigation commands. Usually it is an anonymous class inside `Activity`.\n`Activity` provides `Navigator` to the `CommandBuffer` in `_onResume_` and removes it in `_onPause_`.\n\n**Attention**: Use `_onResumeFragments()_` with `FragmentActivity` ([more info](https:\u002F\u002Fdeveloper.android.com\u002Freference\u002Fandroid\u002Fsupport\u002Fv4\u002Fapp\u002FFragmentActivity.html#onResume()))\n\n```kotlin\nprivate val navigator = AppNavigator(this, R.id.container)\n\noverride fun onResumeFragments() {\n    super.onResumeFragments()\n    navigatorHolder.setNavigator(navigator)\n}\n\noverride fun onPause() {\n    navigatorHolder.removeNavigator()\n    super.onPause()\n}\n```\n\n## Navigation commands\nThese commands will fulfill the needs of the most applications. But if you need something special - just add it!\n+ Forward - Opens new screen\n![](https:\u002F\u002Fgithub.com\u002Fterrakok\u002FCicerone\u002Fraw\u002Fmaster\u002Fmedia\u002Fforward_img.png)\n+ Back - Rolls back the last transition\n![](https:\u002F\u002Fgithub.com\u002Fterrakok\u002FCicerone\u002Fraw\u002Fmaster\u002Fmedia\u002Fback_img.png)\n+ BackTo - Rolls back to the needed screen in the screens chain\n![](https:\u002F\u002Fgithub.com\u002Fterrakok\u002FCicerone\u002Fraw\u002Fmaster\u002Fmedia\u002FbackTo_img.png)\n+ Replace - Replaces the current screen\n![](https:\u002F\u002Fgithub.com\u002Fterrakok\u002FCicerone\u002Fraw\u002Fmaster\u002Fmedia\u002Freplace_img.png)\n\n## Predefined navigator\nThe library provides predefined navigator for _Fragments_ and _Activity_.\nTo use, just provide it with the container and _FragmentManager_.\n```kotlin\nprivate val navigator = AppNavigator(this, R.id.container)\n```\n\nA custom navigator can be useful sometimes:\n```kotlin\nprivate val navigator = object : AppNavigator(this, R.id.container) {\n    override fun setupFragmentTransaction(\n        screen: FragmentScreen,\n        fragmentTransaction: FragmentTransaction,\n        currentFragment: Fragment?,\n        nextFragment: Fragment\n    ) {\n        \u002F\u002Fsetup your animation\n    }\n\n    override fun applyCommands(commands: Array\u003Cout Command>) {\n        hideKeyboard()\n        super.applyCommands(commands)\n    }\n}\n```\n\n## Screens\nDescribe your screens as you like e.g. create a Kotlin `object` with all application screens:\n```kotlin\nobject Screens {\n    fun Main() = FragmentScreen { MainFragment() }\n    fun AddressSearch() = FragmentScreen { AddressSearchFragment() }\n    fun Profile(userId: Long) = FragmentScreen(\"Profile_$userId\") { ProfileFragment(userId) }\n    fun Browser(url: String) = ActivityScreen { Intent(Intent.ACTION_VIEW, Uri.parse(url))  }\n}\n```\n\nAdditional you can use `FragmentFactory` for creating your screens:\n```kotlin\nfun SomeScreen() = FragmentScreen { factory: FragmentFactory -> ... }\n```\n\n## Screen parameters and result listener\n```kotlin\n\u002F\u002Fyou have to specify screen parameters via new FragmentScreen creation\nfun SelectPhoto(resultKey: String) = FragmentScreen {\n    SelectPhotoFragment.getNewInstance(resultKey)\n}\n```\n\n```kotlin\n\u002F\u002Flisten result\nfun onSelectPhotoClicked() {\n    router.setResultListener(RESULT_KEY) { data ->\n        view.showPhoto(data as Bitmap)\n    }\n    router.navigateTo(SelectPhoto(RESULT_KEY))\n}\n\n\u002F\u002Fsend result\nfun onPhotoClick(photo: Bitmap) {\n    router.sendResult(resultKey, photoRes)\n    router.exit()\n}\n```\n\n## Sample\nTo see how to add, initialize and use the library and predefined navigators see the **sample project**  \n(thank you [@Javernaut](https:\u002F\u002Fgithub.com\u002FJavernaut) for support new library version and migrate sample project to Kotlin!)\n\nFor more complex use case check out the [GitFox (Android GitLab client)](https:\u002F\u002Fgitlab.com\u002Fterrakok\u002Fgitlab-client)\n\n## Applications that use Cicerone\n\u003Ca href=\"https:\u002F\u002Fplay.google.com\u002Fstore\u002Fapps\u002Fdetails?id=ru.foodfox.client\">\u003Cimg src=\"https:\u002F\u002Fplay-lh.googleusercontent.com\u002FgWYedIqy8QujCQOn0kzEIBEkGLBSpuKvFm-fMcfkWnJ1Oirtv847xAE4OyhAaohdcp5V=s360\" width=\"64\" \u002F> Яндекс.Еда — доставка еды\u002Fпродуктов. Food delivery\u003C\u002Fa>\u003Cbr>\n\u003Ca href=\"https:\u002F\u002Fplay.google.com\u002Fstore\u002Fapps\u002Fdetails?id=com.kms.me\">\u003Cimg src=\"https:\u002F\u002Fplay-lh.googleusercontent.com\u002FIBzu0tlHd_amw2HbjBLOZiCfK-0tn0CnwkMdOd1toP23rdHUV-i7L2ViNKgIg687=s360\" width=\"64\" \u002F> Kaspersky Internet Security\u003C\u002Fa>\u003Cbr>\n\u003Ca href=\"https:\u002F\u002Fplay.google.com\u002Fstore\u002Fapps\u002Fdetails?id=com.deliveryclub\">\u003Cimg src=\"https:\u002F\u002Fplay-lh.googleusercontent.com\u002Fm6-gFunvj7aQD5fdv8EdJZBN5M4REIobTaPZPYS0K5Td7CNYnazN7fOKiPwwaY3hJw=s360\" width=\"64\" \u002F> Delivery Club – Доставка еды и продуктов\u003C\u002Fa>\u003Cbr>\n\u003Ca href=\"https:\u002F\u002Fplay.google.com\u002Fstore\u002Fapps\u002Fdetails?id=ru.hh.android\">\u003Cimg src=\"https:\u002F\u002Fplay-lh.googleusercontent.com\u002FYpAV7Q-ZJhI5tzFk_wEX-7-x2BydtnCtFTVUrmq0zAO6jLCLA4nNcfem3p_Pyowg9w=s360\" width=\"64\" \u002F> Поиск работы на hh. Вакансии рядом с домом\u003C\u002Fa>\u003Cbr>\n\u003Ca href=\"https:\u002F\u002Fplay.google.com\u002Fstore\u002Fapps\u002Fdetails?id=com.foodient.whisk\">\u003Cimg src=\"https:\u002F\u002Fplay-lh.googleusercontent.com\u002FeKotZjJcZOU2_L9t2l34EEY7aGl5zhvKVuEbF0Kc4MRs_pAC2SJgOnWMkMTFjR_e9EY=s360\" width=\"64\" \u002F> Whisk: Recipe Saver, Meal Planner & Grocery List\u003C\u002Fa>\u003Cbr>\n\u003Ca href=\"https:\u002F\u002Fplay.google.com\u002Fstore\u002Fapps\u002Fdetails?id=kz.beeline.odp\">\u003Cimg src=\"https:\u002F\u002Fplay-lh.googleusercontent.com\u002FhzgjpQQpy6Z-Byye0aVKSv9P7h8yx58i6pVkQtiM6jB99iWFXjYfKeaPqJ3wm6Rtb38=s360\" width=\"64\" \u002F> Мой Beeline (Казахстан)\u003C\u002Fa>\u003Cbr>\n\u003Ca href=\"https:\u002F\u002Fplay.google.com\u002Fstore\u002Fapps\u002Fdetails?id=com.mercuryo.app\">\u003Cimg src=\"https:\u002F\u002Fplay-lh.googleusercontent.com\u002FFKulXdc15r5PWX6hTZi2i3iaJjcQHwd9xParp6YPiQ2KiBqza7jwEt_b_tqLwXpyEHg=s360\" width=\"64\" \u002F> Mercuryo Bitcoin Cryptowallet\u003C\u002Fa>\u003Cbr>\n\u003Ca href=\"https:\u002F\u002Fplay.google.com\u002Fstore\u002Fapps\u002Fdetails?id=com.warefly.checkscan\">\u003Cimg src=\"https:\u002F\u002Fplay-lh.googleusercontent.com\u002F2c2uuiSl2vwGgp-vdI-VArQEMdSSXk1neUK5A-Udc0WANPcvp5kBJFEugrFiXnxUc7k=s360\" width=\"64\" \u002F> ЧекСкан - кэшбэк за чеки, цены и акции в магазинах\u003C\u002Fa>\u003Cbr>\n\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Feduard1abdulmanov123\u002FNews\">\u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002Feduard1abdulmanov123\u002FNews\u002Fdev\u002Fapp\u002Fsrc\u002Fmain\u002Fres\u002Fmipmap-xxxhdpi\u002Fic_launcher.png\" width=\"64\" \u002F> RSS Reader для Вести.Ru\u003C\u002Fa>\u003Cbr>\n\u003Ca href=\"https:\u002F\u002Fplay.google.com\u002Fstore\u002Fapps\u002Fdetails?id=com.epam.connect.android\">\u003Cimg src=\"https:\u002F\u002Fplay-lh.googleusercontent.com\u002FaN7R6BiR7yt7b3oEoBI30pVwzsdzaWe3TWpw8c9igqoOj79Pm2xVh4_C4qwjSKwjVio=s360\" width=\"64\" \u002F> EPAM Connect\u003C\u002Fa>\u003Cbr>\n\u003Ca href=\"https:\u002F\u002Fplay.google.com\u002Fstore\u002Fapps\u002Fdetails?id=org.consumerreports.ratings\">\u003Cimg src=\"https:\u002F\u002Fplay-lh.googleusercontent.com\u002FdEdOwZOjXAdamytxY1TgY8LS-Hc9FKCcit5HP1RyaKqRAWjDJEyFSQS1XlqQPpeY5UI=s360\" width=\"64\" \u002F> Consumer Reports: Product Reviews & Ratings\u003C\u002Fa>\u003Cbr>\n\u003Ca href=\"https:\u002F\u002Fplay.google.com\u002Fstore\u002Fapps\u002Fdetails?id=ru.zakaz.android\">\u003Cimg src=\"https:\u002F\u002Fplay-lh.googleusercontent.com\u002Fjj18yK2dB2MHZ_QdO21aXyznGXteIF2q4mgxY4ubLhFv9gwZqHVDeu1i2FmanS-0Furm=s360\" width=\"64\" \u002F> Zakaz.ru\u003C\u002Fa>\u003Cbr>\n\n## Participants\n+ Idea and code - Konstantin Tskhovrebov (@terrakok)\n+ Architecture advice, documentation and publication - Vasili Chyrvon (@Jeevuz)\n\n## License\n```\nMIT License\n\nCopyright (c) 2017 Konstantin Tskhovrebov (@terrakok)\n                   and Vasili Chyrvon (@Jeevuz)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and\u002For sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n","Cicerone 是一个轻量级库，旨在简化 Android 应用中的导航过程。其核心功能包括支持多种架构模式（如 MVP、MVVM 和 MVI）下的灵活导航，同时具备静态类型检查屏幕参数、生命周期安全等技术特点。此外，Cicerone 支持多返回栈、结果监听器以及平行导航等功能，使得实现类似 Instagram 的复杂导航需求变得简单。该库非常适合用于需要高效且易于测试的导航解决方案的应用场景中，特别是那些采用单一活动设计或希望减少框架依赖以保持项目简洁性的开发者。",2,"2026-06-11 03:12:21","top_language"]