Web1 JsonTextDecodeWithDictionaries Runtime Error java.lang.String cannot be cast to com.google.appinventor.components.runtime.util.YailDictionary

Hello,

I'm trying to make my application multilingual using the Web1 JsonTextDecodeWithDictionaries block.
The three blocks attached show my solution, which is not good. I get the following error message on my phone when I start my application for the second time: Runtime Error java.lang.String cannot be cast to com.google.appinventor.components.runtime.util.YailDictionary End Application .

When I start my application for the first time, there is no error message, but the component texts are displayed with the caption "not found".

I am also attaching my JSON dictionary, which contains three languages ​​so far.
Szotaram.json (51.8 KB)

The blocks:



How can I solve this problem so that this error message does not appear?
However, I also ask that since I assume that reading the Dictionary JSON file into the application with the Web1 block takes time (especially if there will be more languages ​​in the dictionary), how can I give more time for my Dictionary to be usable in my application?

I appreciate all advice!

In Screen Initialize, disable Clock1.
Do that in the Designer too.

You don't want it firing when that global variable with the dictionary is empty.

Pull in a File Error event for good measure, in case you misspelled the file name.

Look in the screen1 blocks for file names helper blocks, stuck to other blocks. Take any of them, and use its selector to point it to your JSON file.

You can also typeblock media file names in the blocks editor.

That clock1 timer code should just be a procedure you would call after receiving the JSON.

Why do you need to wait?

The web1 JSON decode block does not go out to the Web.

It's instantaneous.

It was just a handy component to hold the JSON conversion library.

I personally would have moved it to the built-in blocks pallet, under dictionaries.

1 Like

I have corrected the commands in my application according to your advice. I hope I understood your advice correctly. I am attaching the three questionable blocks.



Perhaps because I don't know the correct value of the file path (string), my application can't find my Szotaram.json dictionary in the File1.Exist block of the Screen1.Initialize section. First, I gave the following value for the file path in a text block: '//' without quotes. Then I deleted it. When this didn't work either, only the following error message "File not found", I inserted the block containing the file name from the Screen1 section in place of the file path. Even then, the part that checks whether the Szotaram.json file exists cannot find my Szotaram.json dictionary. But this only happens the first time I run my application.
When I run my application for the second time, the original error message "Runtime Error ..." appears again, and the values ​​(texts) of some keys of one of the languages ​​from my dictionary are displayed.
Where am I wrong?

(Canned Reply: ABG- Export & Upload .aia)
Export your .aia file and upload it here.
export_and_upload_aia

Proportion_Solver.aia (294.8 KB)

I took a look in your json file.

It maps phrases into other target languages, in a nested targetLanguage/phrase/translaton.

Nice.

proceeding into your code ...

I found your File component:
image

The default scope attribute can be set to point to the assets folder, if all you do with this component is load json files.

That would avoid having to include the // file name prefix for the MyDict load.

I am reading Clock1.Timer and Screen1.Initialize.

They need to be divorced from each other.

Beside mucking around with MDict, is there any other branch of Clock1.Timer that needs to run at startup?

1 Like

It is ironic that your app teaches math functions, but you never use a value function in your app, and never parametrize.

I went looking for where valasztott_nyelv (the current language code) is set in your code, and found a couple of hundred tests of it.

That should have been hidden under layers of value function calls.

I am finding your use of global variables for signalling too complex for me, like a game of Jenga.

I recommend splitting up Clock1.Timer into a few separate well named Clock components with their own simpler single functions. Swiss Army knives are awful.

1 Like

In Screen1.Initialize,

The FirstTime TinyDB tag/value is superfluous.

You could have asked for the TinyDB value at tag 'MyDict', with default an empty dictionary.

Drop it into global MyDict regardless, then test global MyDict against the value Empty Dictionary.

It is always simpler to lose global variables and flags, if you you can get your status information directly. Fewer wires to cross.

The code you want to execute in Screen1.Initialize after you are sure global variable MyDict has been loaded should be moved into a separate procedure, call it Initialize_Phase_2.

You would choose to call it from after you verified that global MyDict is ready, either early in Screen1.Initialize after MyDict came back full from TinyDB, or in the File1.GotText event, after you used the JSON data to load up TinyDB and the MyDict global variable.

I regret your code is too fragile for me to do that for you. I might break something amidst its nest of swords.

1 Like

I went looking for old examples of applying translation techniques to lists of components.

Here's one of them.

1 Like

No, there is no other branch of Clock1.Timer that needs to run at startup.

Please explain this to me in more detail so I can understand.

I did. Indeed, it's much simpler and clearer this way. By the way, I somehow didn't think that the Clock1 element could be renamed.

http://www.appinventor.org/book2

Please read chapter 21 to the end

1 Like

How can I make sure that the MyDict global variable is loaded?
I am attaching pictures of the blocks involved:


when_Screen1_Initialize_do__part_Get_MyDict_somehow
Until I know how to make sure that the MyDict global variable is loaded, I will not put the Initialize_Phase_2 part, which would be responsible for displaying the text values ​​of the user interface elements, into a separate procedure.

I am trying this APK file on my phone.
Before installing the next copy after modifying the code, I delete my application data and the application itself (Proportion Solver) from my phone.
The video below shows that the error message appears when I run my application for the first time after installation, but when I run my application for the second time, my application works almost fine.
The video of my application.

Where am I wrong?

Or something like this:

no need to change filescope

2 Likes

Is there a
Is Dictionary empty
block?

No, but empty list block on a dictionary seems to work OK

Now the error message mentioned in the title does not appear when I first run my application, however the text translations of the UI elements are not yet displayed, although a pop-up message indicates that the json file was loaded successfully.
Again, the element texts only appear when I run my application for the second time.
I am attaching a link to the video of the first and second run.
Application's first run.
Application's second run.