bytedance/scene

是否应该添加一个 SceneFragment

chachako opened this issue · 15 comments

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

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

qii commented

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

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

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

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

qii commented

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();
    }

@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

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

换成 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)

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

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

qii commented

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

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

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

qii commented

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

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

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

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

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

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 更加合适

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

这两个不可以同时进行吗,例如 MainScene 中我需要放置一个 ViewPager,就需要使用到 GroupScene, NavigationSceneCompatUtility.setupWithFragment 也可以接入 GroupScene 吗?

public static void setupWithViewPager(@NonNull final ViewPager viewPager,

qii commented

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

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

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

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

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

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

疑惑消失了,非常感谢