In my login Activity, just after the use log in, I sync data and create several tables in sql.
If the user open another app before this process finish, I want to cancel it and delete tables.
I thought I could put it in onPause or onStop, but then, when the process finishes and go to the dashboard activity, onPause or onStop should be called, and I don't want this.
I assume the solution is simple, but I can't figure out how to solve it.
Any idea?
The logic behind your solution is straightforward - create a flag (say for example shouldRollback) to true when you start your transactions. Once your transaction are successfully completed, you set this flag to false. In your onPause() method, simply check for this flag. If it is true, you know you need to roll back the changes.
I would only suggest this if this is your requirement. Personally, I would process all database operations in a background thread. The thread can run in the background even if other applications are opened. There will be too much overhead (if you have a large number of transactions) to keep rolling back inserts. You could use the transaction methods from the SQLiteDatabase object to automatically roll back changes if they were not completed successfully.
Related
I have an App with 2 activities A -> B. From B the user can update data being displayed by A, so I want A to show fresh data when the user navigates back (actually not so simple, some network involved so data can be updated at any time).
The activities are listening to ddbb changes so the views can be updated when data changes. Problem is data can change while activities are in background, so I am not sure when and how i should listen for changes. I can think of two approaches:
Listen for changes during the whole Activity lifecycle (onCreate - onDestroy) and just update the views when the data changes. This will update views from background activities.
Listen for changes only when the Activity is being active or displayed (between onStart/onStop or onResume/onPause) and force a view update every time the activity comes to the foreground (since changes might have happened while activity wasn't listening).
Mixed approaches; keep the listeners the whole lifecycle but only update views when activity comes to foreground.
Im not sure which is the correct way to handle data observing while in background.
Option 2 sounds more reasonable, but having to update the views when the activity comes to foreground may lead to UI lag right when the user starts interacting with the activity.
Option 1 will cause a lot of updates every time data is updated.
Thoughts on this?
You can choose any of the three options that suits your particular use case. Though I will say that the conventional use is with start/stop. onStart says that the activity is visible to the user in some way (either fully or partially) and onStop says that the activity is definitely not visible. So if you don't care to update the UI while the activity is not showing at all, use these lifecycle states.
You just may need to be prepared to capture data that you may have missed while the activity was stopped before it gets started again (for example, if the user pressed the home button, then came back to the activity via the task switcher. So performing your query again and rebuilding the contents of views from scratch may be necessary.
I'm sure this question gets asked a lot, but I'm looking for the simplest solution with Android best practices in mind (no hacky manifest that tries to keep a single Activity instance). Also, I'm not looking for a retain Fragment solution.
I'm looking for the simplest way in an Activity to initiate a background task and provide a callback function. If the Activity gets re-created (config change), then I want the old activity to release the reference, and attach a callback to the new Activity instance.
Lastly, I don't want to have to perform the operation again. Meaning, if it's some HTTP resource, it should be cached so that the operation is not run again wastefully.
Thanks!
First of all you need to decouple a task execution and activities(UI). To achieve this you can use events which UI sends to some task executor. The basic idea looks like this:
when method onResume was called you register you activity to receive events.
then later somewhere you execute the task to load some data from network.
next you have three options:
a) the task finished and your activity exists. The task sends event "i'm_finished". And your activity receives it.
b) the task is finished but your activity was destroyed/hided. When activity was hided the system called onStop method of your activity where you unregister your activity to receive new event. So event was not delivered.
c) the task is not finished and new activity was created. New activity checks if data is available or is downloading now in onResume method. If it's downloaded then show it, if not then wait.
The detailed explanation is here: http://www.mdswanson.com/blog/2014/04/07/durable-android-rest-clients.html.
The most popular event libraries for Android: Otto and EventBus
I my experience the simplest way is actually to use an AsyncTask (http://developer.android.com/reference/android/os/AsyncTask.html). However, that might blow up after a config change. So you should probably attach that AsyncTask to a "HeadlessFragment". For the Fragment you can enable "setRetainInstanceState" so the fragment will not be recreated. Then after config change you can just attach to that fragment again.
My app is retaining all of the variable values when it closes and this is effecting how it runs when reopened. Is there any way to reset them all upon app close? or is there a way to clean the app from memory when it is closed so to speak? For the moment I have just been setting all of the important variables "=0" in the last few lines of execution but I know there must be a correct way to doing this.
EDIT:
OK I thought that it would just be easier to reply here instead of individually to everyone.
The app is indeed staying alive in the background, I checked with advanced task killer. How would I get the ap to "Die" by presing the back button? I think this would be the easiest solution given how the app works:
open app > press start button > press stop button > results screen > press back button to exit.
so basically each time the app runs should be an independant execution.
Override the onPause, onResume, and onDestroy methods. onPause should save anything upon pausing, onResume should reload these values when it is resumed, and onDestroy will be called when your app closes. You can clean up stuff in onDestroy. See this link.
You app is probably not closing but remaining in background. Check advanced task manager and see if the app is running or not.
You need to familiarize yourself with the Activity Lifecycle.
You could leverage onResume() to reset your variables; also note onDestory() and onPause().
UPDATE:
Killing the application in its entirety each time the app moves to the background is an anti-pattern. You should really look at your application and follow the aforementioned activity lifecycle pattern and take the needed steps to insure your variables exist as you desire based on state.
I like what #Alex and #Jack said. To add to that, also consider that you can call finish() in your Activity if you want to force it to close up and return to the last Activity. Going along with this, also consider the use of setResult(int) (JavaDoc Here)
You can also set a flag on the Intent when you call the Activity you are questioning about. A flag like FLAG_ACTIVITY_NO_HISTORY could be helpful:
If set, the new activity is not kept in the history stack. As soon as the user navigates away from it, the activity is finished. This may also be set with the noHistory attribute.
List of Intent Flags
Uninitialized variables are bad. Don't do it. ALWAYS manually reset variables before using them for the first time.
the onResume() method will let you reset the variables when the program resumes, but will also do it when you return to the activity unless you add the logic that says you are coming from in the app, not the home page. Maybe onRestart() is what you really need? I'm not positive, but it's possible with onResume.
I have two activities. In activity 1 I write a value to a SQLite database by entering that value into an EditText field. Once I press the submit button, the data is written and I am moved along to another activity - activity 2. Activity2 also does the same thing in that I can write new data and persist it to the database with a button click. So, my question is: do I need to synchronize the method (which is on a separate thread from the UI) in activity 1, as well as the method in activity 2 in order to prevent thread safety issues in the database? Keep in mind that both methods access the same database but from different activities. Technically, activity 1 should be complete with onStop having been called and the new activity (activity 2), now being visible. Is it even possible for these two activities and their corresponding threads accessing the database (via different methods) to have any kind of concurrency problems given the Android activity life cycle?
Thanks very much,
Matt
Check this method SQLiteDatabase.setLockingEnabled(boolean lockingEnabled)
How is your background thread created? A background thread will continue to run even after an activity has been stopped.
If data in activity 2 will not be persisted until the user has entered some data, then it seems like a lock would be unnecessary given the fact that the data from activity 1 should persist in a matter of milliseconds.
However, if you're preparing for the worst case scenario, I don't see how a database lock would hurt anything (as #Pepi suggested). The only way I can see this being a problem is if work being done in your background thread (activity 1) is hanging on something before it can commit the data. If activity 2 starts it's own background worker to commit data, then you could potentially have a race between these two background threads.
I have two static tables with about 500 records each which provide lookup material for some ListViews in my app. When the app first starts and the tables are created I run a process to populate the tables which takes less than a minute but I've been looking to run the process in background using Async Task with a progress dialog letting the user know what is happening.
My concern is that while the process is running and the data is being added and then the user tilts the phone the process will cancel. What would be the state of my database then? Is Async Task the best solution for this or should I use Threading?
So when you rotate or change the orientation of the phone, the activity is the only thing destroyed. You don't necessarily have to get rid of the async task. In fact it will live on. Just don't let another task come in and work on it ad-hocly.
So if you want to have your activity act as if upon rotating that you can start right back up, where you left off, there is a method called onRetainNonConfigurationInstance(). It's basically the method that stashes objects which can't be parceled like in saveInstanceState()
So the idea being:
public void onCreate(Bundle a) {
...
AsyncTask myTask = getNonConfigurationInstance();
if (myTask == null) {
myTask = new AsyncTask();
myTask.execute();
}
...
}
public Object onRetainNonConfigurationInstance() {
return myTask;
}
This will keep the async task running, and when you get your onCreate called after the rotation you just pick it back up and do what needs to be done.
One thing to be conscious of is the progressView. It will have to be destroyed and reinitialized to the new state. Also the overall dismissing of it and showing it in the first place should be done outside the AsyncTask. But nothing is to say that the AsyncTask can't call some callback that you always set in your onCreate() so that it will notify to tell to update the UI or play a sound of completion, etc.
You could also decide to handle the configuration changes on your own through the use of the android:configChanges in your manifest.
You then implement the onConfigurationChanged method and perform any actions inside.
See the developer doc.
When a configuration change occurs at
runtime, the activity is shut down and
restarted by default, but declaring a
configuration with this attribute will
prevent the activity from being
restarted. Instead, the activity
remains running and its
onConfigurationChanged() method is
called.