1

我正在尝试使用 ArrayAdapter 获取 JSON 数据并将其显示在我的 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)

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

4

1 回答 1

3

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

这是通用图像加载器的设置类。我有一个实用程序包,这个类在这个包下。您可以通过在 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) {...}方法中。我的示例适配器是这样的。您可以忽略我的听众,这是因为我的每一行都有一个按钮。

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 个类似的活动,您需要复制/粘贴上面的代码。

希望它可以帮助你:)

于 2013-06-24T04:57:49.973 回答