I'm currently building an android application with quite a few different connected activities. In each activity I've got a private updateView() method to update all the textViews and stuff on that screen. This gets called in the onResume() method so that each time the activity comes to the front it's views will be updated.
Is this the right way to do things or is there a more standard pattern for keeping your views in sync with the data?
I think that you are doing this correctly. onResume would be the perfect time to update your views, I assume you are only updating if there is actually new data to be displayed?
If retrieving the data during the updateView method takes a long time then you should do it in an AsyncTask to avoid clogging the UI Thread which will make your app hang.
In fact any data retrieval like getting data from the web or reading from your apps database should be done in an AsyncTask. This is because even if your data retrieval seems to take milliseconds on your device it may conceivably take longer on another, less powerful device.
Related
I'm trying to determine whether or not I download data in my android application. I can do this by making the method return true when it does download data, but the listener doesn't seem to be invoked until all other code is finished running (meaning it waits until a pause in your code). So I'm wondering if there is a way to sort of "forcibly" invoke these listeners? Perhaps by creating the listener in a different thread? Would this work or would it be a waste of time? I've already tried to sleep on the main thread for a few seconds, but that doesn't seem to do it either. If it wouldn't work, could you explain when exactly these listeners are invoked? Thanks in advance.
To add onto my question, I am NOT using the realtime database. I understand how realtime triggers work, but I am using the Firestore, so I am only getting data once, not getting realtime updates :)
As you have already noticed with the API calls that deal with reading and writing data are fully asynchronous. This means that the call always returns immediately, without blocking the code to wait for a result. The results come some time later, whenever they’re ready, since it may take some time for this. Depending on your connection speed and the state, it may take from a few hundred milliseconds to a few seconds before that data is available. So Firebase, already is using another thread (other than the main thread) to get the work done.
Calling a synchronous function on your app’s main thread could freeze the app indefinitely, which is a terrible UX. On Android, it could also soft-crash with an Application Not Responding (ANR) dialog.
Doug Stevenson, has explained in his post everything that you need to know about Fireabse asynchronous behaviour and what you need to do/avoid when dealing with Firebase.
I have a task object that I would like to track time spent on. I am running a timer counting up for a variable in the task, but whenever I go to update the task inside the database it seems like it somehow gets set back to null even after I confirm that it updates. I was thinking that maybe I am not understanding the database class completely, and making the context that I am calling the database on somehow affects the data inside. Is there any reason that my data is being set to null?
Okay, so I figured this out. The problem was that I was creating multiple instances of the database in one activity. Also, I was using a service that was meant to share data across activities that both affect the data within the database in specific ways. When I passed between these activities, the application was essentially swapping between different instances of the same database, and therefore never really saved the data correctly and led to some weird behavior.
The moral of the story is that you should create one global database for your activity, and try to share the same database between two activities attempting to manipulate the same data.
Firstly I have investigated other StaleDataExceptions on SO but none really answer, or lead me to a solution to my current App design problem.
I'm creating a Music Player App, which I initially designed to query the MediaStore.Audio with a CursorLoader to retrieve information from the Content Provider - this works fine, however obviously if you have a big music library there could be a more than desirable wait time getting all the information back when the app loads each time. My second approach was to start a remote Service on app first launch, which queries the MediaStore.Audio using a CursorLoader and registers for any updates. When the Cusror is returned I then run an AsyncTask to process the information into an ArrayList of Custom POJO class that implements the Parcelable Interface which then gets marshalled/demarshalled via an Intent back to a handler in the Music App. This solution works well because if the app is closed, and reopened it just queries the Service for the latest ArrayList of custom Objects, rather than having to query the MediaStore.Audio at all - the Service implements LoaderCallback<Cursor> and always updates ArrayList of custom Objects and notifies the App if open, if not it has them ready for when the app is reopened.
Right - to the problem (ok took a bit of time, but necessary background information). The issue is : If I'm in another media app and start deleting music files in quick succession the registered Listener in my service is calledback and a new cursor is delivered, however the AsyncTask I am using to iterate over the existing cursor has a Race Condition where it is closed by another Thread / CursorLoader as the Cursor is updated - exception thrown : android.database.StaleDataException: Attempted to access a cursor after it has been closed.
The current workaround I'm using is use setUpdateThrottle to 20 seconds when registering the listener, this works, however means there is a delay in getting updated information back to the Service.
Is there any viable solution or approach where I can avoid this problem?
Thanks in advance.
UPDATE
A working viable solution, was actually quite easy to achieve - it initial problem however does illustrate my lack of experience with Loaders, however I've gained some knowledge on the way to finding a solution.
Solution:
I am still using a remote Service. However instead of using a CursorLoader - which was closing the cursor whilst I was still processing it in the onLoadComplete() callback, I am using a AsyncTaskLoader. The AsyncTaskLoader coupled with a ContentObserver can still monitor for underlying data changes from a Uri but is not directly coupled with the Cursor object like a CursorLoader. I am able to monitor for data changes and let the AsyncTaskLoader know it needs to reload data (forceLoad()), however this is queued, and doesn't affect the processing of loadInBackground() method - Once this returns, it simply cancels the task and starts the new task.
I have an Activity that displays a text based on data pulled from MySQL server. The problem is that the Activity won't load until data is pulled, which sometimes takes some long seconds or even doesn't load at all, and in the meantime the users gets a black screen.
I tried to pass the mission of getting the data from the server to a service, but also it waits for pulling the data and only then shows the layout of the Activity.
I also tried to make an activity with fixed text and then call the Activity that pulls the data from the server, but still the program wait for the data.
Can you think on a creative solution for it? or maybe a non-creative one as well :)
you can use asynctask for this:
http://developer.android.com/reference/android/os/AsyncTask.html
or you can show a waiting dialog to user until you get your data(do it in separate thread).....
or you can implement a splash screen and there you can fetch data.....
You need to do it inside another thread. Try using AsyncTask class.
The delay is probably due to the call to fetch the data being done on the main thread, also called the UI thread. Processes which take any significant amount of time, and by that I mean even a second or two should be done in a seperate thread. Android provides a class called AsyncTask to help make threading painless.
You mention you tried a service but did you take a look at an IntentService? (Can't link it yet but it's on d.android.com.) I like using them for these kind of tasks cause they handle the threading for you (like an AsyncTask) and it separates concerns better. The IntentService then sends a broadcast message that the activity picks up indicating that the data is available or not. Store the data locally in a sqlite db or as a json/xml file.
The first time the app is run, I want to have a checkbox list appear where the user selects the list items that they are interested in, and run the program based on that. Every subsequent time the app is run, I want those selected settings to be remembered, or changed with an options menu, in which case the new settings will be remembered. But all I know how to do is make an app go from the beginning every time it is run...
Similarly, my app reads sequentially through all the data in a large, read-only, unchangable database. As of right now, it creates and opens and fetches all the data every time, which takes a few seconds at the start of the program to open up and do anything. Is there a way to get around this, or, is it even a good idea to try to get around this?
To remember the users selection, have a look at SharedPreferences. You can store the selected items there.
To the database: That really depends on your app. If you need all that data at the same time in memory, I guess theres no way around loading it at the start. If you only need parts, it would be a good idea to load a part of the data when required. But without exact knowledge of your app/use case, this is hard to tell.
When you have some sort of "lag" when loading the database: Do you probably load the database in the UI-thread (= without creating a seperate thread for loading)? Thats bad practice since it blocks all UI operations. Have a look at AsyncTasks. Thats a handy class that wraps around a thread and lets you do things in the background without blocking all the UI. After it's done with its task (loading in this case) it provides you a onPostExecute() callback where you can update your UI with the loaded data.