I have a Fragment, and once the user presses OK, an Item is added to my database and its ID is added to the ArrayAdapter. Immediately after, the adapter tries to draw the view, but the first time it tries to get its attributes, it returns a null HashMap (it gets drawn properly the following times).
Is there a way to make sure the item is in the table before trying to get its attributes?
Even putting the attribute retrieval into a while loop until it returns a not-null HashMap doesn't work so it doesn't look to be an issue of time.
You need to do Select or GetAttributes with ConsistentRead=true as Amazon SimpleDB supports two read consistency options: eventually consistent read and consistent read. Eventually consistent read is default. For more detail please refer doc. link
Try using AsynTask.
Add item to database in doInBackground.
Read it in postExecute.
You are done.
Related
Scenario
I am using onSnapshot() to listen to document changes in Firestore. My document contains an array field. I would like to see which items were added/deleted from the nested array in the document. Is there any way to achieve this?
Possible Solution
I see there is an oldDocuments() field in the QuerySnapshot.snapshot object which could be used to achieve my goal. I could just compare the oldDocument with the returned snapshot to see what changed in the nested array. The problem is oldDocument is a private field that I can't access through the API.
I am using Android Kotlin as my client.
There is nothing built in that can help you see what exactly in a document has changed. However, there are two workarounds.
The first one would be to attach a persistent listener and view changes between snapshots. That means that when you attach the listener you get a list of all documents your query returns. As soon as a document is changed, onEvent will fire. This means that you'll be able to know the document that has changed. Knowing that you already have a list with the initial documents, you can find the old document based on the ID and compare it against the new one.
Another solution would be to save a new document each time something changes. This is some kind of document versioning. In this way, you'll always be able to check the new document against the old one using only two document reads.
Suppose we would like to retrieve 15 random children from questions node having this database structured as below:
1. The first (intuitive and discussed) way of retrieving random children from Firebase is to retrieve the whole required parent node (questions as dataSnapshot) and then select some random children on the client-side. This method has been pointed out in many posts, like in this one here .
Obviously, this method has its downsides; for example when querying through a large sized parent node (e.g. over 10.000 children) retrieving such an amount every time would result in a huge bandwidth usage as well as a client side burden. (when we actually require only a small amount of children)
2. Moving on: another approach, as described here which uses an iterator somehow bypasses the whole client side burden, yet the huge bandwidth usage could still occur as we download the whole parent node every time.
3. An interesting approach is described in Tom's answer in this firebase discussion which proposes:
A hacky way of doing this would be to generate a random key and do a query with startAt().limit(1). I have a feeling this could hurt the performance of your firebase though, so this should not be an operation you perform often. We don't have a real random sample function.
This solution actually sounds pretty good, yet I am not sure how it would indeed impact my Firebase.
4. Another silly solution could actually be naming the question ids manually, so to speak, from 0 to N, therefore handling the random group of ids on the client side and retrieving the questions spot-on by knowing the actual name of nodes.
5. And lastly, I have come up with the following solution to which I ask if is more or less viable than the ones presented above: creating another parent containing the question ids only and when needed, one should retrieve this parent which is much "lighter" than questions parent . From there, I would have the specific random ids and I would only need to snipe for those children. To better understand my meaning, please check the below picture:
Now, from this method arises the following issue: is assigning (let's say) 15 eventListeners good practice? Could this actually slow up things? (Note: this applies to methods 3 and 4 as well)
And ultimately, which method is actually the optimal one when querying from a large database for some random children?
You can use the classic solution as I explained in this answer but if you are afraid of getting huge amount of data then use instead 15 listeners. There is nothing wrong in using listeners as long as you remove them according to the life-cycle of your activity. So, IMHO go ahead with 15 listeners.
We have 2 case here
case 1
If you want to grab all details of the random ids at once, then I suggest 1 listener to the parent node (get value of datasnapshot using pojo class).
case 2
If you want to get the details independently upon request then you will have to attach a listener to each (random id) that you want.
Concerning performance
Try to use only Listener For Single Value Events as they listen one time and then stop (better for performance).
Dont use Value Event Listener (because these listeners keep checking for changes and therefore bad performance as listeners increase).
EDIT
lets say you listened to (questions_ids) node, now you have access to the random id keys, store them in a String variable, and then inside the same listener add another listener to (questions) pointing to the id that you want to grab details
//first listen to question ids ref (the one with 15 ids)
question_ids_ref.addListenerForSingleValueEvent(...{
//grab the key of each (random id) and store in variable
String random_01=......;
//run another listener this time to questions ref
questions_ref.child(random_01).addListenerForSingleValueEvent(..{
//get details of random_01 and so on....
});
});
I need a little help with an issue in App Inventor 2. The case is that I have a JSON result that is parsed, and then have it stored in a tinyDB tag as a list (storeparseData).
Problem is that, I have this function done as screen initiates, so to have the tinyDB tag populated with that JSON list and then searched for a specific value on user request.
As the app is running and I input a search criteria, I get the following error "The arguments [empty-string] are the wrong number of arguments for GetValue". I suppose that, it finds nothing yet to be stored in the tinyDB tag to search for, cause the JSON data take some time to be fetched and parsed.
Here is what I have done for now for checking if the stored list is in the tinyDB:
Here I check the stored list in tinyDB for an item:
So how can I check if the tinyDB is populated in this tag with the JSON results list, so I can then have it searched? Is this possible in App Inventor 2?
Please someone advise on this issue with a sample code blocks if possible, or a similar tutorial, if there is any. Thank you all in advance for your answers.
This looks very strange... a complicated if then else structure, loads of empty sockets and your comparison if "storeparsedData" = <empty string> always will be false... obviously this does not make sense...
it looks like you are thinking too complicated?
what about this:
As already recommended in my answer to your other question you should learn how to work with lists...
how to work with lists
how to work with list of lists (pdf) by appinventor.org
see also An example of a complex List of Lists
Also doing some more tutorials might help to learn some more basics...
To answer your question "Can you explain why you've chosen to create an empty list there.": if you are working with lists as in the example and you are trying to read a list from TinyDB, then you also have to think about what should happen, if that tag is not available in TinyDB (for example after starting the app the first time). And for lists, in this case an empty list should be returned. Note: the is list empty? block always expects a list. If you set valueIfTagNotThere to an empty string, then you will get a runtime error...
You can use Clock function to delay the time. Firstly, just set the global DelayCountdown to specific number in "when Screen1.Initialize" part. Then, by using "when Clock1.Timer" function, you just need to add another check whether the DelayCountdown is equal to zero before you do another function.
I have elements in a listview that change the way they look based on a network response
by the time the network responds the listview item (or item in the arraylist) could be at a different index
What I can do:
Make an alternate api call back to the server which returns all the items in the list (in their most updated form), and then call notifyDataSetChanged() on the adapter
but this seems like a waste of processes, and so does some alternative of searching an arraylist for the equivalent object, updating it and then calling notifyDataSetChanged()
Is there a way instead to have something like a BroadcastReceiver within the adapter that can keep track of the adapter item which started the network call or service? any maybe only respond to the receiver if the view is not currently recycled
It's hard to give an exact answer as your best approach since what you described is a really high level overview. I'll have to give an equal high level answer. Hopefully it help.
There's not many ways around searching an ArrayList in the adapter for a given item. One good idea:
You could create a custom adapter which is backed by an ArrayList but also maintains a Set of the data as well. The benefit is finding an item is O(1) however any adds or removes require you to modify two collections instead of one...which will cause a slight slow down. I've personally had to use this solution once for a highly complex adapter/listview. It could get updated quite often (to the point throttling notifyDataSetChanged() was once discussed) Surprisingly the slow down in maintaining a List and Set was hardly noticeable and overall worked well.
You could use a similar approach if your data has some sort of unique id associated with it. In which case you could build a Map of the data and use the maps values() method to obtain the List to use for the adapter. While using the keys to quickly find and update the required data. This may or may not be more difficult then the Set idea. Further if you can get your data into a SparseArray (having a unique int for each item), then you could use a SparseArrayAdapter which can get you O(log n) search times. Of course you loose the ability to sort your data in any meaningful way.
I'm not sure how viable the BroadcastReceiver idea is. I would see it more like each item's object instance would control the network request/response for itself, but that would seem tricky and odd. There's always the option of using a CursorAdapter. Just store all your data to DB. Have the network calls update the DB which can then be reflected within the CursorAdapter.
The endless adapter that I've used in my code, doesn't stop expecting data even if I am out of it. Thus the throbbing symbol, which is the loading symbol here, keeps on circling expecting some data.
How do I stop it? How do I make the endless adapter know that I'm out of data?
Also, I would like to tweak the adapter so that it can use multiple lists. Is it possible? By multiple lists, I mean list embedded inside another list. If yes, is there an example or any ideas as to how to do it?
How do I make the endless adapter know that I'm out of data?
Quoting the documentation:
Your EndlessAdapter subclass also needs to implement cacheInBackground(). This method will be called from a background thread, and it needs to download more data that will eventually be added to the ListAdapter you used in the constructor. While the demo application simply sleeps for 10 seconds, a real application might make a Web service call or otherwise load in more data.
This method returns a boolean, which needs to be true if there is more data yet to be fetched, false otherwise.
Since this method is called on a background thread, you do not need to fork your own thread. However, at the same time, do not try to update the UI directly.
If you expected to be able to retrieve data, but failed (e.g., network error), that is fine. However, you should then return false, indicating that you have no more data.
Also, I would like to tweak the adapter so that it can use multiple lists. Is it possible? By multiple lists, I mean list embedded inside another list.
No. Android does not support the notion of lists inside of lists. You are welcome to take a look at my MergeAdapter (if you really mean that you wish to concatenate multiple lists together) or Android's ExpandableListView (if your lists-in-lists is really some sort of shallow tree structure).
It is possible to use different data for your own Adapter this data can be of any type such as
ArrayList<HashMap/HashSet<?,List<?>>> it is your own business how you will use it within your getView(...) method. You can implement a poller service which will update your Adapter with data accordingly and setAdapter() after. If there's no data just idle...
hope this helps abit.