So, I have this android application and even some users. As I have a crash report system, I can see when someone's app crashes and the cause.
It appears that, though rarely, the app crashes randomly with NullPointerException when it tries to change some attributes(rotation, text, etc..). I make sure everything is set first thing in the onViewCreated method(using Fragments) like this:
private TextView orientationView;
orientationView = this.getActivity().findViewById(R.id.orientationView);
Using this ^^ example, I then try to hide/show this view and get an exception as it appears to be null sometimes, which is what I struggle to figure out why.
orientationView.setVisibility(View.VISIBLE); // app crashes when orientationView is null
Being a newbie in android development, I am not sure if it is a good practice, but in some of the fragments, I set all the previously initialized resources to null in the onDestroyView method, but the one that crashes the most doesn't have this method implemented, which make me to believe that somehow the resources are just not found/initialized in some rare occasions and I fail to change them later with an exception.
Could someone help me figure this out :) (more description could be provided, if needed)
Related
Let's say we call a method on a variable fetched through findViewById():
TextView tv = (TextView) findViewById(R.id.text);
tv.setText("Some text");
Android Studio automatically warns us that setText() may produce a NullPointerException if tv turns out to be null. If we however are certain that tv will never be null (unless something really wonky happens which should crash the app anyway), is it really worth encapsulating the method call within an if(tv != null){} statement? What if these two (or more) rows are executed very often? Can we gain any significant performance increase?
I personally don't think there is much point in checking these are null because you will know if they are present in your layout file or not, so I wouldn't bother.
However, I do sometimes use the following to prevent the warnings in Android Studio:
assert tv != null;
I don't know how this affects performance but I imagine it will have almost no difference.
Throwing or creating new exceptions will definitely consume more resources than what you might expect BUT it is always good to handle the exception where necessary rather than let the app crash. IF you are absolutely certain that the textview or whatever UI element ISpresent in the correct XML for your activity and/or the fragment then i don't think that you should use try catches at all..
Yes you can use asserts to avoid warning of Android Studio as mentioned above, and with respect to performance I don't think you will notice any huge performance variation. However, its always good to catch exceptions and log them as it can be really useful while debugging.
Actually, it can be null.
If you have complicated layout, and many ids, it can happen if you type id of other layouts.
This is only a warning. If your layout is simple to remember all ids or you sure it's never null, don't bother this warning.
This warning is helpful when you change an id in layout manually.
EX:
layout 1 has ids : text_view_1, button_1
layout 2 has ids : text_view_1, button_2
Activity 2 use layout 2 and findViewById(text_view_1)
If you change from text_view_1 to text_view_2 (MANUALLY by typing). No error happened, because id text_view_1 is still exits. But NullPointerException will occur when you run application.
Here is the link of the Minesweeper project on codeproject.com.
I just wanted to ask one thing here. I completely understood the logic and algorithm this guy used, but when he called the showMineField() method inside startNewGame() method , he called it after createMineField(). I am really confused! Shouldn't the layout be set before setting up mines and handling the user click events? But the code seems to work fine. If I just call showMineField() inside startNewGame() , it gives me NullPointerException.
This is because you cannot show a mine field before creating all the objects.
It is like trying to run without legs. If you call showMineField() that is using objects that have not been initialized. Thats why you are recieving a NUllPointerException. Nullpointer is throws when a method is trying to be call on an object that has not been created yet. createminefield() initialzes everything so that nullpointer is not thrown
I was going through following tutorial: http://www.dreamincode.net/forums/topic/190013-creating-simple-file-chooser/#viewSource
Inside the FileChooser class there is one exception beeing supressed, since there is nothing within the catch clause. So I decided to add following statement to the catch clause:
Log.e(ACTIVITY_SERVICE, e.getCause().toString());
For some reason this always causes the app to crash (NullPointerException). When I don't do any logging, except for a a simple syso print, then I don't get any exception and the app does't crash either. Then it works fine. I'm new to the whole Android Framework and just want to understand why this is happening.
Thanks to Ingo's and CommonsWare's hints I came to the conclusion, that following line caused the exception:
EDIT:
In fact it was the start of the foreach loop, which iterates over all subdirectories and files of a given directory. I didn't know, that this would cause a NPE, if the list you want to iterate on is actually null. For some reason I thought that the loop would be automatically skipped in this case.
Things were going well until I switched off the screen lock on my device, then things started going wrong intermittently.
I've managed to track the issue down and have some workarounds in mind BUT I would like to know if there is 'best practice' for avoiding or removing the issue.
The issue:
I have an application which changes images based on the application status.
The images are not huge but quite large (231k~) and are stored as resources.
After several screen rotations (I counted 27 with a project using a single ImageView), loading the images fails with Exception of type 'Java.Lang.OutOfMemoryError'
Stripped down to the barest project, the following demonstrates the problem:
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
//get a reference to the ImageView
var imageView = FindViewById<ImageView>(Resource.Id.imageView1);
imageView.SetImageBitmap( Android.Graphics.BitmapFactory.DecodeResource( this.Resources, Resource.Drawable.Ready) );
}
The above code is the only method I used to reproduce the issue.
Whilst attempting to resolve, I extended the example so that imageView was released in OnDestry:
protected override void OnDestroy ()
{
base.OnDestroy ();
imageView.SetImageBitmap( null );
imageView.DestroyDrawingCache();
imageView.Dispose();
}
This made no difference unless I added GC.Collect() which I don't want to do.
The best workaround I've currently thought of so far would be to modify the code as follows:
static Bitmap _ready = null;
private Bitmap GetReadyImage {
get {
if (_ready == null) {
_ready = Android.Graphics.BitmapFactory.DecodeResource (this.Resources, Resource.Drawable.Ready);
}
return _ready;
}
}
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
//get a reference to the ImageView
imageView = FindViewById<ImageView>(Resource.Id.imageView1);
imageView.SetImageBitmap( GetReadyImage );
}
This relies upon a static reference to each Bitmap and a property accessor for each.
I could even write a method which stores the images in a static List to save writing property accessors for each different property/variable.
I could perhaps add the flags ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize |ConfigChanges.KeyboardHidden) but this would break the normal Activity lifecycle which I've read isn't best practice?
I find it strange that having scoured the web, I've not yest encountered similar issues or examples. I'm left wondering how most others deal with this?
Any thoughts or comments are much appreciated.
I can only approach this problem from a truly native perspective, as I have not worked directly with the Mono framework.
The described symptoms are 100% indicative of a memory leak in the Activity, but the code shows no real evidence. If you can truly produce the issue with a project containing only one Activity and those four lines of code, it sounds to me like it is perhaps a framework bug that ought to be filed with Xamarin. Have you attempted to create the same simple project in pure Java to see how the results fare on the same device/emulator you are using? It would also be interesting to know if the issue is localized to a specific version of Android. I have never seen this particular behavior before in a native application project.
The awkward part is your statement that forcing a garbage collection makes the problem go away. You're right, you shouldn't have to do that, but a true memory leak (i.e. an unreleased reference) would still persist even if you hit the GC several times. The Android paradigm of destroying and re-creating the Activity on each rotation is such that even if the old Activity lived for awhile, when memory was tight it (and all its references) would quickly be collected to make room for a new instance. If this is not happening, and each Activity is living on past even the system triggered GC passes, perhaps there is a stuck reference in the native code generated by Mono.
Interestingly enough, technically your workaround actually does introduce a true leak, by attaching the Bitmap to a static field that is never cleared. However, I agree that in comparison it seems like a more efficient move. A simpler workaround might also be to code your Activity to manually handle configuration changes (I don't know if Mono is different, but this is accomplished by adding android:configChanges="orientation" to the manifest file). This will keep your Activity from being recreated on each rotation, but it may also require you to reload your view hierarchy if you have different layouts for landscape and portrait. However, even if you have to do this the Acitivity instance will be the same you can safely save the Bitmap without resorting to a static field.
However, if you cannot reproduce the problem with the same project in a native Java project, I would report a Mono bug.
Hard to see without the entire code but it obviously sounds like you have a memory leak. Screen rotation (due to the destroying/creation of the activity) is known to cause these. You might want to have a read at this article by Romain Guy as well as this talk from last year's IO.
I am working on a flash game and about finished with it but I'm running into an issue. When the game ends, or the user presses the "End Game" button I want to return them to the main menu. The game is set up so that the main menu is on the 3rd frame, and the game runs in the 4th frame. All of the game code is there.
A few things I have tried:
I just simply tried to return to the 3rd frame. This results in the error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Hundred_fla::MainTimeline/GotoEndGame()[Hundred_fla.MainTimeline::frame5:66]
I have tried returning all the game vars to their default values, removing all children... so on... I also get the exact same error... not sure what the problem is. I thought one solution would be to reload the movie, but this will be running on Android/IOS and I cannot refresh a webpage. ... any help would be greatly appreciated. Thanks
Edit: The code on line 66 is:
while(stage.numChildren > 0){
stage.removeChildAt(stage.numChildren-1);
}
You should lock stage link before trying to purge it of objects. You are seemingly removing the instance that runs the code, so it loses stage reference.
var theStage:Stage=stage;
while(theStage.numChildren > 0){
theStage.removeChildAt(0);
//you can always be sure that element at [0] exists, rather than going for [numChildren-1]
}
Depending on what's line 66 of the 5th frame, it could a few things:
you are targeting Flash Player 9, where the display objects are loaded asynchronously to your gotoAndStop call, so you end up with null references. Solution is to target Flash Player 10 or 11 (change it in Publish Settings [Ctrl+Shift+F12]). If you really need to target Flash Player 9, there are convoluted methods to ensure the attributes are accessible
after the gotoAndStop you are referencing an object from the 5th frame, which is not available anymore, and thus throws a null object reference error
it's an error in your logic and we need to see some of the code to find it
When in doubt, it's always best to leave the gotoAndStop call as the last one in the method.
Edit:
After seeing the code, it seems that stage itself is null and thus throwing the error. If it makes no visible difference, you can surround your code with a try/catch:
try {
while(stage.numChildren){
stage.removeChildAt(0);
}
} catch (error:Error) {
}
Also try listening to the ADDED_TO_STAGE event to make sure you have a valid reference to stage before accessing it.