My goal is to do drop down list while user input text using Google Places API, it works fine, but if user wont to remove the input text by holding backspace button, it will throw different exceptions.
Somethimes it:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.ViewGroup$LayoutParams android.view.View.getLayoutParams()' on a null object reference
at android.widget.PopupWindow.update(PopupWindow.java:1615)
at android.widget.PopupWindow.update(PopupWindow.java:1593)
at android.widget.ListPopupWindow.show(ListPopupWindow.java:609)
at android.widget.AutoCompleteTextView.showDropDown(AutoCompleteTextView.java:1105)
at android.widget.AutoCompleteTextView.updateDropDownForFilter(AutoCompleteTextView.java:974)
at android.widget.AutoCompleteTextView.access$900(AutoCompleteTextView.java:90)
at android.widget.AutoCompleteTextView$PopupDataSetObserver$1.run(AutoCompleteTextView.java:1299)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Somethimes it, this excpetion I catch, it does not affect on app :
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:3936)
at android.view.ViewGroup.addView(ViewGroup.java:3786)
at android.view.ViewGroup.addView(ViewGroup.java:3758)
at android.widget.PopupWindow.preparePopup(PopupWindow.java:1076)
at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:999)
at android.widget.ListPopupWindow.show(ListPopupWindow.java:639)
at android.widget.ListPopupWindow$PopupDataSetObserver.onChanged(ListPopupWindow.java:1757)
at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
at android.widget.ArrayAdapter.notifyDataSetChanged(ArrayAdapter.java:286)
at android.widget.ArrayAdapter.clear(ArrayAdapter.java:261)
at com.driveyello.yello.adapters.AutoPredictionAdapter$1.performFiltering(AutoPredictionAdapter.java:66)
at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.os.HandlerThread.run(HandlerThread.java:61)
This exceptions makes crash:
Process: com.driveyello.yello, PID: 25191
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.ViewGroup$LayoutParams android.view.View.getLayoutParams()' on a null object reference
at android.widget.PopupWindow.update(PopupWindow.java:1615)
at android.widget.PopupWindow.update(PopupWindow.java:1593)
at android.widget.ListPopupWindow.show(ListPopupWindow.java:609)
at android.widget.AutoCompleteTextView.showDropDown(AutoCompleteTextView.java:1105)
at android.widget.AutoCompleteTextView.setFrame(AutoCompleteTextView.java:1051)
at android.view.View.layout(View.java:15667)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.widget.ScrollView.onLayout(ScrollView.java:1502)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1076)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:1043)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15671)
at android.view.ViewGroup.layout(ViewGroup.java:5038)
at android.widget.Frame
Here is my adapter, AutoCompletePlace
it's a simple model that contains two string fields, getters/setters
public class AutoPredictionAdapter extends ArrayAdapter<AutoCompletePlace> {
private GoogleApiClient mGoogleApiClient;
public AutoPredictionAdapter(Context context) {
super(context, 0);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if( convertView == null ) {
holder = new ViewHolder();
convertView = LayoutInflater.from(getContext()).inflate( android.R.layout.simple_list_item_1, parent, false );
holder.text = (TextView) convertView.findViewById( android.R.id.text1 );
convertView.setTag( holder );
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(getItem(position).getDescription());
return convertView;
}
public void setGoogleApiClient(GoogleApiClient mGoogleApiClient) {
this.mGoogleApiClient = mGoogleApiClient;
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
if( mGoogleApiClient == null || !mGoogleApiClient.isConnected() ) {
Toast.makeText(getContext(), "Not connected", Toast.LENGTH_SHORT).show();
return null;
}
clear(); // here exceptions are thrown
displayPredictiveResults(constraint.toString());
return null;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
try {
notifyDataSetChanged(); // here exceptions are thrown
}catch (Exception e){
e.printStackTrace();
}
}
};
}
private void displayPredictiveResults(String query) {
//Southwest corner to Northeast corner.
final LatLngBounds bounds = new LatLngBounds( new LatLng( 39.906374, -105.122337 ), new LatLng( 39.949552, -105.068779 ) );
//Filter: https://developers.google.com/places/supported_types#table3
/*List<Integer> filterTypes = new ArrayList<>();
filterTypes.add( Place.TYPE_ESTABLISHMENT );*/
Places.GeoDataApi.getAutocompletePredictions( mGoogleApiClient, query, bounds, null )
.setResultCallback(
new ResultCallback<AutocompletePredictionBuffer>() {
@Override
public void onResult(AutocompletePredictionBuffer buffer) {
if (buffer == null)
return;
if (buffer.getStatus().isSuccess()) {
for (AutocompletePrediction prediction : buffer) {
try {
//Add as a new item to avoid IllegalArgumentsException when buffer is released
add(new AutoCompletePlace(prediction.getPlaceId(), prediction.getDescription()));
}catch (Exception e){
e.printStackTrace();
}
}
}
//Prevent memory leak by releasing buffer
buffer.release();
}
}, 60, TimeUnit.SECONDS);
}
private static class ViewHolder {
TextView text;
}
Here is how I configure auto prediction, I have two AutoCompleteTextView.
private void configureAutoPrediction(){
mPredictionAdapter = new AutoPredictionAdapter(getActivity());
mFirstAddressAutoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
AutoCompletePlace place = (AutoCompletePlace) parent.getItemAtPosition(position);
findPlaceById(place.getId(),FIRST_ADDRESS);
}
});
mSecondAddressAutoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
AutoCompletePlace place = (AutoCompletePlace) parent.getItemAtPosition(position);
findPlaceById(place.getId(),SECOND_ADDRESS);
}
});
mFirstAddressAutoCompleteTextView.setAdapter(mPredictionAdapter);
mSecondAddressAutoCompleteTextView.setAdapter(mPredictionAdapter);
}
private void findPlaceById( final String id, final int addressID ) {
if( TextUtils.isEmpty(id) || mGoogleApiClient == null || !mGoogleApiClient.isConnected())
return;
Places.GeoDataApi.getPlaceById(mGoogleApiClient, id).setResultCallback(new ResultCallback<PlaceBuffer>() {
@Override
public void onResult(PlaceBuffer places) {
if (places.getStatus().isSuccess()) {
Place place = places.get(0);
switch (addressID){
case FIRST_ADDRESS:
mFirstAddressAutoCompleteTextView.setText(place.getAddress());
break;
case SECOND_ADDRESS:
mSecondAddressAutoCompleteTextView.setText(place.getAddress());
break;
default: throw new IllegalArgumentException("Unknown address id");
}
mPredictionAdapter.clear();
}
//Release the PlaceBuffer to prevent a memory leak
places.release();
}
});
}