Android将图像从URL加载到自定义列表视图适配器而不使用Picasso

时间:2016-05-29 04:29:05

标签: android listview custom-adapter

我正在尝试从网址加载图片而我已经使用过Picasso,但是如果可能的话,我想知道如何在没有外部库的情况下执行此操作。我知道我必须得到一个Asynctask,但我不确定如何实现它。

这是我的getview代码

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

    View row = convertView;
    if(position==0){

        NewsObj currNews = news.get(position);
        DataHandler dh;
        if(convertView==null){
            LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.firstnews,parent,false);
            dh = new DataHandler();
            dh.newsTitle = (TextView)row.findViewById(R.id.newsTitle);
            dh.newsDate = (TextView)row.findViewById(R.id.newsDate);
            dh.newsIcon = (ImageView)row.findViewById(R.id.newsIcon);
            row.setTag(dh);
        }else{
            dh = (DataHandler)row.getTag();
        }
        NewsObj no = (NewsObj)this.getItem(position);
        new AsyncDownloadTask().execute(row,no.getImgurl());
        dh.newsTitle.setText(no.getTitle());
        dh.newsDate.setText(no.getDate());

    }else{

        NewsObj currNews = news.get(position);
        DataHandler dh;
        if(convertView==null){
            LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.newslist,parent,false);
            dh = new DataHandler();
            dh.newsTitle = (TextView)row.findViewById(R.id.newsTitle);
            dh.newsDate = (TextView)row.findViewById(R.id.newsDate);
            dh.newsIcon = (ImageView)row.findViewById(R.id.newsIcon);
            row.setTag(dh);
        }else{
            dh = (DataHandler)row.getTag();
        }
        NewsObj no = (NewsObj)this.getItem(position);
        new AsyncDownloadTask().execute(row,no.getImgurl());

        dh.newsTitle.setText(no.getTitle());
        dh.newsDate.setText(no.getDate());

    }
    return row;
}


 private class AsyncDownloadTask extends AsyncTask<Object, String, Bitmap>{

    private View view;
    private Bitmap bitmap = null;
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if(bitmap!=null&&view!=null){
            ImageView newsIcon = (ImageView)view.getTag(R.id.newsIcon);
            newsIcon.setImageBitmap(bitmap);
        }
    }

    @Override
    protected Bitmap doInBackground(Object... params) {
        view = (View)params[0];
        String uri = (String)params[1];
        try{
            InputStream inputStream = new URL(uri).openStream();
            bitmap = BitmapFactory.decodeStream(inputStream);
        }catch (Exception e){
            e.printStackTrace();
        }
        return bitmap;
    }
}

这是我的异步任务

更新:遇到空指针异常

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageBitmap(android.graphics.Bitmap)' on a null object reference

3 个答案:

答案 0 :(得分:2)

您可以编写自己的代码。但是使用库会处理与库关联的所有样板代码。除非另有说明,否则我还建议您使用库。以下是编写自己的代码时需要考虑的一些样板内容。

  1. 内存管理:外部库负责确保图片不会占用您应用可用的所有内存。 Android Bitmaps非常注重内存,因此最好将此部分提供给库。

  2. 处理活动销毁:如果在图片下载过程中旋转手机,它会重新创建活动,然后您需要处理以前请求的取消并启动它们试。

  3. 取消之前的请求:编写图像库,使得不再可见的列表视图项不会继续下载。假设你向下滚动。然后下载作为第一行的一部分的图像是没有意义的。您应取消此类下载并开始下载新图像。编写图像下载程序库以处理这些文件。

  4. 缓存:图像库同时使用内存缓存和磁盘缓存来存储下载的位图。因此,他们只下载新图像,除非它们不可用。

  5. 从UI线程加载大位图:假设您的应用包含大型位图。要将它们加载到视图中,必须先从磁盘加载它们。您需要编写代码,以便加载它们不会阻止主UI线程。

  6. 加载相关图片尺寸:您的应用可能会运行具有高网屏密度的新Android设备或屏幕密度较低的旧设备。根据您的目标设备,如果您的设备不支持此类屏幕密度,则无需加载全分辨率图像。通常库会为您处理,

  7. 这些只是需要考虑的一些样板材料。因此,我强烈建议您为图像加载部分使用一个好的库,除非它是如此需要!!!

答案 1 :(得分:0)

您只需使用java.net.URL将图片加载到ImageView中,如

    ImageView loadedImage;

    @override
    protected Bitmap doInBackground(String... url) {
        String URL_OF_IMAGE = url[0];
        Bitmap bitmap = null;
        try {
            InputStream in = new java.net.URL(URL_OF_IMAGE).openStream();
            bitmap= BitmapFactory.decodeStream(in);
        } catch (Exception e) {
        }
        return bitmap;
    }

    protected void onPostExecute(Bitmap result) {
        loadedImage.setImageBitmap(result);
    }

但请注意,您应该将AsyncTask扩展为第一个参数String,最后一个参数为Bitmap

private class DowmloadImage extends AsyncTask<String, Void, Bitmap>

答案 2 :(得分:0)

您可以使用网络图像视图而不是Imageview。这肯定会让你的生活更轻松。

<com.android.volley.toolbox.NetworkImageView
    android:id="@+id/networkImageView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:background="#000000"/>

应替换所需的XML文件中的Image视图。

public ImageLoader getImageLoader() {
    getRequestQueue();
    if (mImageLoader == null) {
        mImageLoader = new ImageLoader(this.mRequestQueue,
                new LruBitmapCache());
    }
    return this.mImageLoader;
}

上面的类还创建了一个ImageCache,它可以与普通的凌空缓存一起使用,但只为请求缓存图像。

设置图片网址。

advImage.setImageUrl("Your Image URL", AppController.getInstance().getImageLoader());

相应地调用Image Loader功能。您也可以设置defalult占位符图像。