Android - problems with a multi-level activity chain - android

(Note that I've searched online for the warnings I'm describing below, and have come up with next to nothing about them.)
I'm working with API level 10. I have a preference screen (XML-based), and one of the options in there creates a custom ListActivity as follows:
PreferenceActivity contains an option that creates a...
ListActivity which is a dialog that employs...
setOnClickListener() which contains an onClick() method that (right before calling finish()) will startActivity() a new Intent...
sub-Activity which starts up an...
AsyncTask which does variable time work which when done calls...
onPostExecute() which calls finish()
The thing is, it works... but I'm getting a raft of warning starting with:
10-16 21:59:25.010: WARN/WindowManager(170): Rebuild removed 4 windows but added 3
10-16 21:59:25.010: WARN/WindowManager(170): This window was lost:.....
Curiously, this raft of warnings ONLY comes up when the task executes quickly! When I added a Thread.sleep() call to my AsyncTask to artificially inflate its runtime it worked and threw no warnings whatsoever. In fact, as long as it takes more than (roughly) 500 ms to run it works fine. (Note that I tried using startActivityForResult() to no greater effect - the same problem occurs.)
The goal is that the user selects a preference item, they change its setting, some processing takes place, and then the user is left back at the preference menu they started on.
I'm betting it's a race condition... the order in which the windows are destroyed varies depending on that run-time... and I get the impression that when the sub-Activity closes before its parent ListActivity the warnings get thrown. But sprinkling a 1s sleep() in isn't a reasonable solution unless this is some sort of Android bug (unlikely, but then again I've reproduced a couple of those today already).
So, what's the flaw in this my that leads to this stream of warnings? It'd be nice to say "on preference, do this, then do that, then finish" but I think what I'm doing is the equivalent. Maybe not... thoughts?
Edit: I decided to try doing this ListActivity as a custom Dialog... that was one of the more painful things I've tried to do lately (getApplication() doesn't work and lots of other things seem to go wrong... it may be inexperience to some extent, but dialogs really weren't meant for this either...

Try the following two things:
Dismiss your dialog before calling finish() on its parent activity (PreferenceActivity).
Make sure you are starting your AsyncTask later in the sub-activity's lifecycle. I'm specifically thinking you should launch it in onResume().
My best guess is that the AsyncTask is calling finish() on the sub-activity, before the sub-activity has had a chance to fully start up. Why that would matter? I'm not sure. Something to try though. Good luck!

Related

Is it possible to check a second Espresso Intent matcher after you receive the result from the first one?

When using the intended(IntentMatcher) from the Android Espresso API, is it possible to do this twice in the same Activity?
So for example I click a button which starts an Activity for result. I check that this Activity has fired using intended(IntentMatcher). That works.
However, when I get the result, I want to fire off an Intent for a different Activity. In this case just a local Activity in the same app package with no result.
When I do this manually in the app it works fine, but Espresso can't seem to detect the second Intent in my test. What I am I missing or is this not possible? Alternatively, how should I be doing it? Maybe my design is bad.
When I do the check I'm trying this:
intended(toPackage(<packageName>));
intended(hasComponent(hasClassName(<className>)));
The first line matches but not the second one. And even if the second line is not completely correct it never seems to show anything in the error log about the second Activity I'm actually starting.
Another thing adding to the confusion is that two intents are definitely being fired as it shows that in the log. They both seem to be the same one but with slightly different details - one is a package, one is a component. Does it log the result from the first Intent as an Intent in itself? Sounds unlikely but where is this other intent coming from? I know it's not the second Activity I'm launching as it still fires even when that Activity isn't called (when the first Intent result is a fail).
I've also considered that maybe it's not getting detected because it's not waiting long enough for the second intent to fire. If that were the case, what would I do about that? I don't see much talk about handling time sensitive things in Espresso. Like checking if a progress bar is shown but then hidden again while not pressing anything. How do you do that? Maybe it's the same answer.
Any help appreciated!
Ok I found the problem. My IdlingResource wasn't working.
After fixing that it works like a charm :)

Android - Notepad example - Why populate in onCreate?

I have finished the Layout exercise and wondering why they include the call to populateFields() in both onCreate and onResume.
According to Activity Lifecycle "onResume" will always be performed before the Activity is shown so why not just there?
I have real production code that populates fields and is only called in onResume and it works just fine.
I thought one reason would be that maybe onResume is called after the activity is shown, but a bit of googling digs this (mostly unrelated) thread:
http://groups.google.com/group/android-developers/browse_thread/thread/ddea4830bedf8c6c?pli=1
Quote: onResume() is thus the last thing that happens before the UI is shown
This is what Dianne Hackborn says so i guess we can trust her :)
Actually I have seen apps (in my app and also others), where fields were only populated in onCreate(), but not in onResume().
Lets call that app 'A'.
The effect was that when the user pressed the home button, went to a different app, and then returned to 'A', the screen stayed black, as 'A' was still in memory and thus the system did not bother to call onCreate(), but directly went into onResume().
So basically I'd say (and this seconds what #Torp wrote) populate the UI in onResume() and be done.
But then, this answer is slightly off-topic as it does not answer your "why" question.
You don't populate in onResume because it will be called every time the activity is shown.
You generally want to create as few objects as possible, so you create them once and for all in onCreate, and then you can always check that they are still updated in onResume.

Android AsyncTask - Start Next Activit From onPostExecute - Bad Idea?

I have an activity which performs a bunch of SQLite inserts as its very last act before starting another activity which relies on the just-inserted data.
I have just moved all the db stuff into an AsyncTask...and, yep, you guessed it, the new activity is being called before the previous one's inserts have completed.
Now, I'm happy with the speed of my db operations, but, how do I make my app wait for the AsyncTask to finish before starting the next activity?
I was thinkig about starting it fromonPostExecute, but that feels wrong, although I don't know why it would be if it is.
Currently all I intend to do in pre/postExecute is show a default dialog...but, that's obviously also failing because the next activity is starting as soon as the asyncTask is started :)
No need for AsyncTask usage here, or is there just a simple way to say "woah, boy, wait a sec!"? :)
It's OK to launch the other activity on onPostExecute... in fact, it sounds reasonable in your case.

ResourceNotFound on layout inflation

My app may launch a sub-activity for a specific purpose. When that activity finishes, I get the results in onActivityResult. These results are then processed in the subsequent onResume. This consists of a setContentView and also starting an AsyncTask that puts up a ProgressDialog.
This all works well when initiated the normal way, which is via a user request (i.e., menu selection) after the app is up and running. However, under some conditions I need to do this right as the app is starting up, so I initiate this sequence right from my onCreate. What then happens is that I get fatal ResourceNotFound errors within any o/s call that implicitly calls the layout inflater. I got around this with setContentView by pre-inflating the view in my onCreate method, but the AsyncTask's onPreExecute still fails on ProgressDialog.show() as it "fails to find" Android's own progress_dialog.xml!
Anyone know what's happening here?
I suspect it's something to do with the timing, where this is occurring before the main activity has even had a chance to display its screen. These calls are all being made on the main UI thread, but maybe something hasn't completed within the o/s under these conditions.
As a closeout, the problem turned out to be totally unrelated to what I described in my post. Turns out it was due to blindly using some code that had been posted in some online forum showing how to get and use AssetManager. Trouble is, at the end of the block of code he had put "assMan.close()". Well, this closes the asset manager for the entire activity and resources can no longer be accessed!
It took a while to find it since it was not something that I did via my own understanding.

Same Activity called twice... Issue with Multiple AsyncTasks?

I have three simultaneous instances of an AsyncTask for download three files. When two particular ones finish, at the end of onPostExecute() I check a flag set by each, and if both are true, I call startActivity() for the next Activity.
I am currently seeing the activity called twice, or something that resembles this type of behavior. Since the screen does that 'swipe left' kind of transition to the next activity, it sometimes does it twice (and when I hit back, it goes back to the same activity). It's obvious two versions of the activity that SHOULD only get called once are being put on the Activity stack.
Could this be from both onPostExecute()s executing simultaneously and both checking the flags each other set at the exact same time? This seems extremely unlikely since two processes would have to be running line-by-line in parallel...
*****EDIT*** A lot removed from this question since I was way off in what I thought was wrong. Nonetheless I found the answer here quite useful, so I have edited the question to reflect the useful parts.
The only way I can find that this is
possible is if both AsyncTasks'
onPostExecute() executed SO
simultaneously that they were
virtually running the same lines at
the same time, since I set the
'itemXdownloaded' flag to true right
before I check for both and call
startActivity().
Since they are both called on the main application thread, that's not possible, unless you're doing something really strange.
I would introduce some Log calls to ensure that you are not misreading the symptoms.
Beyond that, it is difficult to see any problems from your pseudocode, unless there's a possibility of other downloadID values beyond the three shown. For example, if there is a DL4, and DL4 completed after DL1 and DL2, DL4 would trigger your activity.

Categories

Resources