jmo
jmo

Reputation: 357

ListView crashes on scroll Android

I have a ListView that is populated by a JSONArray. The data loads, but when I attempt to scroll, it crashes

Logcat:

09-19 11:50:53.512  15110-15110/io.moffat.kitchenpal E/InputEventReceiver﹕ Exception dispatching input event.
09-19 11:50:53.513  15110-15110/io.moffat.kitchenpal E/MessageQueue-JNI﹕ Exception in MessageQueue callback: handleReceiveCallback
09-19 11:50:53.514  15110-15110/io.moffat.kitchenpal E/MessageQueue-JNI﹕ java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
            at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:591)
            at com.pkmmte.view.CircularImageView.refreshBitmapShader(CircularImageView.java:341)
            at com.pkmmte.view.CircularImageView.invalidate(CircularImageView.java:262)
            at android.widget.ImageView.setImageDrawable(ImageView.java:456)
            at com.squareup.picasso.PicassoDrawable.setPlaceholder(PicassoDrawable.java:61)
            at com.squareup.picasso.RequestCreator.into(RequestCreator.java:664)
            at com.squareup.picasso.RequestCreator.into(RequestCreator.java:601)
            at io.moffat.kitchenpal.RecipeAdapter.getView(RecipeAdapter.java:87)
            at android.widget.AbsListView.obtainView(AbsListView.java:2347)
            at android.widget.ListView.makeAndAddView(ListView.java:1864)
            at android.widget.ListView.fillDown(ListView.java:698)
            at android.widget.ListView.fillGap(ListView.java:662)
            at android.widget.AbsListView.trackMotionScroll(AbsListView.java:4991)
            at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:3418)
            at android.widget.AbsListView.onTouchMove(AbsListView.java:3801)
            at android.widget.AbsListView.onTouchEvent(AbsListView.java:3632)
            at android.view.View.dispatchTouchEvent(View.java:8471)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2399)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2092)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2405)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2106)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2405)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2106)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2405)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2106)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2405)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2106)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2405)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2106)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2405)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2106)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2369)
            at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1719)
            at android.app.Activity.dispatchTouchEvent(Activity.java:2742)
            at android.support.v7.internal.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:59)
            at android.support.v7.internal.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:59)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2330)
            at android.view.View.dispatchPointerEvent(View.java:8666)
            at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4123)
            at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3989)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3544)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3597)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3563)
            at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3680)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3571)
            at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3737)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3544)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3597)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3563)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3571)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3544)
            at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5807)
            at android.view.ViewRootImpl.doPr
09-19 11:50:53.516  15110-15110/io.moffat.kitchenpal E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: io.moffat.kitchenpal, PID: 15110
    java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
            at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:591)
            at com.pkmmte.view.CircularImageView.refreshBitmapShader(CircularImageView.java:341)
            at com.pkmmte.view.CircularImageView.invalidate(CircularImageView.java:262)
            at android.widget.ImageView.setImageDrawable(ImageView.java:456)
            at com.squareup.picasso.PicassoDrawable.setPlaceholder(PicassoDrawable.java:61)
            at com.squareup.picasso.RequestCreator.into(RequestCreator.java:664)
            at com.squareup.picasso.RequestCreator.into(RequestCreator.java:601)
            at io.moffat.kitchenpal.RecipeAdapter.getView(RecipeAdapter.java:87)
            at android.widget.AbsListView.obtainView(AbsListView.java:2347)
            at android.widget.ListView.makeAndAddView(ListView.java:1864)
            at android.widget.ListView.fillDown(ListView.java:698)
            at android.widget.ListView.fillGap(ListView.java:662)
            at android.widget.AbsListView.trackMotionScroll(AbsListView.java:4991)
            at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:3418)
            at android.widget.AbsListView.onTouchMove(AbsListView.java:3801)
            at android.widget.AbsListView.onTouchEvent(AbsListView.java:3632)
            at android.view.View.dispatchTouchEvent(View.java:8471)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2399)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2092)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2405)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2106)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2405)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2106)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2405)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2106)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2405)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2106)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2405)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2106)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2405)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2106)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2369)
            at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1719)
            at android.app.Activity.dispatchTouchEvent(Activity.java:2742)
            at android.support.v7.internal.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:59)
            at android.support.v7.internal.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:59)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2330)
            at android.view.View.dispatchPointerEvent(View.java:8666)
            at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4123)
            at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3989)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3544)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3597)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3563)
            at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3680)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3571)
            at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3737)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3544)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3597)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3563)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3571)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3544)
            at android.view.ViewRootImpl.deliverInputEv

Activity with the Listview

class Populate extends AsyncTask<String, String, JSONArray> {

        protected void onPreExecute() {
            progress = ProgressDialog.show(RecipeSearch.this, "Finding Recipes", "Searching....", true);
        }

        @Override
        protected JSONArray doInBackground(String... urls) {
            JSONParser recipeParse = new JSONParser();
            String rawJSON = recipeParse.getJSON(urls[0]);

            try {

                if (rawJSON != null) {
                    JSONObject object = new JSONObject(rawJSON);
                    JSONArray jArray = object.getJSONArray("recipes");
                    return jArray;
                } else {
                    JSONArray jArray = null;
                    return jArray;
                }

            } catch(Exception e) {
                System.out.println(e);
                Toast.makeText(getApplicationContext(), "Error Searching for Recipes",
                        Toast.LENGTH_SHORT).show();

             JSONArray jArray = null;
                return jArray;
            }
            //do http request and add objects to array here.
            //need to do a custom adapter
           // return null;
        }

        @Override
        protected void onPostExecute(JSONArray jArray) {

            if (jArray != null) {
                final ListView recipes = (ListView) findViewById(R.id.recipeView);

                recipes.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                        JSONObject selected = (JSONObject) (recipes.getItemAtPosition(position));

                        String url = null;
                        try {
                            url = selected.getString("source_url");
                        } catch (JSONException e) {
                            e.printStackTrace();
                            Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_SHORT).show();
                        }
                        Intent i = new Intent(Intent.ACTION_VIEW);
                        i.setData(Uri.parse(url));
                        startActivity(i);

                    }
                });

                recipeAdapter = new RecipeAdapter(RecipeSearch.this, jArray);//jArray is your json array
                recipes.setAdapter(recipeAdapter);

            } else {
                Toast.makeText(getApplicationContext(), "No Recipes Found", Toast.LENGTH_SHORT).show();
                finish();
            }
            progress.dismiss();
        }
    }

Adapter

public class RecipeAdapter extends BaseAdapter implements ListAdapter {


    private final Activity activity;
    private final JSONArray jsonArray;


    public RecipeAdapter (Activity activity, JSONArray jsonArray){
        assert activity !=null;
        assert jsonArray != null;

        this.jsonArray = jsonArray;
        this.activity = activity;

    }

    @Override
    public int getCount(){
        if(null==jsonArray)
            return 0;
        else
            return jsonArray.length();
    }

    @Override
    public JSONObject getItem(int position){
        if(null==jsonArray) return null;
        else
        return jsonArray.optJSONObject(position);
    }

    @Override
    public long getItemId(int position){

        return 0;
    }

    @Override
    public View getView (int position, View v, ViewGroup parent){
        if (v == null) {
            v = View.inflate(activity, R.layout.recipe_item, null);
        }

        CircularImageView icon = (CircularImageView)v.findViewById(R.id.recipeIcon);
        TextView title = (TextView) v.findViewById(R.id.recipeTitle);
        TextView supplier = (TextView) v.findViewById(R.id.supplier);


        JSONObject JSdata = getItem(position);
        if(null!=JSdata){
            try {
                if (JSdata.has("title")) {
                    title.setText(JSdata.getString("title"));
                }
                if (JSdata.has("publisher")) {
                    supplier.setText(JSdata.getString("publisher"));
                }
                if (JSdata.has("image_url")){
                    String image = JSdata.getString("image_url");
                if (image != null) {
                    Picasso.with(activity)
                            .load(image)
                            .centerCrop()
                            .resize(50, 50)
                            .into(icon);
                }
                } else {
                    Toast.makeText(activity, "Image not loaded",
                            Toast.LENGTH_SHORT).show();
                }
            } catch (JSONException e) {

                e.printStackTrace();
            }

        }
        ImageView fav = (ImageView)v.findViewById(R.id.favbutton);
        fav.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(activity, "Fav",
                        Toast.LENGTH_SHORT).show();
            }
        });

        return v;
    }


}

I can't figure out why it's crashing. I assumed it was a JSON error based on similar questions, so I put in conditional checks to make sure that the JSONObject had the fields I was looking for.

Upvotes: 0

Views: 454

Answers (1)

2hamed
2hamed

Reputation: 9047

It's actually not a JSONException. As you can see in Logs there is null reference to a Bitmap which upon calling getWidth throws an exception.

The only place I can see this can occur is in the following line:

Picasso.with(activity)
       .load(image)
       .centerCrop()
       .resize(50, 50)
       .into(icon);

You should check if you're feeding a valid url to Picasso cause if not, Picasso will throw an exception.

Upvotes: 1

Related Questions