bytedance / scene

Android Single Activity Framework compatible with Fragment.
Apache License 2.0
2.08k stars 198 forks source link

是否应该添加一个 SceneFragment #31

Closed chachako closed 4 years ago

chachako commented 4 years ago

一些特殊情况需要在已有 Fragment 中添加 Scene,我应该怎么做?使用 setupWithFragment 注册后怎么解决返回多层 Scene 问题?

所以有没有像 SceneActivity 一样的封装好的 Fragment 基类供使用

qii commented 4 years ago

【返回多层 Scene 问题】具体是啥,没理解,你是想在 Fragment 里面用 Scene,又想要支持导航操作,用返回键回退到上个 Scene 吗?

chachako commented 4 years ago

【返回多层 Scene 问题】具体是啥,没理解,你是想在 Fragment 里面用 Scene,又想要支持导航操作,用返回键回退到上个 Scene 吗?

Activity Fragment -- RootScene ---- Scene ---- Scene

然后所有子 Scene 不都应该可以返回上一级吗,但是我尝试了注册在 Fragment 后,不管是在哪个 Scene 中点击返回键都会直接返回桌面

qii commented 4 years ago

SceneActivity 能做到让里面的 Scene 返回到上一层,是因为拦截了 onBackPressed,Fragment 本身没有这样的方法,你只能通过 override Activity 的 onBackPressed,转发给你的 Fragment 写个类似 onBackPressed。Fragment 的 onBackPressed 里面则是使用 NavigationSceneCompatUtility。setupWithFragment 返回的 SceneDelegate

Activity 代码

@Override
    public void onBackPressed() {
        if (!this.mFragment.onBackPressed()) {
            super.onBackPressed();
        }
    }

Fragment 代码

public boolean onBackPressed() {
       return this.mDelegate.onBackPressed();
    }
chachako commented 4 years ago

@qii 尝试在已有的项目 Fragment 接入 Scene 时:

java.lang.IllegalStateException: Scene NavigationScene{7ef0004} is root Scene, not a child Scene
    at com.bytedance.scene.Scene.getParentScene(Scene.java:771)
    at com.bytedance.scene.Scene.dispatchOnSceneCreated(Scene.java:1061)
    at com.bytedance.scene.navigation.NavigationScene.dispatchOnSceneCreated(NavigationScene.java:801)
    at com.bytedance.scene.Scene.dispatchCreate(Scene.java:307)
    at com.bytedance.scene.SceneLifecycleManager.onActivityCreated(SceneLifecycleManager.java:84)
    at com.bytedance.scene.SceneLifecycleDispatcher.onActivityCreated(SceneLifecycleDispatcher.java:70)
    at com.bytedance.scene.ui.LifeCycleCompatFragment.onActivityCreated(LifeCycleCompatFragment.java:56)
qii commented 4 years ago

你这个是啥版本,能换 1.0.3 试试吗?

chachako commented 4 years ago

换成 1.0.3 Release 后上面的错误消失了,但是出现了新的问题:

java.lang.IllegalStateException: Can't retain fragements that are nested in other fragments
    at android.support.v4.app.Fragment.setRetainInstance(P:782)
    at com.bytedance.scene.ui.ScopeHolderCompatFragment.onCreate(ScopeHolderCompatFragment.java:39)

当我将这一行代码注释掉后,结果可以正常运行

https://github.com/bytedance/scene/blob/f86de971e870638a7836537d187fe8ebeb30c691/library/scene_ui/src/main/java/com/bytedance/scene/ui/ScopeHolderCompatFragment.java#L38

这种情况该如何解决呢(项目的 Support V4 版本有点老)

qii commented 4 years ago

或者你复制代码,自己写一份 NavigationSceneCompatUtility.setupWithFragment,里面用你自己的 ScopeHolderCompatFragment.java (去掉 setRetainInstance(true),代价是屏幕旋转的话,ViewModel 也没了,不过你的 support 版本这么低,应该 ViewModel 也没吧

chachako commented 4 years ago

或者你复制代码,自己写一份 NavigationSceneCompatUtility.setupWithFragment,里面用你自己的 ScopeHolderCompatFragment.java (去掉 setRetainInstance(true),代价是屏幕旋转的话,ViewModel 也没了,不过你的 support 版本这么低,应该 ViewModel 也没吧

项目没有用 ViewModel 就应该没有影响吧

qii commented 4 years ago

或者你复制代码,自己写一份 NavigationSceneCompatUtility.setupWithFragment,里面用你自己的 ScopeHolderCompatFragment.java (去掉 setRetainInstance(true),代价是屏幕旋转的话,ViewModel 也没了,不过你的 support 版本这么低,应该 ViewModel 也没吧

项目没有用 ViewModel 就应该没有影响吧

应该没,因为 ScopeHolderCompatFragment 这个东西的用处就是让一些数据在屏幕旋转(开启 Activity 销毁重新创建)的时候能够继续存活

chachako commented 4 years ago

另外,FragmentTransaction 中也不存在 commitNowAllowingStateLoss 这个方法,只有 commitcommitAllowingStateLoss

chachako commented 4 years ago

SceneActivity 能做到让里面的 Scene 返回到上一层,是因为拦截了 onBackPressed,Fragment 本身没有这样的方法,你只能通过 override Activity 的 onBackPressed,转发给你的 Fragment 写个类似 onBackPressed。Fragment 的 onBackPressed 里面则是使用 NavigationSceneCompatUtility。setupWithFragment 返回的 SceneDelegate

Activity 代码

...

Fragment 代码

public boolean onBackPressed() {
       return this.mDelegate.onBackPressed();
    }

当 mDelegate 是 SceneDelegate 时才有 onBackPressed 这个方法,但是如果我是使用的 GroupSceneCompatUtility.setupWithFragment -> GroupSceneDelegate 将怎么判断

qii commented 4 years ago

SceneActivity 能做到让里面的 Scene 返回到上一层,是因为拦截了 onBackPressed,Fragment 本身没有这样的方法,你只能通过 override Activity 的 onBackPressed,转发给你的 Fragment 写个类似 onBackPressed。Fragment 的 onBackPressed 里面则是使用 NavigationSceneCompatUtility。setupWithFragment 返回的 SceneDelegate Activity 代码

...

Fragment 代码

public boolean onBackPressed() {
       return this.mDelegate.onBackPressed();
    }

当 mDelegate 是 SceneDelegate 时才有 onBackPressed 这个方法,但是如果我是使用的 GroupSceneCompatUtility.setupWithFragment -> GroupSceneDelegate 将怎么判断

GroupSceneCompatUtility 和 NavigationSceneCompatUtility 的区别在于,根是 GroupScene(支持UI 组合) 还是 NavigationScene(支持导航栈,返回),我看你这里说的,你的需求就是导航,那么就应该用 NavigationSceneCompatUtility 更加合适

chachako commented 4 years ago

GroupSceneCompatUtility 和 NavigationSceneCompatUtility 的区别在于,根是 GroupScene(支持UI 组合) 和 NavigationScene(支持导航栈,返回),我看你这里说的,你的需求就是导航,那么就应该用 NavigationSceneCompatUtility 更加合适

这两个不可以同时进行吗,例如 MainScene 中我需要放置一个 ViewPager,就需要使用到 GroupScene, NavigationSceneCompatUtility.setupWithFragment 也可以接入 GroupScene 吗? https://github.com/bytedance/scene/blob/36a4626f4a319faafb6bf4d1a6dcd381871abb12/library/scene_ui/src/main/java/com/bytedance/scene/ui/GroupSceneUIUtility.java#L177

qii commented 4 years ago

NavigationScene 和 GroupScene 是可以互相嵌套的,然后 GroupSceneUIUtility 跟 GroupSceneCompatUtility/NavigationSceneCompatUtility 都不一样,只是把 ViewPager 这类跟 GroupScene 绑定。

比如你说的这个内嵌 ViewPager 的事情,看你的意思,应该是在 Fragment 里面做,自然用 NavigationSceneCompatUtility. setupWithFragment(your_fragment, MainScene.class, R.id.your_container_id) 这样

这里的 MainScene,应该是 继承的 GroupScene

chachako commented 4 years ago

NavigationScene 和 GroupScene 是可以互相嵌套的,然后 GroupSceneUIUtility 跟 GroupSceneCompatUtility/NavigationSceneCompatUtility 都不一样,只是把 ViewPager 这类跟 GroupScene 绑定。

比如你说的这个内嵌 ViewPager 的事情,看你的意思,应该是在 Fragment 里面做,自然用 NavigationSceneCompatUtility. setupWithFragment(your_fragment, MainScene.class, R.id.your_container_id) 这样

这里的 MainScene,应该是 继承的 GroupScene

疑惑消失了,非常感谢