3

Some users are reporting this error:

java.lang.NullPointerException
at android.widget.ArrayAdapter.getCount(ArrayAdapter.java:291)
at android.widget.AutoCompleteTextView$PopupDataSetObserver$1.run(AutoCompleteTextView.java:1670)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)

Here is my code snippet:

    private List<City> autoCompleteCities = new ArrayList<City>();
    private List<City> autoCompleteCitiesOld = new ArrayList<City>();
    private ArrayAdapter<String> autoCompleteAdapter;
    private AutoCompleteTextView cityView;

    ...

    autoCompleteAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line);
    autoCompleteAdapter.setNotifyOnChange(true);

    cityView = (AutoCompleteTextView) findViewById(R.id.city);      

    cityView.setAdapter(autoCompleteAdapter);
    cityView.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            LogUtil.i("!!!!!!!!!!!!! ontextchanged", s.toString());
            autoCompleteAdapter.clear();
            autoCompleteCitiesOld = autoCompleteCities;
            if (s.toString().length() > 2) {
                autoCompleteCities = search(s.toString());
                for (City city : autoCompleteCities) {
                    autoCompleteAdapter.add(city.getDisplayName());
                }
            }
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void afterTextChanged(Editable s) {
        }
    });

It doesnt happen for me, but I have enough error reports to know it happens for several users. Any idea what is wrong? Why does this happen to only a handful of users?

I found this post but putting the fetching of new autocomplete values in an AsyncTask meant that the results always were one character behind what the user had entered.

Community
  • 1
  • 1
timothyjc
  • 2,188
  • 3
  • 29
  • 54
  • That exception would happen if the list data that is backing the adapter is made null at some point. When the adapter is first initialized(even when it's done only with the layouts file like in your code) an empty list is assigned so you must be doing something at a later time that makes the list `null`(if you only use the `add` method that shouldn't happen). Also your use of the `AutoCompleteTextView`(the way you modify the adapter) is not quite the proper way. – user Jan 12 '13 at 13:20
  • What is the proper way? I have no references to the autoCompleteAdapter besides what is shown in the code above... – timothyjc Jan 12 '13 at 18:44
  • 1
    The proper way would be to do the auto complete by implementing your own filter in the adapter(as the `AutocompleteTextView` is using the filter to get the suggestions). There is no point in re-setting the adapter's data each time the user modifies the text in the `AutoCompleteTextView` if the full list of values(or cities) doesn't modify between searches. – user Jan 13 '13 at 09:56
  • 1
    If I add all the cities at once to the adapter then filter them it takes too long as there are something like 100,000 cities. This is why it needs to be updated dynamically... – timothyjc Jan 13 '13 at 14:10
  • 1
    I didn't say to add all the cities at once(as an `AutoCompleteTextview` will show suggestions only when you insert characters in it(this actually calls the `getFilter` method of the adapter)), you just need to move what you currently do in the `Filter` implementation of the custom adapter(you also get a background thread so there aren't any problems). – user Jan 13 '13 at 14:21
  • [This](https://developers.google.com/places/training/autocomplete-android) tutorial explains how to implement what @Luksprog said. That tutorial wants you to create a [custom ArrayAdapter](http://sogacity.com/how-to-make-a-custom-arrayadapter-for-listview/), which also provides a more elegant solution to use custom classes in lists. – Niklas Ekman Jan 16 '13 at 16:14
  • @timothyjc Can you please post your search(String s) method. actually I am working on AutoComplete Prob. – Ashish Dwivedi Jan 17 '13 at 10:02
  • You are implementing AutocompleteTextView in wrong way. as @Luksprog said in the comment, AutoCompleteTextView should takes array at initial and then using filter you can filter data as you want. – Dharmendra Jan 17 '13 at 12:23
  • this happens on ice cream sandwich but works fine on later versions of android – user1159819 Mar 12 '14 at 20:08

5 Answers5

1

Where are you passing the ArrayList to the ArrayAdapter. The NullPointerException throws while counting the list lenght in ArrayAdapter. But the list is not passed to Adapter, so the list object in default Adapter contains null.

knvarma
  • 974
  • 5
  • 6
  • I dont actually have an ArrayList, but rather add the city names directly into the adapter. Are you saying I need to add something like this: ArrayList cities = new ArrayList(); autoCompleteAdapter = new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, cities); – timothyjc Oct 07 '12 at 21:14
0

My hypothesis is that you are somewhere using static variables which are nulled after activity recreation. See my answer here: Public static variables and Android activity life cycle management

create android v.4 emulator, go to developer's settings, disable background tasks, disable multiple activities and then try to use your application - chances are it will fail.

Community
  • 1
  • 1
agamov
  • 4,407
  • 1
  • 27
  • 31
0

Where did u have added the array of String ,the reason of error may be the empty array list as: autoCompleteAdapter = new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line);

here u hav'nt assign any string array

And enter your full code it will help lot to the people to understand the problem

GOLDEE
  • 2,318
  • 3
  • 25
  • 49
0

Better do null check before using object like below and do it in search function also..

 if (s.toString().length() > 2) {
     autoCompleteCities = search(s.toString());
     if(autoCompeleteCities!=null){     
         for (City city : autoCompleteCities) {
              autoCompleteAdapter.add(city.getDisplayName());
         }
       }

Jitendra
  • 1,107
  • 2
  • 12
  • 22
0

I had exactly the same problem with the same issue. In my case I have thousands of streets I dynamically add and remove from the list. In my case it was always reproducable when I enter some value into the AutoComplete field, let's say 3 characters (while threshold is set to 0), so the dropdown list appears, and then I delete those characters by delete button very quickly. That means I hit the delete button a lot of times. It always crashes then. I figured out that clear causes the crashes. I put the clear in beforeTextChanged and the crashes were gone:

public class StreetTextWatcher implements TextWatcher {

    private final StreetArrayAdapter adapter;
    private boolean alreadyAdded = false;

    public StreetTextWatcher(StreetArrayAdapter adapter) {
        this.adapter = adapter;
    }

    @Override
    public void afterTextChanged(Editable s) {
        //not used
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        if (s.length() < 1)  {
            adapter.clear();

            alreadyAdded = false;
        }
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {           
        if (s.length() == 1) {
            if (s.toString().toLowerCase(Locale.GERMAN).startsWith("a") && !alreadyAdded)  {
                adapter.addAll(StreetNames.STREETS_A);
                alreadyAdded = true;
            }

            if (s.toString().toLowerCase(Locale.GERMAN).startsWith("b") && !alreadyAdded)  {
                adapter.addAll(StreetNames.STREETS_B);
                alreadyAdded = true;
            }

            //more streets...
        }
    }
}

StreetArrayAdapter:

public class StreetArrayAdapter extends ArrayAdapter<String> {

    public StreetArrayAdapter(Context context, int textViewResourceId) {
        super(context, textViewResourceId);
    }

    public void addAll(String[] streets) {
        for (String street : streets) {
            add(street);
        }
    }
}
Bevor
  • 8,396
  • 15
  • 77
  • 141