【问题标题】:Universal ImageLoader java.io.EOFException通用 ImageLoader java.io.EOFException
【发布时间】:2013-06-20 11:58:50
【问题描述】:

我正在尝试获取 JSON 数据并使用 ArrayAdapter 在我的 ListView 中显示它。无论如何,在我的适配器中,我正在使用来自https://github.com/nostra13/Android-Universal-Image-Loader 的通用图像加载器,并且除了图像之外的其他数据都已正确加载。有些图片显示正确,有些不应该在特定项目上,有些没有完全加载。

这是我的调用片段:

public class SampleFragment extends Fragment implements
    OnItemClickListener {

private ListView songsListView;
private ArrayList<String> list;
private ArrayAdapter<String> dataAdapter;
private View rootView;
private Button selectReferenceSong;
private Fragment memberFragment;
private String[] songsArray;
private ArrayAdapter<String> arrayAdapter;
private ArrayList<ReferenceTracks> arrayOfList;
private String bufferString;

private static final String rssFeed = "https://dl.dropboxusercontent.com/u/32769459/reference_tracks.json";

private static final String TAG_MUSIC = "music";
private static final String TAG_SONG = "song";
private static final String TAG_TITLE = "title";
private static final String TAG_ARTIST = "artist";
private static final String TAG_DURATION = "duration";
private static final String TAG_THUMBURL = "thumb_url";

public SampleFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    rootView = inflater.inflate(R.layout.sample_layout, container, false);

    songsListView = (ListView) rootView.findViewById(R.id.songsListView);
    songsListView.setOnItemClickListener(this);

    arrayOfList = new ArrayList<ReferenceTracks>();

    if (Utility.isNetworkAvailable(getActivity())) {
        new AsynchronousTask().execute(rssFeed);
    } else {
        Toast.makeText(getActivity().getApplicationContext(),
                "No Network Connection!", Toast.LENGTH_SHORT).show();
    }

    return rootView;
}

@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
    // TODO Auto-generated method stub

}

/**
 * 
 * @Asynchronous class
 */
public class AsynchronousTask extends AsyncTask<String, Void, String> {

    ProgressDialog pDialog;
    private RowAdapter objRowAdapter;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        pDialog = new ProgressDialog(getActivity());
        pDialog.setMessage("Loading...");
        pDialog.setCancelable(false);
        pDialog.show();
    }

    @Override
    protected String doInBackground(String... params) {
        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
        return Utility.getJSONString(params[0]);
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);

        if (null != pDialog && pDialog.isShowing()) {
            pDialog.dismiss();
        }

        if (null == result || result.length() == 0) {
            Toast.makeText(getActivity().getApplicationContext(),
                    "No data found from web.", Toast.LENGTH_SHORT).show();
        } else {

            try {
                JSONObject topObject = new JSONObject(result);
                JSONObject musicObject = topObject.getJSONObject(TAG_MUSIC);
                JSONArray jsonArray = musicObject.getJSONArray(TAG_SONG);
                for (int i = 0; i < jsonArray.length(); i++) {
                    JSONObject objJson = jsonArray.getJSONObject(i);

                    ReferenceTracks objItem = new ReferenceTracks();
                    objItem.setTitle(objJson.getString(TAG_TITLE));
                    objItem.setArtist(objJson.getString(TAG_ARTIST));
                    objItem.setDuration(objJson.getString(TAG_DURATION));
                    objItem.setThumbUrl(objJson.getString(TAG_THUMBURL));

                    arrayOfList.add(objItem);

                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

            setAdapterToListview();

        }

    }

    public void setAdapterToListview() {
        objRowAdapter = new RowAdapter(getActivity(), R.layout.reference_song_list_item, arrayOfList);
        songsListView.setAdapter(objRowAdapter);
    }
}}

这是我的自定义适配器:

public class RowAdapter extends ArrayAdapter<ReferenceTracks> {

private Context activity;
private ArrayList<ReferenceTracks> items;
private ReferenceTracks objBean;
private int row;
private ImageLoader imageLoader;
private DisplayImageOptions options;

public RowAdapter(Context act, int resource, ArrayList<ReferenceTracks> arrayList) {
    super(act, resource, arrayList);
    this.activity = act;
    this.row = resource;
    this.items = arrayList;
    imageLoader = ImageLoader.getInstance();
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    View view = convertView;
    ViewHolder holder;
    if (view == null) {
        LayoutInflater inflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(row, null);

        holder = new ViewHolder();
        view.setTag(holder);
    } else {
        holder = (ViewHolder) view.getTag();
    }

    if ((items == null) || ((position + 1) > items.size()))
        return view;

    objBean = items.get(position);

    holder.tvImage = (ImageView) view.findViewById(R.id.list_image);
    holder.tvTitle = (TextView) view.findViewById(R.id.title);
    holder.tvArtist = (TextView) view.findViewById(R.id.artist);
    holder.tvDuration = (TextView) view.findViewById(R.id.duration);
    holder.pbar = (ProgressBar) view.findViewById(R.id.progressbar);

    if (holder.tvImage != null) {
        if (null != objBean.getThumbUrl()
                && objBean.getThumbUrl().trim().length() > 0) {
            final ProgressBar pbar = holder.pbar;

            imageLoader.destroy();
            imageLoader.init(ImageLoaderConfiguration.createDefault(activity));
            imageLoader.displayImage(objBean.getThumbUrl(), holder.tvImage,
                    options, new ImageLoadingListener() {

                        @Override
                        public void onLoadingStarted(String imageUri,
                                View view) {
                            // TODO Auto-generated method stub
                            pbar.setVisibility(View.VISIBLE);
                        }

                        @Override
                        public void onLoadingFailed(String imageUri,
                                View view, FailReason failReason) {
                            // TODO Auto-generated method stub
                            pbar.setVisibility(View.INVISIBLE);
                        }

                        @Override
                        public void onLoadingComplete(String imageUri,
                                View view, Bitmap loadedImage) {
                            // TODO Auto-generated method stub
                            pbar.setVisibility(View.INVISIBLE);
                        }

                        @Override
                        public void onLoadingCancelled(String imageUri,
                                View view) {
                            // TODO Auto-generated method stub

                        }
                    });

        } else {
            holder.tvImage.setImageResource(R.drawable.ic_launcher);
        }
    }

    if (holder.tvTitle != null && null != objBean.getTitle()
            && objBean.getTitle().trim().length() > 0) {
        holder.tvTitle.setText(Html.fromHtml(objBean.getTitle()));
    }
    if (holder.tvArtist != null && null != objBean.getArtist()
            && objBean.getArtist().trim().length() > 0) {
        holder.tvArtist.setText(Html.fromHtml(objBean.getArtist()));
    }
    if (holder.tvDuration != null && null != objBean.getDuration()
            && objBean.getDuration().trim().length() > 0) {
        holder.tvDuration.setText(Html.fromHtml(objBean.getDuration()));
    }

    return view;
}

public class ViewHolder {
    public ImageView tvImage;
    public ProgressBar pbar;
    public TextView tvTitle, tvArtist, tvDuration;
}}

虽然这是我的应用程序类:

public class SampleApplication extends Application {

@Override
public void onCreate() {
    super.onCreate();

    DisplayImageOptions displayimageOptions = new DisplayImageOptions.Builder()
            .showStubImage(R.drawable.ic_stub)
            .showImageOnFail(R.drawable.ic_error)
            .showImageForEmptyUri(R.drawable.ic_empty)
            .cacheInMemory()
            .cacheOnDisc()
            .bitmapConfig(Bitmap.Config.RGB_565)
            .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
            .build();

    File cacheDir = StorageUtils.getCacheDirectory(getApplicationContext());

    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
    .threadPoolSize(4)
    .threadPriority(Thread.NORM_PRIORITY)
    .tasksProcessingOrder(QueueProcessingType.LIFO)
    .defaultDisplayImageOptions(displayimageOptions)
    .discCacheSize(50 * 1024 * 1024)
    .discCacheFileCount(1000000)
    .memoryCache(new WeakMemoryCache())
        .build();
    ImageLoader.getInstance().init(config);
}}

这也是日志:

    06-24 11:18:12.935: E/ImageLoader(6428): null
06-24 11:18:12.935: E/ImageLoader(6428): java.io.EOFException
06-24 11:18:12.935: E/ImageLoader(6428):    at libcore.io.Streams.readAsciiLine(Streams.java:203)
06-24 11:18:12.935: E/ImageLoader(6428):    at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:561)
06-24 11:18:12.935: E/ImageLoader(6428):    at libcore.net.http.HttpEngine.readResponse(HttpEngine.java:801)
06-24 11:18:12.935: E/ImageLoader(6428):    at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:274)
06-24 11:18:12.935: E/ImageLoader(6428):    at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:479)
06-24 11:18:12.935: E/ImageLoader(6428):    at com.nostra13.universalimageloader.core.download.BaseImageDownloader.getStreamFromNetwork(BaseImageDownloader.java:113)
06-24 11:18:12.935: E/ImageLoader(6428):    at com.nostra13.universalimageloader.core.download.BaseImageDownloader.getStream(BaseImageDownloader.java:84)
06-24 11:18:12.935: E/ImageLoader(6428):    at com.nostra13.universalimageloader.core.decode.BaseImageDecoder.getImageStream(BaseImageDecoder.java:84)
06-24 11:18:12.935: E/ImageLoader(6428):    at com.nostra13.universalimageloader.core.decode.BaseImageDecoder.decode(BaseImageDecoder.java:73)
06-24 11:18:12.935: E/ImageLoader(6428):    at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.decodeImage(LoadAndDisplayImageTask.java:290)
06-24 11:18:12.935: E/ImageLoader(6428):    at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryLoadBitmap(LoadAndDisplayImageTask.java:250)
06-24 11:18:12.935: E/ImageLoader(6428):    at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.run(LoadAndDisplayImageTask.java:131)
06-24 11:18:12.935: E/ImageLoader(6428):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
06-24 11:18:12.935: E/ImageLoader(6428):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
06-24 11:18:12.935: E/ImageLoader(6428):    at java.lang.Thread.run(Thread.java:856)

我在图像加载器的应用程序类上是否有任何设置错误或遗漏?我一直在寻找同样的例外,但似乎没有什么能接近修复。任何帮助都可以。非常感谢!

【问题讨论】:

    标签: android json android-listview android-arrayadapter universal-image-loader


    【解决方案1】:

    我长期使用通用图像加载器。所以,我更喜欢将它的设置放在一个类中,这样我的应用程序就可以简单地访问它。

    这是通用图像加载器的设置类。我有一个实用程序包,这个类在这个包下。您可以通过在 onLoadingComplete() 中注释掉线来制作图像曲线的角落。

    public class ImageDownloader {
    
        private static final  String TAG = "ImageDownloader";
        public static final String DIRECTORY_NAME = "YOUR_DIRECTORY_NAME";
    
        private static ImageDownloader instance = null;
        private ImageLoader imageLoader;
    
        protected ImageDownloader(Context context) {
            // Exists only to defeat instantiation.
            configImageDownloader(context);
        }
    
        public static ImageDownloader getInstance(Context context) {
            if(instance == null) {
                instance = new ImageDownloader(context);
            }
            return instance;
        }
    
        /**
         * This constructor will configure loader object in order to display image.
         * @param context
         */
        private void configImageDownloader(Context context) {
    
            File cacheDir = StorageUtils.getOwnCacheDirectory(context, DIRECTORY_NAME + "/Cache");
    
            // Get singleton instance of ImageLoader
            imageLoader = ImageLoader.getInstance();
    
            // Create configuration for ImageLoader (all options are optional)
            ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context).denyCacheImageMultipleSizesInMemory()
                    .memoryCache(new UsingFreqLimitedMemoryCache(4 * 1024 * 1024))
                    .discCache(new UnlimitedDiscCache(cacheDir))
                    .discCacheFileNameGenerator(new HashCodeFileNameGenerator())
                    .defaultDisplayImageOptions(
                            new DisplayImageOptions.Builder()
                                    .showStubImage(R.drawable.ic_default_logo)
                                    .resetViewBeforeLoading()
                                    .cacheInMemory()
                                    .cacheOnDisc()
                                    .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
                                    .build())
                    .tasksProcessingOrder(QueueProcessingType.FIFO)
                    .build();
    
            // Initialize ImageLoader with created configuration.
            imageLoader.init(config);
        }
    
    
        public void displayImage(final ImageView imageView, String imageURI) {
            if(imageView == null  ||  imageURI == null) {
                Log.e(TAG, "Either of image view or image uri is null");
                return;
            }
    
            // Load and display image
            imageLoader.displayImage(imageURI, imageView, new ImageLoadingListener() {
    
                @Override
                public void onLoadingStarted(String imageUri, View view) {}
    
                @Override
                public void onLoadingFailed(String imageUri, View view, FailReason failReason) {}
    
                @Override
                public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
    //                Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
    //                imageView.setImageBitmap(getRoundedCornerBitmap(bitmap, 30));
                }
    
                @Override
                public void onLoadingCancelled(String imageUri, View view) {}
            });
        }
    
        public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
            Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(output);
    
            final int color = 0xff424242;
            final Paint paint = new Paint();
            final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
            final RectF rectF = new RectF(rect);
            final float roundPx = pixels;
    
            paint.setAntiAlias(true);
            canvas.drawARGB(0, 0, 0, 0);
            paint.setColor(color);
            canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
    
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
            canvas.drawBitmap(bitmap, rect, rect, paint);
    
            return output;
        }
    }
    

    在您的适配器类中,首先您需要将所有定义移至if (view == null) {...}method。我的示例适配器是这样的。你可以忽略我的听众,因为我的每一行都有一个按钮。

    public class MyCrowdAdapter extends BaseAdapter {
    
        public interface OnCrowdRemoveUserListener {
            public void OnRemoveUserClicked(User user);
        }
    
        private final String TAG = "*** MyCrowdAdapter ***";
    
        private Context context;
        private OnCrowdRemoveUserListener listener;
        private LayoutInflater myInflater;
        private ImageDownloader imageDownloader;
        private List<User> userList;
    
        public MyCrowdAdapter(Context context) {
            this.context = context;
            myInflater = LayoutInflater.from(context);
    
            imageDownloader = ImageDownloader.getInstance(context);
        }
    
        public void setData(List<User> userList) {
            this.userList = userList;
    
            Log.i(TAG, "List passed to the adapter.");
        }
    
        @Override
        public int getCount() {
            try {
                return userList.size();
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    
        @Override
        public Object getItem(int position) {
            return null;
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
    
            if (convertView == null) {
                convertView = myInflater.inflate(R.layout.list_my_crowd_row, null);
                holder = new ViewHolder();
    
                Typeface font = Typeface.createFromAsset(context.getAssets(), "fonts/ITCAvantGardeStd-Demi.ttf");
                holder.tvUserName = (TextView) convertView.findViewById(R.id.tvUserName);
                holder.tvUserName.setTypeface(font);
                holder.ivPicture = (ImageView) convertView.findViewById(R.id.ivPicture);
                holder.btnRemove = (Button) convertView.findViewById(R.id.btnRemove);
                holder.btnRemove.setFocusable(false);
                holder.btnRemove.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Integer pos = (Integer)v.getTag();
                        Log.i(TAG, "Item: " + pos);
                        listener.OnRemoveUserClicked(userList.get(pos));
                    }
                });
    
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
    
            holder.btnRemove.setTag(position);
            holder.tvUserName.setText(userList.get(position).getFirstName());
            imageDownloader.displayImage(holder.ivPicture, userList.get(position).getProfilePictureUrl());
    
            return convertView;
        }
    
        public void setOnRemoveClickedListener(OnCrowdRemoveUserListener listener) {
            this.listener = listener;
        }
    
        static class ViewHolder {
            TextView tvUserName;
            ImageView ivPicture;
            Button btnRemove;
        }
    }
    

    一个建议,而不是像这样的验证: if (holder.tvTitle != null && null != objBean.getTitle() && objBean.getTitle().trim().length() > 0) {...} 只需使用静态方法TextUtils,如下所示: if(!TextUtils.isEmpty(objBean.getTitle);

    ============

    更新

    ============

    关于在图像顶部显示进度条的问题: 它既简单又复杂:)有两种方法, 第一种方式是基于您的代码: 1-在 ImageDownloader 类中定义一个接口,就像我在适配器中的接口一样。应该是这样的:

    public interface OnImageDownloaderListener {
        public void OnDownloadStarted();
        public void OnDownloadFinished();
    }
    

    2- 在声明部分声明它

    OnImageDownloaderListener listener;
    

    3- 像这样改变两个听众

    @Override
                public void onLoadingStarted(String imageUri, View view) {
            listener.OnDownloadStarted();
    }
    
                @Override
                public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
    //                Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
    //                imageView.setImageBitmap(getRoundedCornerBitmap(bitmap, 30));
            listener.OnDownloadFinished();
                }
    

    4- 将此方法添加到 ImageDownloader 类中

    public void setOnImageDownloaderListener(OnImageDownloaderListener listener) {
            this.listener = listener;
        }
    

    5- 在您的适配器中并在此行下方:

    imageDownloader = ImageDownloader.getInstance(context); 
    

    像这样实现这两种方法:

    imageDownloader.setOnImageDownloaderListener(new ImageDownloader.OnImageDownloaderListener{
        @Override
        public void OnDownloadStarted() {
            pbar.start();
        }
    
        @Override
        public void OnDownloadFinished(){
            pbar.stop();
        }
    }
    );
    

    它应该可以帮助你。但是,如果我是你,我会采用第二种方法,即创建新组件。该组件包括两个视图,一个图像视图和顶部的进度条(与您当前拥有的相同)。然后在该组件类中添加上述所有方法。因此,通过您的应用程序,您可以轻松地在任何您想要的活动中添加视图并传递 URL,然后组件负责显示进度条并停止它。根据您的代码,如果您有 10 个类似的活动,您需要复制/粘贴以上代码。

    希望对你有帮助:)

    【讨论】:

    • 哇!有效!我在我的应用程序类及其 displayImage 方法中使用了您的 ImageDownloader 类。另外,我喜欢圆角!非常感谢。但我很好奇是什么让我的设置不起作用?是缓存吗?
    • 我记得当我开始在我的第一个应用程序中将此库集成到我的应用程序中时,我遇到了类似的问题。现在,我在我的第四个应用程序中使用它,这是迄今为止最优化的一个。关于设置我不知道! :(
    • 我明白了,这也是我第一个使用 UIL 的应用程序,所以我不确定要使用哪种最佳设置。真的很感谢这个!顺便说一句,我如何调用 displayImage 的侦听器?我想将它用于我的进度条。
    • 我没明白你的意思?您的对话框进度条还是图像顶部有进度条?
    • 我在图像顶部和之前的适配器(请参阅我的代码)中有一个进度条,声明为 pbar,我在其中操纵其在 onLoadingStarted、onLoadingFailed 和 onLoadingComplete 的可见性。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-10
    • 2018-06-14
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    • 2018-06-18
    相关资源
    最近更新 更多