Roku应用ObserveField visible在屏幕显示时未触发问题排查
Roku应用开发问题:TopicScreen的onVisibleChange不触发及内容填充失败
问题描述
我正在使用BrightScript和SceneGraph开发一款Roku应用,应用内有一个PosterGrid供用户选择海报。用户选择海报后会调用ShowTopicScreen子过程加载TopicScreen组件,但当前遇到以下问题:
onVisibleChange子过程仅在按下返回键回到首屏时触发,屏幕显示时从未执行- 无法填充
titleLabel内容,但TopicScreen已正常加载(可看到静态标签“A test label”)
相关代码如下:
ShowTopicScreen.brs
sub ShowTopicScreen(topic as Object) topicScreen = CreateObject("roSGNode", "TopicScreen") topicScreen.content = topic topicScreen.ObserveField("visible", "OnDetailsScreenVisibilityChanged") ShowScreen(topicScreen) end sub sub OnTopicScreenVisibilityChanged(event as Object) visible = event.GetData() currentScreen = GetCurrentScreen() screenType = currentScreen.SubType() if visible = false if screenType = "HomeScreen" currentScreen.jumpToItem = m.selectedTopicIndex end if end if end sub
TopicScreen.xml
<?xml version="1.0" encoding="UTF-8"?> <component name="TopicScreen" extends="Group" initialFocus="topicList"> <script type="text/brightscript" uri="TopicScreen.brs" /> <interface> <!-- Specifies the content for the Grid --> <field id="content" type="assocarray" /> <field id="topiccontent" type="node" alias="topicList.content" /> <field id="rowItemSelected" type="intarray" alwaysnotify="true" alias="topicList.rowItemSelected" /> <field id="jumpToRowItem" type="intarray" alias="topicList.jumpToRowItem" /> </interface> <children> <Label id="titleLabel" width="1020" translation="[105,170]" /> <Label id="textLabel" width="1020" translation="[105,190]" text="A test label" /> <RowList itemComponentName="TopicRowListItemComponent" id="topicList" translation="[105,240]" numRows="2" rowitemSize="[[320,180]]" rowItemSpacing="[[20,0]]" itemSize="[1100,270]" rowLabelOffset="[[50,20]]" focusXOffset="[50]" showRowLabel="[true]" rowFocusAnimationStyle="floatingfocus" /> </children> </component>
TopicScreen.brs
sub Init() m.top.observeField("visible", "onVisibleChange") m.titleLabel = m.top.FindNode("titleLabel") end sub sub onVisibleChange() 'this only runs when I leave the screen if m.top.visible = true SetContent() end if end sub sub SetContent() m.titleLabel = m.top.topic.title end sub
原因与解决方案
问题原因
visible字段观测逻辑问题:SceneGraph组件的visible字段默认值为true,当调用ShowScreen加载组件时,visible字段没有发生值的变更(从false到true),因此不会触发观测事件。只有当visible状态发生切换时(比如返回首屏时从true变为false),才会触发onVisibleChange。SetContent函数错误:代码中m.titleLabel = m.top.topic.title存在两个问题:- 错误地将标签节点本身赋值为字符串,应该设置标签的
text属性 - 接口定义的字段是
content,不是topic,应该访问m.top.content.title
- 错误地将标签节点本身赋值为字符串,应该设置标签的
解决方案
推荐采用观测content字段变更的方式来触发内容填充,因为这更贴合数据驱动的逻辑,当外部传入content时自动更新UI。
修正后的TopicScreen.brs
sub Init() ' 改为观测content字段,当外部赋值时触发更新 m.top.observeField("content", "onContentChanged") m.titleLabel = m.top.FindNode("titleLabel") end sub sub onContentChanged() ' 确保content有效时才执行填充 if m.top.content <> invalid then SetContent() end if end sub sub SetContent() ' 修正为设置label的text属性,且访问正确的content字段 m.titleLabel.text = m.top.content.title end sub
额外修正:ShowTopicScreen中的事件名错误
原代码中观测visible时指定的回调函数名是OnDetailsScreenVisibilityChanged,但实际定义的是OnTopicScreenVisibilityChanged,会导致返回首屏时的逻辑无法执行,需要修正为:
topicScreen.ObserveField("visible", "OnTopicScreenVisibilityChanged")
备选方案:主动调用填充函数
如果坚持使用visible观测,也可以在创建TopicScreen并设置content后,主动调用SetContent:
sub ShowTopicScreen(topic as Object) topicScreen = CreateObject("roSGNode", "TopicScreen") topicScreen.content = topic topicScreen.callFunc("SetContent") ' 主动触发内容填充 topicScreen.ObserveField("visible", "OnTopicScreenVisibilityChanged") ShowScreen(topicScreen) end sub
内容的提问来源于stack exchange,提问作者cesarcarlos
相关产品推荐
相关产品推荐

