简体   繁体   中英

App is crashing on scrolling of list

In my app I am displaying map and list of items. I am using google place api to fetch nearest places and showing on map as markers having name and vicinity and as well as list. Here is my code

GooglePlacesActivity.java

import android.app.ActionBar;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

import java.io.IOException;
import java.util.List;


public class GooglePlacesActivity extends FragmentActivity implements LocationListener, GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener{

    GoogleMap mMap;
    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;
    private double latitude;
    private double longitude;

    List<Place> placeList;

    ListView listView;

    PlaceAdapter mPlaceAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_google_places);

        ActionBar actionBar = getActionBar();
        actionBar.show();

        mGoogleApiClient = new GoogleApiClient.Builder(this).
                addApi(LocationServices.API).
                addConnectionCallbacks(this).
                addOnConnectionFailedListener(this).
                build();

        actionBar.setCustomView(R.layout.search_actionbar);
        final EditText search = (EditText) actionBar.getCustomView().findViewById(R.id.searchField);

        listView = (ListView) findViewById(R.id.list_item);

        search.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                String value = search.getText().toString();
                StringBuilder googlePlacesUrl = new StringBuilder("https://maps.googleapis.com/maps/api/place/search/json?");
                googlePlacesUrl.append("location=" + latitude + "," + longitude);
                googlePlacesUrl.append("&radius=" + 1000);
                googlePlacesUrl.append("&types=" + value);
                googlePlacesUrl.append("&key=" + API_KEY);

                GooglePlacesTask googlePlacesTask = new GooglePlacesTask();
                googlePlacesTask.execute(googlePlacesUrl.toString());

                return false;
            }
        });

        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME);

        if (mMap == null){
            mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.googleMap)).getMap();
            mMap.setMyLocationEnabled(true);
        }
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_google_places, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }


    @Override
    protected void onStart() {
        super.onStart();
        mGoogleApiClient.connect();
    }

    @Override
    protected void onStop() {
        mGoogleApiClient.disconnect();
        super.onStop();
    }

    @Override
    public void onConnected(Bundle bundle) {
        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(1000*60);

        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);

    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {

    }

    @Override
    public void onLocationChanged(Location location) {
        latitude = location.getLatitude();
        longitude = location.getLongitude();
        LatLng latLng = new LatLng(latitude, longitude);
        mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
        mMap.animateCamera(CameraUpdateFactory.zoomTo(12));
    }

    private class GooglePlacesTask extends AsyncTask<String, Void, String>{
        String data;

        @Override
        protected String doInBackground(String... params) {
            try{
                data = Http.read(params[0]);
                Log.d("DATA", data);
            }catch (IOException e){
                e.printStackTrace();
            }

            return data;
        }

        @Override
        protected void onPostExecute(String result) {

            placeList = ParseJson.parsedata(result);

            for (Place place : placeList){
                Log.d("Latitude", String.valueOf(place.getLatitude()));
                Log.d("Longitude", String.valueOf(place.getLongitude()));
                Log.d("Name", place.getName());
                Log.d("Vicinity", place.getVicinity());

            }

            for (int i = 0; i < placeList.size(); i++) {
                mMap.addMarker(new MarkerOptions()
                        .title(placeList.get(i).getName())
                        .position(
                                new LatLng(placeList.get(i).getLatitude(), placeList
                                        .get(i).getLongitude()))
                        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN))
                        .snippet(placeList.get(i).getVicinity()));
            }
            CameraPosition cameraPosition = new CameraPosition.Builder()
                    .target(new LatLng(placeList.get(0).getLatitude(), placeList
                            .get(0).getLongitude())) // Sets the center of the map to
                            // Mountain View
                    .zoom(14) // Sets the zoom
                    .tilt(30) // Sets the tilt of the camera to 30 degrees
                    .build(); // Creates a CameraPosition from the builder
            mMap.animateCamera(CameraUpdateFactory
                    .newCameraPosition(cameraPosition));

            mPlaceAdapter = new PlaceAdapter(GooglePlacesActivity.this, placeList);
            mPlaceAdapter.notifyDataSetChanged();
            listView.setAdapter(mPlaceAdapter);
        }
    }
}

PlaceAdapter.java

package com.aquib.android.placefinder;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import java.util.List;


/**
 * Created by dell on 2/19/2015.
 */
public class PlaceAdapter extends ArrayAdapter<Place>{

    private final List<Place> list;
    private final Context context;

    public PlaceAdapter(Context context, List<Place> list){
        super(context, R.layout.place_list, list);
        this.context = context;
        this.list = list;
    }

    static class ViewHolder{
        protected TextView text;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        View view = null;
        ViewHolder viewHolder;

        if (convertView == null){
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.place_list, parent, false);
            viewHolder = new ViewHolder();
            viewHolder.text = (TextView) view.findViewById(R.id.placeName);
            view.setTag(viewHolder);
        }

        else {
            viewHolder = (ViewHolder) view.getTag();
        }

        viewHolder.text.setText(list.get(position).getName());
        return view;
    }
}

when i scroll my list, app is crashing and generating NullPointerException.

And this error is generating

java.lang.NullPointerException
            at com.aquib.android.placefinder.PlaceAdapter.getView(PlaceAdapter.java:46)
            at android.widget.AbsListView.obtainView(AbsListView.java:2255)
            at android.widget.ListView.makeAndAddView(ListView.java:1790)
            at android.widget.ListView.fillDown(ListView.java:691)
            at android.widget.ListView.fillGap(ListView.java:655)
            at android.widget.AbsListView.trackMotionScroll(AbsListView.java:5143)
            at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:3243)
            at android.widget.AbsListView.onTouchMove(AbsListView.java:3587)
            at android.widget.AbsListView.onTouchEvent(AbsListView.java:3431)
            at android.view.View.dispatchTouchEvent(View.java:7706)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2210)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1945)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2068)
            at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1515)
            at android.app.Activity.dispatchTouchEvent(Activity.java:2458)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2016)
            at android.view.View.dispatchPointerEvent(View.java:7886)
            at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3947)
            at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3826)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3392)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3442)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3411)
            at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3518)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3419)
            at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3575)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3392)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3442)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3411)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3419)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3392)
            at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5532)
            at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5512)
            at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5483)
            at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5612)
            at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
            at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
            at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:176)
            at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:5585)
            at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:5631)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
            at android.view.Choreographer.doCallbacks(Choreographer.java:574)
            at android.view.Choreographer.doFrame(Choreographer.java:542)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographe.

This happens because when you scrolling your list getView() method is getting called. Now yor view is null so its showing ANR

to overcome on this situation you should do this

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    //View view = null;
    ViewHolder viewHolder;

    if (convertView == null){
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView= inflater.inflate(R.layout.place_list, parent, false);
        viewHolder = new ViewHolder();
        viewHolder.text = (TextView) view.findViewById(R.id.placeName);
        convertView.setTag(viewHolder);
    }

    else {
        viewHolder = (ViewHolder) convertView.getTag();
    }

    viewHolder.text.setText(list.get(position).getName());
    return convertView;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM