I have a weird problem. As I have asked in previous posts, I have a lot of data coming from NET in my app. The problem is that a lot of text and images r there, so though I can make the user wait wen he clicks on a list item, but I don't want to make him wait wen he clicks the back button.
In the sense that I don't want to re-download all data; data 1ce downloaded should remain.
Which 1 is the right method?
1. Using a special class which stores all data... and using the variables each time I go back,
or
2. Is there any specific save instance method for saving such data in the class
itself... if it is then do inform me how to call the saved instance Activity
when back is clicked.
By "user clicks the back button" I understand that the previous activity is displayed and returned at the top of the stack (see activity lifecycle).
This mean this activity is not created again, but resumed (unless it was killed by core because other applications need memory), so its fields and attributes keep their values.
So if you store your datas in some activity fields, you might be able to retrieve their values and display them without re-download them.
Of course you have to test these fields before accessing them in order to avoid NPE in case of activity first start.
You shouldn't rely on any Activity already existing when you start it or return to it.
Check out this previous question about caching already-downloaded data:
What is the ideal place to cache images?
You shouldn't have any pauses in the UI anyway when the user enters an Activity; you should be doing all the downloading on a background thread and showing some sort of progress indicator to the user. If you don't do this and the UI thread is blocked by a slow download (about 15 seconds), the user will be presented with an "Application Not Responding" dialog and asked to either kill your application or keep waiting. Not good.
Related
The title isn't good, please read bellow to understand better my problem
I have an Android application, one of its tasks is time consuming and will often take between 2-5 minutes to be finished... this task is done by a background service which has a reference to the starter activity.
99% of users doesn't want to wait all this time looking to a loading bar and will simple open another app or something like... what might lead to android destroying the referenced activity...
Ignoring the context leak of this story... my problem is:
When the service finishes its task it will try to call a method to return the values to the parent activity, but as it was destroyed now I can't do it...
So when user re-opens the app the last known state by that activity is "loading" so it keeps loading forever... (or retry to rerun the task what will lead to another 5 minutes wait and so on...)
how can i avoid this situation?
==============update=================
After getting a very good answer that would probably solve most of problems like mine i decided to add more information to let clear my problem.
The time consuming background service ISN'T process intensive, actually the reason it takes so long is because it is validating with the service some user "credentials" (when i say some, is really more than one)
So i can't store the result and trust it is valid on next run
I do know the this protocol needs to be improved but is going to take a bigger archtecture change so i would like to know if someone has any idea how to handle it on its actual requirements
Is there a need to do run the background task every time your Activity starts?
Typically, if your Activity needs these values to work and it takes so long to calculate or fetch these values, you would store these values after the background service has finished with them.
Basically, you're creating a cache for your data. So when your Activity starts, it checks the cache for data. If it finds the data, then it loads it immediately. If it doesn't find the data, then it runs the background task (typically the initial run).
It's also common to have a timestamp of when the data was stored in your cache, so if time apart is too long, you could either:
Show the outdated data, while running the background task. Background task finishes and stores new data to cache, then notifies Activity that there's new data. Activity updates with the new data.
Don't show outdated data, instead, you wipe the cache of the old data and run the background task.
Basically, this solution simply has your Service store the values calculated into a storage location, whether it's a database, SharedPreferences, files, or etc.
You avoid the need to have your Service return values to an Activity, since there's no guarantee the Activity still exists. Instead, the Service only notifies the Activity that it added newly updated data to the storage location, so if the Activity still exists, it'll update without a problem. And if the Activity is killed already, then it'll simply fetch the data when it starts up again.
I got some issue when I developing an App.
After I minimized the app or turn the screen off, and open lot of other apps or reopen the phone after a long time.
When I restart my app, it try to resume and keep showing the same page(with fragment).
But the data I need was already been destroyed so it will be null.
The data is an object array, I know maybe I can store them in db.
But due to the data will update every time user click something.
So I don't want to save it into data base, I guess that means lot of storage I/O witch is not necessary.
I'm wondering if there is any solution to restart the hole app when things is destroyed?
Or the only way to make it happen is I handle the null array and do the reload myself?
I don't really want to do that cause I guess that will bring me many unexpected issues cause the data is related with many pages.
Too many situations I have to consider when do switching pages.
Are there any advice?
But the data I need was already been destroyed so it will be null
That is because your process was terminated and you did not save your state.
But due to the data will update every time user click something
Or, you could fork a thread to save the data as part of your onPause() or onStop() methods. There are many possibilities between "never save" and "save on every click".
So I don't want to save it into data base, I guess that means lot of storage I/O witch is not necessary
If you want the data to be there 30+ minutes after the user left the app, your choices are to save the data locally (file, database, SharedPreferences) or save the data on the Internet somewhere.
For small amounts of data over shorter time periods, you could put the data in the Bundle supplied to onSaveInstanceState() and then pull the data out of the Bundle again later (e.g., in onRestoreInstanceState() of your activity). You already should be doing this to handle screen rotations and other configuration changes.
I'm wondering if there is any solution to restart the hole app when things is destroyed?
You are welcome to add android:clearTaskOnLaunch="true" to your launcher activity, to indicate that you always want to start over from scratch whenever the user leaves your app and tries to come back to it. Users will not appreciate this, as this means that they will lose their state even for being out of your app briefly (e.g., a quick reply to a text message). This attribute does not terminate your process, but it will force the user back to the launcher activity and will eliminate any other activities that had been in your app previously.
Or the only way to make it happen is I handle the null array and do the reload myself?
That is what developers normally do, yes.
Application Flow Image (Cannot post directly - not enough reputation yet)
Introduction
We are creating an application that manages our products. We have several types of a products (1) and each type of product has dozens of those type (2) (ex. Videos).
We have an xml files on our website that holds all the information for each product. When a user selects the type of product (1) it reaches out to our website to download the xml file which populates the product list (2). The user then selects the product from the list which then passes the information to the product single activity (3).
Oh philosophy was when creating the application to create a place where the user can download the product and materials connected to it, but have the application manage which products you have downloaded. You download everything you need so when you don't have internet connection you are still able to use the application and view the products you have downloaded.
Problem
Some of the products in our app are fairly large and require an extended amount of time to download. When a user is on the product single activity (3) they can download the products and when a configuration change happens we understand we need to use fragments to maintain the progress bar and text on the button.
! The problem comes in when the user hits the back button.
We don't want to just cancel the download for the user.
It takes quite a while for the download to finish
We want the user to have the ability to download multiple products at once.
Not canceling the ASyncTask actually lets it continue running when the user hits the back button and even allows us to send Toast messages to show that it is still running. The problem comes in when the user navigates back to the activity the UI doesn't show the file is still downloading because we lost the reference to the ASyncTask that is running.
Solution
We are trying to come up with a solution so that the user can back out of the product single activity (3) and come back to it later and see the status of an ASyncTask if it was started earlier. The problem is if the activity is destroyed how do we hold on to a reference to the ASyncTask or Fragment.
The solution to your problem would be to use services. Services in Android are designed to be long running background tasks. Although you can't directly hook into the UI thread from services, you can use Handlers to post to the UI. Your service will stay around as long as they are needed (Android kills them only under low memory conditions and even then tries to stay away from the running ones).
AsyncTask is designed to be used only for short operations. It is possible to use it with some changes to run longer processes but Android prefers to not do it that way. Android specifically tries to steer you to use background threads and processes.
The problems that you are seeing are because AsyncTask (generally being defined from within the activity class) are tied to the Activity itself and maintains a reference to it. But when an activity goes to the background and has remained in the background for some time, the activity may be destroyed and GC'd at which point, the AsyncTask loses its reference to the parent. With services, it will not matter whether your activity is still available or not. You can connect to the service anytime you want and then query the service to find the status of the download.
first of all there are services that do background work even if your app is displayed on the screen or dead.. second of all there are threads that work and work and work..
thirdly there is a methon called onBind that binds an activity to a service..
your SOLUTION??
use threads in services and whenver your activity is called or app is opened
bind it to the service to get what you want...
NOTE: if your file takes some time to download, well then asynctask is not a recommended approach..that is if it takes a hell of a timee..
Hope im helpful...thnks
In Android it is generally a good practice to perform no database operation (or at least complex ones) in UI-Thread. I have an activity with a complex form and I want to ensure that all data is saved when the activity goes in the background (e.g. the user presses the home button or a phone call comes in). In the activity’s onPause()-method I can start an AsyncTask which stores the data in database but I can never be sure that the task finishes successfully because android can kill the process before the task finished because the activity and the whole app is in background.
I can save data synchron in the onPause-method but then it’s possible to run in to an ANR.
I know that Android restores the views after the activity was killed but this works only correct when View Ids are unique. I have a lot of programmatically added Views where I cannot ensure the Id’s uniqueness and to use the saveInstanceState-functionality is nearly impossible because I have to save very complex models.
Is there any possibility to ensure that data will be saved before android kills a process without doing it in the UI-Thread?
I created an application once where I had similar data consistency concerns. What I did there is delegate the storing of the data objects to a Service I created just for that purpose. Although this makes the starting/stopping/initialization of your Activity a lot harder (once the activity is started again, you will have to wait for the service to complete its previously started save action), this was the only "Android" way I could think of to deal with this problem.
You might look into using a service for that if you are afraid that the system kills your background-processes before they are completed. This might be over-kill, but will definitely work as expected =) Just google "Android Service Tutorial" if you are unsure how to use them.
-Services won't be killed unless you want them to!
Indeed, if you're running an AsyncTask in onPause(), Android can kill your applications's process without waiting for the worker thread to finish. But it won't kill the process if there's a running Service. So a nice solution here is to implement database synchronization logic using an IntentService.
I'm facing the same question here, when to save data: while the user completes a form or when the activity pauses. Also we must take into consideration screen rotations or other events that might result in data loss.
Here is what I found on the Android developer site:
For content provider data, we suggest that activities use a "edit in
place" user model. That is, any edits a user makes are effectively
made immediately without requiring an additional confirmation step.
Supporting this model is generally a simple matter of following two
rules:
When creating a new document, the backing database entry or file for
it is created immediately. For example, if the user chooses to write a
new e-mail, a new entry for that e-mail is created as soon as they
start entering data, so that if they go to any other activity after
that point this e-mail will now appear in the list of drafts.
When an activity's onPause() method is called, it should commit to the backing
content provider or file any changes the user has made. This ensures
that those changes will be seen by any other activity that is about to
run. You will probably want to commit your data even more aggressively
at key times during your activity's lifecycle: for example before
starting a new activity, before finishing your own activity, when the
user switches between input fields, etc.
This model is designed to
prevent data loss when a user is navigating between activities, and
allows the system to safely kill an activity (because system resources
are needed somewhere else) at any time after it has been paused. Note
this implies that the user pressing BACK from your activity does not
mean "cancel" -- it means to leave the activity with its current
contents saved away. Canceling edits in an activity must be provided
through some other mechanism, such as an explicit "revert" or "undo"
option.
You need to start a backgrounds service daemon with a notification to make sure your data is saved and shut down the service and notification as soon as the data is saved. The notification will be shown until the background service is running as it is mandatory to show services of background service otherwise your application would crash.
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.