Not able to pass values between screens using get start value and open/close screens

Hello guys, probably today is a bad day for me and also complete quickly simple things seems to be impossible.... I am trying to pass data between different screens. I am able to pass between Screen1 and Screen2 but if I modify the data inside Screen2 and then send back to Screen1 using "close screen with value result" the value read by get start value in Screen1 is always the same sent by Screen1.
I think I am doing something wrong but searching here and around the web I found solutions very close to mine, just little details are different. I uploaded the screenshots and the aia. The aia filename is that because m


y goal is to pass a dictionary between different screens but I started with a simple text variable as initial test.
TestPassDictionariesBetweenScreens.aia (4.5 KB)

Screenshot 2022-11-08 at 23-55-52 AI2

I found that if I change the "close screen with value result" with "open another screen with start value" it works. Did I use the close command wrongly? Or may be a bug? I tryed also returning constants instead of variables but close screen does not return the correct value or at least "get start value" does not read it as modified inside Screen2. Last but not least I suppose that if I use open screen to switch back to Screen1 both Screens are maintained in memory, instead after close screen only Screen1 is maintained in memory. So, if I suppose correctly, using close screen there are at most 2 screens in memory. Is my supposition right?

Why not use the tinydb to transfer values?

In my understanding TinyDB accesses flash memory, instead passing values between screens as lists and dictionaries uses ram memory. My idea is: I have a DB with some tables having the same fields but with different content and depending by an initial setup done every time the app starts, at the beginning the app have to select the right table to use. Then, to achieve maximum speed, I had the idea to copy the needed data from the DB table to something else. I already know that TinyDB works but I would like to see if managing the data with a dictionary requires less time.

this looks like you do not switch screens correctly... in your case probably you forgot to use the OtherScreenClosed event in Screen1... however while testing in the companion app you have to be careful, why? see the notes here App Inventor Tutorials and Examples: Manager Screen | Pura Vida Apps

Taifun

I see no dictionary blocks in your blocks images ?

I think I found the bug related to close screen. When a screen closes it triggers 2 actions in the Screen called it: Screen.Initialise and OtherScreenClosed. In Initialize get start value always returns the value passed to the called screen, the returned result from OtherScreenClosed contains the right value returned by the close screen. I do not know if this is the correct behaviour it has to have but it looks a little strange to me.

Yes, correct. In a previous post I wrote it is my goal to pass a dictionary between screens but I began with a simpler test using just a text variable.

you might want to read my previous answer and follow the link

Taifun

Well... I think there is a bug. If Screen1 opens Screen2 it does not close itself, it is still in memory, so when Screen2 closes itself Screen1 becomes active because it was the caller. But because it was not closed it is wrong that closing Screen2 Screen1.Initialize is executed before OtherScreenClosed. Screen1.Initialize in this condition should not be called and all the RAM variables should have the value they had before calling Screen2. It is obvious, logical and simple. Actually I found a workaround that in my case works. In most of my apps Screen1 is a splash screen and the place where I initialize "global variables" and DBs, then when finished it switches to a "main" screen. So, I have always 2 or 3 screens in memory. Taking care about what ScreenX.Initialize does in each screen the problem is solved because in this way the data to pass between screens is not rewritten each time the caller screen becomes active after the called screen closes itself.

I alway test in companion and the apk after each significative modification or deveopment step. In this case, apart "close application" everything else works having the same behaviour on both conditions.

At the beginning I saw that Screen1.Initialize was called every time Screen2 closed itself so I (wrongly) supposed that reading "get start value" inside it was right/sufficient. When I modified my original blocks testing and managing OtherScreenClosed I saw that it was called after .Initialize and that result contained the right value of the passed variable as modified inside Screen2. So, Screen1 is not the right place to initialize the "global" variable, it has to be initialized before, then I moved the logic to open other screens in a "main" screen and I left only the variable initialization inside Screen1. It is a workaround. I agree that every time a screen is opened the .Initialize function has to be executed but in my mind "open" a screen means it is not active or in memory neither. If it opened another screen it is not visible but because the screen it opened must return to it I think it is wrong to call the .Initialize function.

This solution works, it is a viable workaround for me and my current app.



This is a by-product of testing with the companion, I believe. Typically, the Initialize event of a screen is only called once when the screen is instantiated (if you open multiple screens of the same type, then you end up with multiple copies instantiated). However, when switching screens in the companion, this is emulated since screens in App Inventor for Android are actually Android activities and would need to be declared in the manifest. Instead, the companion provides a singular Screen1 which redraws its contents based on the active screen in the App Inventor editor. When this redraw happens, the Initialize function is called even if that particular screen had been previously initialized. If you compile the app, you shouldn't see this behavior--it's just due to the differences between emulating versus running your app.

I quickly tested the compiled app and seems you are right. I wrote "seems" only because I am tired and I could not see something, here time is about 02:00 AM, but I am confident you are right. Does exist some documentation somewhere about the differences between companion and compiled apps? Should be very useful. And do yuo know a better workaround then mine posted just before your post?

It is mentioned in the notes here App Inventor Tutorials and Examples: Manager Screen | Pura Vida Apps... as it looks like you have missed it, let me copy it here

Current limitations of the AI Companion app:

  1. The close screen block triggers the Initialize event instead of the OtherScreenClosed event.
  2. The close screen with value block triggers both the Initialize and OtherScreenClosed events instead of only the OtherScreenClosed event.
  3. The close application block does not work, a message 'Closing forms is not currently supported during development' will be displayed instead.

Taifun

1 Like

(refreshed in FAQ Usage Techniques section)

I known the 3rd but not the 1st and 2nd.

I think that this is probably something that should be fixed in App Inventor. It will complicate the code generation process a bit to make it work but it seems like it would address quite a few issues.

Well, it is a good news, I think that each difference removed between an app "built" to use companion and its apk it is a very good news. In my case it does not disturb so much now that I know how it works because more or less every app I made uses Screen1 as splash screen and until iti is active it initialise every "global" data, databases and so on and in this case Screen.Initialize is executed just one time. One thing I would like to have a confirmation is when Screen.Initialize is executed in a multiscreen application. To be more clear, suppose to have an app with Screen1...5, Screen5.initialize first time is executed when the app is starting, so after Screen1...4.initialize or the 1st time Screen5 is activated/visible? I am sure that it is executed when is opened but I remember I had an error on my DB some weeks ago and it produces an error retrieving data from a list (because it was empty for the DB error) and it was on Screen3 but running the apk the error happened opening the app (I mean the app installed by the apk) and took some time to find it because at the beginning I tested and verified only Screen1.