-3

FIRST OF ALL, I KNOW WHAT IS AN NULL POINTER EXCEPTION. And no, this thread is not a duplicate So please don't tell me that my object is null, I know it. I just can't understand why, and I think it probably has something to do with the handler thread. I'm a confirmed Android dev, so please just read the problem and stop being insulting with all your "do you know what is a NPE?". Thank you.

I have an Android app in production and some users are experimenting a crash that I just can't reproduce or understand, no matter how hard I try.

To make it simple, I have 2 AutoCompleteTextView corresponding to the firstname and the lastname of an Author. When you start typing, the EditTexts autocomplete with the existing authors in database.

This is working fine for me and for 95% of my users, but some of them are experimenting a crash, sometimes, when clicking on an item.

Here is the code :

    final List<Author> authors = Author.listAll(Author.class);
    List<String> authorNames = getAuthorNames(authors, false);

    authorLastnameEdittext.setAdapter(new ArrayAdapter<>(getActivity(), android.R.layout.simple_dropdown_item_1line, authorNames));
    authorFirstnameEdittext.setAdapter(new ArrayAdapter<>(getActivity(), android.R.layout.simple_dropdown_item_1line, authorNames));

    AdapterView.OnItemClickListener onExistingAuthorClick = new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            String text = ((TextView) view).getText().toString();
            for (Author a : authors) {
                if (!a.toString().equals(text)) {
                    continue;
                }
                author = a;
                authorLastnameEdittext.setText(author.getLastname());
                authorFirstnameEdittext.setText(author.getFirstname());
                existingAuthor = true;
            }
        }
    };

The Stacktrace of the NPE that I have in Firebase is :

Exception java.lang.NullPointerException: Attempt to invoke virtual method  
'java.lang.String com.vgm.mylibrary.model.Author.getFirstname()' on a null object reference
com.vgm.mylibrary.dialog.AddBookDialog$7.onItemClick (AddBookDialog.java:292)
android.widget.AutoCompleteTextView.performCompletion (AutoCompleteTextView.java:915)
android.widget.AutoCompleteTextView.access$500 (AutoCompleteTextView.java:91)
android.widget.AutoCompleteTextView$DropDownItemClickListener.onItemClick (AutoCompleteTextView.java:1208)
android.widget.AdapterView.performItemClick (AdapterView.java:334)
android.widget.AbsListView.performItemClick (AbsListView.java:1531)
android.widget.AbsListView$PerformClick.run (AbsListView.java:3667)
android.widget.AbsListView$3.run (AbsListView.java:5590)
android.os.Handler.handleCallback (Handler.java:739)
android.os.Handler.dispatchMessage (Handler.java:95)
android.os.Looper.loop (Looper.java:145)
android.app.ActivityThread.main (ActivityThread.java:5951)
java.lang.reflect.Method.invoke (Method.java)
java.lang.reflect.Method.invoke (Method.java:372)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1388)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1183)

So the NPE happens on this line : authorFirstnameEdittext.setText(author.getFirstname());

My question is simple : how is that possible ?! The NPE says that at this line, the Author is null. Admit that this is true, the app should have crashed the line before, when doing : authorLastnameEdittext.setText(author.getLastname());

Here is a screenshot of the view to help visualization : Autocomplete screenshot

Thanks !

Edit : I made a modification suggested by pskink, replacing my String ArrayAdapter by an Author ArrayAdapter. So now the code is :

    final List<Author> authors = Author.listAll(Author.class);
    authorLastnameEdittext.setAdapter(new ArrayAdapter<>(getActivity(), android.R.layout.simple_dropdown_item_1line, authors));
    authorFirstnameEdittext.setAdapter(new ArrayAdapter<>(getActivity(), android.R.layout.simple_dropdown_item_1line, authors));

    AdapterView.OnItemClickListener onExistingAuthorClick = new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            author = (Author) parent.getAdapter().getItem(position);
            if (author == null) {
                return;
            }
            authorLastnameEdittext.setText(author.getLastname());
            authorFirstnameEdittext.setText(author.getFirstname());
            existingAuthor = true;
        }
    };

Please note this does not explain the previous NPE, so if you have ideas you're welcome!

VGM
  • 253
  • 4
  • 8
  • That is not what the stacktrace is telling. If authorFirstnameEditText was null, the stacktrace would have been "Exception java.lang.NullPointerException: Attempt to invoke virtual method 'setText()' on a null object reference" – VGM Aug 01 '16 at 15:23
  • What happens when you step through the code? Maybe `getLastname()` got sideways on a valid object and caused it to be freed. – alzee Aug 01 '16 at 15:24
  • Can it be that `author.getFirstname()` Returns null and the exception is because setter can not be called with null value? – Jens Aug 01 '16 at 15:25
  • `onItemClick` method has both `position` and `id` pointing to a current item clicked, so why are you iterating over all `Author`s? – pskink Aug 01 '16 at 15:31
  • @user3137702 getLastName() is juste a getter which gets the lastname of the Author, which is a String. I don't see any reasons why this would free the object – VGM Aug 01 '16 at 15:43
  • @jens No, in Android if you set a null value, it just sets an empty text (but I tried this on my device and I in fact had no problem with it) – VGM Aug 01 '16 at 15:43
  • I also asked what happens when you step through the code. What does the debugger/inspector say about the object? – alzee Aug 01 '16 at 15:50
  • @pskink I am looking for the matching authors in my database, I am not iterating on the list that is displayed. – VGM Aug 01 '16 at 15:50
  • @user3137702 Nothing unusual, because on my device I am not able to reproduce this crash. It only happens for a few number of users. Here is an example if you want : http://i.imgur.com/v4nwfbC.png – VGM Aug 01 '16 at 15:55
  • just call adapter.getItem, no need for iterating over all items – pskink Aug 01 '16 at 16:00
  • Maybe I misunderstood you, but there are two things : first, i get the text corresponding to the select item with String text = ((TextView) view).getText().toString(); Then I'm iterating through my database to find which author is matching this name. The author is not stocked in the adapter, so I can't get it from there. Anyway this does not explain the NPE :/ – VGM Aug 01 '16 at 16:09
  • ok did you know that you can use `new ArrayAdapter`? – pskink Aug 01 '16 at 16:25
  • Well obviously not. I made the modification with ArrayAdataper and the function is much cleaner now, so thank you for that! – VGM Aug 02 '16 at 09:34

2 Answers2

3

Because author.getLastname() is executed before the crash, it seems that author is != null, and at the next line it becomes null.

author is apparently an instance variable, and is set by author = a;.

It looks like another thread is modifying this variable. Without more information, I would recommend the following:

  • Look at other places where you modify this variable.
  • Question the reason for assigning the variable in this case.
  • Probably simply use a.getLastname() and a.getFirstname().

a is a local variable. It cannot be modified from the outside (the content of the object can change, not the reference to it), and therefore you are guaranteed that if a.getLastname() does not throw an NPE, subsequent a.getFirstname() won't either.

njzk2
  • 38,969
  • 7
  • 69
  • 107
  • Thank you for your answer. I'm going to do your modification, because indeed it should avoid the crash. But that still does not explain me why, and as a dev I like to understand why. I only have 5 users on 1K that have been affected until now, but it bothers me anyway. I only modify the author variable in the onViewCreated method (where I do initialize it) and nowhere else. After spending hours on it, I'm thinking of a problem due to the fact that Android is using a Handler in this method (visible in the stacktrace). But I can't figure out why it fails, and why only for few people... – VGM Aug 01 '16 at 16:19
  • `onItemClick` and `onViewCreated` are running both on the ui thread, so that should not explain the issue. I am not familiar with firebase, but I assume it tells you in which thread the exception occurred, and possibly what other threads are doing? – njzk2 Aug 01 '16 at 16:26
  • According to the stacktrace, the exception occured on the main thread (which is normal because onItemClick is running on this thread), and there is no mention of any other thread in Firebase (for this exception at least). This still does not explain the NPE, but I made the notification suggested by @pskink, replacing ArrayAdapter by ArrayAdapter. Way cleaner. – VGM Aug 02 '16 at 09:39
-1

Author.getFirstname()' on a null object reference - your Author object is null.

Oleg Skidan
  • 617
  • 6
  • 24
  • I know. But that does not help me to understand the problem. Like I said above : "The NPE says that at this line, the Author is null. Admit that this is true, the app should have crashed the line before, when doing : authorLastnameEdittext.setText(author.getLastname());" – VGM Aug 01 '16 at 15:16
  • You just need to initialize your `Author` object. Do you know how to do that? – Oleg Skidan Aug 01 '16 at 15:22
  • 1
    I appreciate your answers Oleg, but I'm not a beginner, therefore yes, I know what is a NPE and how to initialize and object :) You have to understand that my problem is that on one line, the object is NOT NULL, because author.getLastName() does not make the app crash. So here, everything seems to be ok. But on the next line, the author is null according to the stacktrace. And I don't know how that is possible (and why it occurs randomly for a very little amount of people) – VGM Aug 01 '16 at 15:39