{"id":15039369,"url":"https://github.com/bytedance/scene","last_synced_at":"2025-05-14T06:13:39.720Z","repository":{"id":41467405,"uuid":"213812935","full_name":"bytedance/scene","owner":"bytedance","description":"Android Single Activity Framework compatible with Fragment.","archived":false,"fork":false,"pushed_at":"2025-04-24T04:43:35.000Z","size":7231,"stargazers_count":2203,"open_issues_count":1,"forks_count":205,"subscribers_count":41,"default_branch":"master","last_synced_at":"2025-04-24T05:27:47.891Z","etag":null,"topics":["activity","android","android-architecture","android-library","fragments","navigation","single-activity-pattern"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bytedance.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-10-09T03:32:13.000Z","updated_at":"2025-04-24T04:43:39.000Z","dependencies_parsed_at":"2022-08-10T02:27:18.974Z","dependency_job_id":"deea656f-1b22-492e-abdb-a133498f55fb","html_url":"https://github.com/bytedance/scene","commit_stats":{"total_commits":455,"total_committers":8,"mean_commits":56.875,"dds":0.08131868131868136,"last_synced_commit":"1f9d8d42f9c6d82211f1790b7651703679c98d4d"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytedance%2Fscene","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytedance%2Fscene/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytedance%2Fscene/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytedance%2Fscene/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bytedance","download_url":"https://codeload.github.com/bytedance/scene/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254083569,"owners_count":22011901,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["activity","android","android-architecture","android-library","fragments","navigation","single-activity-pattern"],"created_at":"2024-09-24T20:42:35.348Z","updated_at":"2025-05-14T06:13:39.682Z","avatar_url":"https://github.com/bytedance.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n    \u003ch1\u003eScene\u003c/h1\u003e\n    \u003cp\u003eTikTok Single Activity Framework.\u003c/p\u003e\n    \u003cp\u003eEnglish\u0026nbsp;\u0026nbsp;|\u0026nbsp;\u0026nbsp;\n    \u003ca target=\"_blank\" href=\"https://github.com/bytedance/scene/blob/master/README_cn.md\"\u003e简体中文\u003c/a\u003e\u0026nbsp;\u0026nbsp;|\u0026nbsp;\u0026nbsp;\n    \u003ca target=\"_blank\" href=\"https://github.com/bytedance/scene/blob/main/README_ja.md\"\u003e日本語\u003c/a\u003e\u0026nbsp;\u0026nbsp;\n    \u003cbr/\u003e\n\u003c/div\u003e\n\n\n[![GitHub license](https://img.shields.io/github/license/bytedance/scene)](https://github.com/bytedance/scene/blob/master/LICENSE)\n[![](https://jitpack.io/v/bytedance/scene.svg)](https://jitpack.io/#bytedance/scene)\n[![API](https://img.shields.io/badge/api-21%2B-green)](https://developer.android.com/about/dashboards)\n\n**Scene** is a lightweight library of navigation and ui composition based on view.\n\n- [x] Compatible with Fragment framework\n- [x] Simple navigation stack management, support multi-navigation-stack\n- [x] Improved lifecycle management and distribution\n- [x] Easier to implement complex cross-page and shared-element animation\n- [x] Supports modification and automatic restoration of Activity and Window properties\n- [x] Support exchange data between Scenes, support request and grant permissions in Scene\n- [x] Support save and recovery parcable state of Scene\n- [x] No R8 / Proguard configuration required\n\n[Download the latest Sample APK](https://github.com/bytedance/scene/blob/master/misc/latest_sample.apk)\n\nIntroduction\n-------------\nScene is designed to replace the use of Activity and Fragment on navigation and page segmentation.\n\nThe main problems of **Activity**:\n1. The stack management of Activity is weak, Intent and LaunchMode are confusing, even if various of hacks still can't completely avoid issues like black screen\n2. The performance of Activity is poor, average startup time of an empty Activity is more than 60ms (on Samsung S9)\n3. Because the Activity is forced to support states recovery, it causes some problems:\n   - Transition animation has limited ability, difficult to implement complex interactive animations.\n   - Shared-element animation is basically unavailable, and there are some crashes unresolved in Android Framework.\n   - Every time starting a new Activity, onSaveInstance() of the previous Activity must be executed completely first, which will lose much performance.\n4. Activity relies on the Manifest file to cause injection difficulties, which also result in that Activity dynamics requires a variety of hacks\n\nThe main problems of **Fragment**:\n1. [Google Navigation Component](https://developer.android.com/guide/navigation) will destory Fragment' view when it is invisible\n2. There are many crashes that the Google official can't solve for a long time. Even if you don't use Fragment, it may still trigger a crash in the OnBackPressed() of AppCompatActivity.\n3. The add/remove/hide/show operation is not executed immediately. With nest Fragments even if you use commitNow(), the status update of the sub Fragments cannot be guaranteed.\n\nThe Scene framework tries to solve these problems of the Activity and Fragment mentioned above.\n\nProvides a simple, reliable, and extensible API for a lightweight navigation and page segmentation solution\n\nAt the same time, we provide a series of migration solutions to help developers gradually migrate from Activity and Fragment to Scene.\n\nGet Started\n-------------\nAdd it to your root build.gradle at the end of repositories:\n```gradle\n//build.gradle\nallprojects {\n\trepositories {\n\t\t...\n\t\tmaven { url 'https://jitpack.io' }\n\t}\n}\n```\n\n```kotlin\n//or settings.gradle.kts\ndependencyResolutionManagement {\n    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)\n    repositories {\n        ...\n        maven { url = uri(\"https://jitpack.io\") }\n    }\n}\n```\n\nAdd it to your build.gradle, [latest_version](https://github.com/bytedance/scene/releases) :\n```gradle\ndependencies {\n\timplementation 'com.github.bytedance:scene:$latest_version'\n        //or\n\timplementation 'com.github.bytedance.scene:scene:$latest_version'\n\timplementation 'com.github.bytedance.scene:scene_navigation:$latest_version'\n\timplementation 'com.github.bytedance.scene:scene_ui:$latest_version'\n\timplementation 'com.github.bytedance.scene:scene_dialog:$latest_version'\n\timplementation 'com.github.bytedance.scene:scene_shared_element_animation:$latest_version'\n\timplementation 'com.github.bytedance.scene:scene_ktx:$latest_version'\n}\n```\n\n```kotlin\n//or build.gradle.kts\ndependencies {\n    implementation (\"com.github.bytedance:scene:$latest_version\")\n    //or\n    implementation (\"com.github.bytedance.scene:scene:$latest_version\")\n    implementation (\"com.github.bytedance.scene:scene_navigation:$latest_version\")\n    implementation (\"com.github.bytedance.scene:scene_ui:$latest_version\")\n    implementation (\"com.github.bytedance.scene:scene_dialog:$latest_version\")\n    implementation (\"com.github.bytedance.scene:scene_shared_element_animation:$latest_version\")\n    implementation (\"com.github.bytedance.scene:scene_ktx:$latest_version\")\n}\n```\n\nFor simple usage, just let your Activity inherit from SceneActivity:\n\n```kotlin\nclass MainActivity : SceneActivity() {\n    override fun getHomeSceneClass(): Class\u003cout Scene\u003e {\n        return MainScene::class.java\n    }\n\n    override fun supportRestore(): Boolean {\n        return false\n    }\n}\n```\n\nA simple Scene example:\n\n```kotlin\nclass MainScene : AppCompatScene() {\n    private lateinit var mButton: Button\n    override fun onCreateContentView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View? {\n        val frameLayout = FrameLayout(requireSceneContext())\n        mButton = Button(requireSceneContext())\n        mButton.text = \"Click\"\n        frameLayout.addView(mButton, FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT))\n        return frameLayout\n    }\n\n    override fun onActivityCreated(savedInstanceState: Bundle?) {\n        super.onActivityCreated(savedInstanceState)\n        setTitle(\"Main\")\n        toolbar?.navigationIcon = null\n        mButton.setOnClickListener {\n            navigationScene?.push(SecondScene())\n        }\n    }\n}\n\nclass SecondScene : AppCompatScene() {\n    private val mId: Int by lazy { View.generateViewId() }\n\n    override fun onCreateContentView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View? {\n        val frameLayout = FrameLayout(requireSceneContext())\n        frameLayout.id = mId\n        return frameLayout\n    }\n\n    override fun onActivityCreated(savedInstanceState: Bundle?) {\n        super.onActivityCreated(savedInstanceState)\n        setTitle(\"Second\")\n        add(mId, ChildScene(), \"TAG\")\n    }\n}\n\nclass ChildScene : Scene() {\n    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View {\n        val view = View(requireSceneContext())\n        view.setBackgroundColor(Color.GREEN)\n        return view\n    }\n}\n```\n\nFragment\n-------------\ncopy [FragmentScene](https://github.com/bytedance/scene/wiki/Scene-load-Fragment) to your project\n\n```kotlin\nclass YourFragment : Fragment() {\n    override fun onCreateView(\n        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?\n    ): View {\n        return View(requireContext())\n    }\n\n    override fun onActivityCreated(savedInstanceState: Bundle?) {\n        super.onActivityCreated(savedInstanceState)\n        val parentScene = ViewUtlity.findScene(this.view()) as YourFragmentScene\n    }\n}\n\nclass YourFragmentScene : FragmentScene() {\n    override val fragmentClass = YourFragment::class.java\n}\n```\n\nCompose\n-------------\nhttps://github.com/bytedance/scene/wiki/Compose\n\nSample\n--------\nScene sample is built using Gradle. On Linux, simply run:\n\n    ./gradlew installDebug\n\nDocument\n-------------\nhttps://github.com/bytedance/scene/wiki\n\nIssues\n-------------\n### Dialog\n\nA normal Dialog's Window is independent and in front of the Activity's Window,\nso if try to push a Scene in a opening Dialog, it will cause the Scene to appear behind it.\nYou can close the dialog box when click, or use transparent Scene to implement the dialog instead of a system Dialog.\n\n\nApps using Scene\n-------------\n| \u003cimg src=\"misc/douyin.png\" alt=\"xigua\" width=\"100\"/\u003e| \u003cimg src=\"misc/douyin.png\" alt=\"xigua\" width=\"100\"/\u003e | \u003cimg src=\"misc/xigua.png\" alt=\"douyin\" width=\"100\"/\u003e | \u003cimg src=\"misc/toutiao.png\" alt=\"toutiao\" width=\"100\"/\u003e | \u003cimg src=\"misc/kesong.webp\" alt=\"kesong\" width=\"100\"/\u003e |\n|:-----------:|:-------:|:-------:|:-------:|:------------------------------------------------------:|\n| TikTok | Douyin | Xigua Video |  Toutiao |  KeSong |\n\n\n## License\n~~~\nCopyright (c) 2019 ByteDance Inc\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n~~~","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbytedance%2Fscene","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbytedance%2Fscene","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbytedance%2Fscene/lists"}