ANR problem in my app - java

I have quite a heavy Activity with a lot of things going on in the UI Thread, and also other Runnable threads within the Activity. Within this main activity I start a new Activity with a button press which is called using startActivityForResult(). Now when I start the new activity I get an ANR error meaning that there is something taking longer than the set amount of time and I get the ForceClose/Wait Dialog pop up.
The thing is, for the new Activity I am only setting the contentView for the activity and nothing else so it means something from the previous Activity is causing it to hang. It has never down this before in the app only recently and I can't think what I have added for it to cause this.
In the first Activity I have OpenFeint, SurfaceHolder.Callback, database calls in background thread and lot's of image manipulation. Are any of these processes hungry enough to cause the ANR?
Could I possibly put the first activity on hold while the second one loads (I thought it did that anyway)? Like I say the second Activity does nothing other than load a ContentView.

When you start a new activity, the previous activity should be put on hold, as you say. But first the activity's onPause is called. Maybe it's this method which causes the ANR? Especially if it is saving large amounts of state data.
Just guessing here.

The fact that there is an ANR it is pretty clear that something is running longer in the UI thread (as you have pointed out). Also, you seem to be doing a lot of things (at least the explanation gives this feeling). At this point I can say try commenting out certain parts and see if the problem persists. E.g. comment the startActivityForResult(), this should tell you which activity is the culprit. Also, if you can put up some pseudo code, I'm sure people would get a better idea and would be able to help better.

The ANR occurs usually when you solicit the UI (like pressing a button), so I think it's not the second activity launch which causes the ANR, but the fact you use the UI.
So the problem is from your first activity, not the second.

Related

runOnUiThread and callbacks strange behavior

At runtime, I am using a callback pattern to have generic code run and use the callback when finished to execute code on the GUI. So in my handler I use the runOnUiThread function against the callback.
These are all async http calls. At runtime if I interrupt and use the back button and go to another fragment for example, the system will swap out the fragments and run both callbacks (the new fragment one on the correct callback, and the old callback that should have ran on the old fragment on the new current fragment). This is wrong, the new fragment gets both callbacks but when it was initialized it was assigned to the other fragment...
This makes no sense and you can only observe the behavior by switching fragments at runtime before an async call finishes. I don't see how it's possible, in the code I check if callback is null so it should have been garbage collected and how it runs on the new callback I don't know how it's possible....there's no additional assignment happening to change this. It's almost like it's just looking in memory for the function signature and running it even though when it does it's on the wrong object.
Does anyone have any clue what's going on? I've surpressed it with an ugly piece code, I just don't know how this is possible?
I understand the obvious candidates are if I assigned it again somewhere, but the answer is no. When the fragment is created it creates an object, assigns itself as the callback, and processing begins so when the fragment is destroyed it should be too. But the async task is still executing which is fine, why it does a callback on the new thread on the main gui I guess is because of runOnUiThread, so that function is somehow changing what the callback object points to in memory?
Its your code :-)
There is no magic happening 'behind the scenes' in Android and no references are changed.
Many have problems like yours, and its always because they assume that the Android system is somehow cleaning up when a fragment or activity instance is replaced or removed. It isn't, and therefore the callbacks are still executed, on a obsolete fragment or activity.
runOnUiThread takes a Runnable and runs it when the UI thread have spare time (after invoking lifecycle methods and finished rendering). Its not magic either :-)

Singletons not available when the App comes back to memory

The problem I'm facing is the following: When I start my app all the singletons get initialized in the main activity and everything works as expected. Then if I press the home buttom and comeback to the app quickly everything works, I think it's because everything is in memory yet, but if I go to chrome watch a couple of videos or start a game and try to get back to my app I get an exception. I don't understand this state of the app because it's not killed but it's not in memory and it tries to get back to the activity it was before pressing the home buttom, the onCreate method is called and I receive the Intent which called the activity in the first place but singletons are not initialized, the exception occurs here:
Tracker tracker = GoogleAnalytics.getInstance(this).getDefaultTracker();
tracker.set(Fields.SCREEN_NAME, "My View");
tracker.send(MapBuilder
.createAppView()
.build()
);
A possible solution I tried is just checking the tracker and if it is null create a new one and set it:
if(tracker == null){
tracker = GoogleAnalytics.getInstance(this).getTracker(trackerId);
GoogleAnalytics.getInstance(this).setDefaultTracker(tracker);
}
But I get another exception in another singleton. My question is: what variables are kept in memory when the app is in this state? What should I do, maybe call finish when the tracker is null? or Intent the main activity?
Simply the Android system doesn't insure anything staying in memory forever, whenever the system needs memory it's gonna start clearing background apps and services according to priority.
One approach is you can make the getters of the singletons handle that, if the instance variable in your singleton is null or not initialized, then you should initialize it, that could solve your problem and it will add a lazy initialization flavor to your approach.
Another is you can add a flag in onSaveInstance() and you can check it in your onCreate(), then you'll know if this is the first time for your activity to start or it has been cleared from memory and is being reinitialized.
Try using finish() and also add the try catch method in If condition

How disable destroy my activity

My app contains Activity. I start it by Intent. Than I turn my Activity to background (switch to Home Screen or similar). After some time the OS destroy my Activity (I think when memory is low). It is possible protect my Activity (in background) from destroy by OS? Or increase it priority to maximum?
Activity is made for a UI holding elements. Service is made for background tasks. From this already sounds logic to make a Service instead of try to keep Activity in background.
Also there are BroadcastReceivers, which will be called on different actions. Boot completed, Internet lost, got and so on.
I think you know what do you want to archive, I would suggest telling in detail an will get a lot better response, with enumeration, maybe code part of component needed to use.
Keeping Activity forced alive is a bad idea in general.
You can load WebView in background.

How do you have the code pause for a couple of seconds in android?

Basically I need a pause (based on just a few seconds) to be put into one action so that the user can see what happens before the next action is taken. So for blackjack, when it's the dealer's turn and he decides to hit, he hits, a card is added, and then he decides what to do next. So before he decides on what to do next, I want the code to pause so it can be "seen" as to what the dealer is doing this way the dealer doesn't complete his actions in less than a second and the player only sees the results.
Thanks in advance!
I should note I have tried using wait(insert number here); but i am told by eclipse that it causes a stack interception error or something of the sort and throws an exception, thus doing nothing : (
Well this is interesting, (the way I've programed the things is "interesting" to say the least) I did the Thread.sleep(5000) and threw it under a try catch, it does sleep for 5 seconds and then continues doing the code. However my updates to views don't show until after I press a button(Is really hating event driven programming).
Learning to think in terms of events is indeed the key here. You can do it. :)
The first rule is: never stall the UI thread. The UI thread is responsible for keeping your app feeling responsive. Any work you do there should not block; do what you need to do and return as quickly as possible. Definitely avoid doing I/O on the UI thread. (There are some places where you can't really help it due to lifecycle requirements, for example saving app state in onPause.) If you ever call Thread.sleep on the UI thread you are doing it wrong.
Android enforces this with the "Application not responding" (or "ANR") error that the user sees. Whenever you see this in an Android app it means the developer did something that caused the UI thread to stall for too long. If the device is really bogged down for some reason this error might not actually be the app developer's fault, but usually it means the app is doing something wrong.
You can use this model to your advantage by posting your own events. This gives you an easy way to tell your app, "do this later." In Android the key to posting your own events is in the Handler class. The method postDelayed lets you schedule a Runnable that will be executed after a certain number of milliseconds.
If you have an Activity that looks something like this:
public class MyActivity extends Activity {
private Handler mHandler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler.postDelayed(new Runnable() {
public void run() {
doStuff();
}
}, 5000);
}
private void doStuff() {
Toast.makeText(this, "Delayed Toast!", Toast.LENGTH_SHORT).show();
}
}
Then 5 seconds after the activity is created you will see the toast created in doStuff.
If you're writing a custom View it's even easier. Views have their own postDelayed method that will get everything posted to the correct Handler and you don't need to create your own.
The second rule is: Views should only be modified on the UI thread. Those exceptions you're getting and ignoring mean something went wrong and if you ignore them your app will probably start misbehaving in interesting ways. If your app does most of its work in other threads you can post events directly to the view you want to modify so that the modifications will run correctly.
If you have a reference to your Activity from that part of your code you can also use Activity#runOnUIThread, which does exactly what the name implies. You might prefer this approach if posting to a single view doesn't really make sense in context.
As for updates to views not appearing until you hit a button, what kind of views are these? Are they custom views that are drawing these updates? If so, are you remembering to call invalidate after data changes to trigger the redraw? Views only redraw themselves after they have been invalidated.

Android App/Activity To Start Fresh Completely every time it starts or resumes?

I have a kid's app for Android and there are some unique considerations for this application since the app has basically no navigation (it's for young kids). I do not want to break my app UI (which has been successful on iPhone) by adding a quit/restart button.
What I really need is fairly simple -- I want my activity/app to start clean and new every single time it starts. Whether it's an initial load or whatever -- basically any time onResume is called I want a completely fresh instance of my app.
I initially thought I could just exit/quit/finish the app when the user leaves. But I haven't found a way to do this that doesn't cause crashes on start. Also every thread/stack overflow post about that idea is filled with people wagging their fingers and saying you should never ever quit an app on android.
If I can't quit the app onExit, is there something I can do to restart my activity every time onResume is called? (or would that be an infinite loop?).
Would greatly appreciate any help!
Try starting your main activity in onResume, and clearing the activity stack:
public void onResume() {
super.onResume();
startActivity(new Intent(this, MainScreen.class).addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
}
maybe these aren't the correctl flags to add, but check out the other Intent flags and this could do what you want!
intent flags documentation
Ended up getting it to work fine by calling finish() in onPause().
Again, I appreciate the advice from people saying "this is not how Android does things". I've got a pretty good understanding of the best practices at this point. This is an unusual situation for an unusual type of user.
in your reload you can try this..
onStop();
onCreate(getIntent().getExtras());

Categories

Resources