Roku Developer Program

Developers and content creators—a complete solution for growing an audience directly.
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
destruk
Level 10

ObserveField

If you have m.routine=m.top.findnode("routinename")
and you set m.routine.observefield("fieldname","callbackfunction")
- each time you execute the routine.observefield line it will add another callback every time the field changes.
This makes it really easy to string a bunch of small routines together to act on the change, however, it isn't smart enough to check the callback function name to see if it's the same as one already in the observefield callback queue.  So it can end up calling the same function multiple times on subsequent calls. (for what it is worth)
So be sure to set unobservefield when the callback fires to prevent this.  I ran into this issue observing the "content" field of a urltransfer request.  Each time it ran, it added another callback because I didn't unobserve the field.
0 Kudos
6 Replies
destruk
Level 10

Re: ObserveField

Another note -- the task thread is about 10 times slower than any other thread.  So if you're downloading xml or json data to parse, use the task thread to do the things you require it to do - like use rourltransfer since that's the only way to do it within Scenegraph, and then as quickly as possible toss the result back to the calling thread to parse and process it.  Speed is immensely improved doing this than having the task thread do the parsing and manipulation of what it received.  When you have the data and have no need for the content field, be sure to unobserve the field, and then set the content field to "" or invalid so it is cleared for the next time you need it.  AlwaysNotify for the content field of a task thread didn't appear to work for me - it always appears to be set to False somehow for task threads, ignoring callbacks for observers if the content is the same as it was prior.

<?xml version="1.0" encoding="utf-8" ?>
<!--********** Copyright 2015 Roku Corp.  All Rights Reserved. **********-->

<component name="taskdownloaddata" extends="Task">
<interface>
<field id="uri" type="uri" />
<field id="content" type="string" />
</interface>
<script type="text/brightscript">
<![CDATA[
Sub init()
m.top.FunctionName="getNewData"
End Sub

Sub getNewData()
readInternet=createObject("roUrlTransfer")
readInternet.setUrl(m.top.uri)
temp=readInternet.GetToString()
m.top.content=temp
End Sub
]]>
</script>
</component>

0 Kudos
EnTerr
Level 8

Re: ObserveField

Try this idea to distinguish between calls https://forums.roku.com/viewtopic.php?f=34&t=98722
Seems like a little bit of abstraction may help you.
0 Kudos
destruk
Level 10

Re: ObserveField

Thanks Enterr.  I suppose the point is - if you're using a task node, only run one of each type at a time if you require a callback for it or if it needs to complete in a specific order.
BTW the wiki docs might fully outline what I described in this thread as the proper way to avoid problems, but there is a lot of information to read in the wiki so I didn't see it before.
0 Kudos
Roku Employee
Roku Employee

Re: ObserveField

"destruk" wrote:
Thanks Enterr.  I suppose the point is - if you're using a task node, only run one of each type at a time if you require a callback for it or if it needs to complete in a specific order.

I believe you can run multiple instances of the same Task-extending component - but for the event handlers to distinguish which does what, should set some field(s) inside, e.g. to let it know which URLs it's working on now or such. Re-using the same Task instance seems risky if the previous execution has not finished yet.
0 Kudos
btpoole
Level 7

Re: ObserveField

"destruk" wrote:
Another note -- the task thread is about 10 times slower than any other thread.  So if you're downloading xml or json data to parse, use the task thread to do the things you require it to do - like use rourltransfer since that's the only way to do it within Scenegraph, and then as quickly as possible toss the result back to the calling thread to parse and process it.  Speed is immensely improved doing this than having the task thread do the parsing and manipulation of what it received.  When you have the data and have no need for the content field, be sure to unobserve the field, and then set the content field to "" or invalid so it is cleared for the next time you need it.  AlwaysNotify for the content field of a task thread didn't appear to work for me - it always appears to be set to False somehow for task threads, ignoring callbacks for observers if the content is the same as it was prior.

<?xml version="1.0" encoding="utf-8" ?>
<!--********** Copyright 2015 Roku Corp.  All Rights Reserved. **********-->

<component name="taskdownloaddata" extends="Task">
<interface>
<field id="uri" type="uri" />
<field id="content" type="string" />
</interface>
<script type="text/brightscript">
<![CDATA[
Sub init()
m.top.FunctionName="getNewData"
End Sub

Sub getNewData()
readInternet=createObject("roUrlTransfer")
readInternet.setUrl(m.top.uri)
temp=readInternet.GetToString()
m.top.content=temp
End Sub
]]>
</script>
</component>



I have noticed the slowness of the task also. So as you stated after the urltransfer was complete, i went back into the brs for parsing as I had always done before 7.6 hit my box. The parse will not run in the brs as it once did. It times out. So to stop the execution timeout I dropped the parse to a task. Big mistake. Absolutely takes forever but I see no other choice except maybe cut down size of data being pulled at one time, unless there is another way.
0 Kudos
destruk
Level 10

Re: ObserveField

btpoole - perhaps the parse allow/disallow depends on the thread?  What I've been doing here is when the channel starts - the first file it executes, basically the first thing it does is download the content xml, parse it, and put it into an RoSGNode ContentNode.  After that it creates the roSGScreen and sets the scene content to the contentnode.  It's real quick.  If you do that, be sure to remove the 'splash_min_time' from the manifest or set it to 0, as the splash screen will still be shown for the few (approximately 6 seconds for 550 items) seconds before the main content screen appears.
Once the channel is up and going, I think I want to minimize any internet content that will need to be parsed as much as possible - as it can take 2-4 seconds simply to load and parse further content from the internet.  And I don't know what I'll need to do to deal with the 6+ second delay making a single sale through the roku billing system - it really needs to be faster than that is. Smiley Sad
0 Kudos