android - 使用 Picasso 在滚动列表中加载图像时崩溃应用程序

标签 android android-listview picasso

我一直在使用 Picasso 用返回图像的 URL 填充 listview。这些 URL 是从 API 调用返回的。

适配器

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 position;
    }

    @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");

                    String[] imagearray = image.split("\\.");
                    String extension = imagearray[imagearray.length - 1];

                    String tag = new String();

                    if (extension.equals("jpg")) {
                        if (URLUtil.isValidUrl(image)) {
                            Picasso.with(activity)
                                    .load(image)
                                    .centerCrop()
                                    .tag(tag)
                                    .error(R.drawable.icon01)
                                    .resize(50, 50)
                                    .into(icon);

                        } else {
                            Picasso.with(activity)
                                    .load(R.drawable.icon01)
                                    .centerCrop()
                                    .resize(50, 50)
                                    .tag(tag)
                                    .into(icon);

                        }

                    }
                }
            } catch (JSONException e) {

                Toast.makeText(activity, "Error finding recipes",
                        Toast.LENGTH_SHORT).show();
                e.printStackTrace();
            }

        }
       final ImageView fav = (ImageView)v.findViewById(R.id.favbutton);
        fav.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                fav.setImageResource(R.drawable.ic_favorite_white_24dp);
                Toast.makeText(activity, "Added to favourites",
                        Toast.LENGTH_SHORT).show();
            }
        });

        return v;
    }


}

我已经阅读了很多相关资料,并且尝试使用 .tag() 方法和滚动监听器:

  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);

                }
            });
           final String tag ="";
            recipes.setOnScrollListener(new AbsListView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(AbsListView view, int scrollState) {


                    Picasso picasso = Picasso.with(getApplicationContext());
                    if (scrollState == SCROLL_STATE_IDLE ||
                            scrollState == SCROLL_STATE_TOUCH_SCROLL) {
                        picasso.resumeTag(tag);
                    } else {
                        picasso.pauseTag(tag);
                    }
                }

                @Override
                public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

                    Picasso picasso = Picasso.with(getApplicationContext());
                    picasso.pauseTag(tag);
                }
            });

            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();
    }
}

虽然这可能会解决问题,但是当我在大列表上滚动时,它会导致应用程序崩溃。登录目录:

   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:99)
            at android.widget.AbsListView.obtainView(AbsListView.java:2347)
            at android.widget.ListView.makeAndAddView(ListView.java:1864)
            at android.widget.ListView.fillUp(ListView.java:732)
            at android.widget.ListView.fillGap(ListView.java:671)
            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

欢迎任何帮助或建议

最佳答案

经过大量调试,弄明白了。

我使用的库试图在未正确加载时对 CircularImageView 资源使用方法。更改为不同的库,现在可以完美运行。

关于android - 使用 Picasso 在滚动列表中加载图像时崩溃应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32684120/

相关文章:

android - 如何在Android中获取图像的大小?

android - Android 中的持久/离线图像缓存

java - Picasso Android 内存问题,当 fragment 被替换时

java - 为 BLE 秤编写应用程序代码 - 包含所有信息

android - 从 Android 上的相机录制视频到 mp4

android - 无法在 genymotion 设备上安装我的 Android 应用程序

android - 如何从 xml 获取垂直按钮 View

android - 为自定义 ListView 创建搜索 View

android - 适配器的内容已经改变但是ListView没有收到通知

android picasso 清除缓存