android - 在ListView中延迟加载图像




image url universal-image-loader (25)

我正在使用ListView来显示与这些图像相关的一些图像和标题。 我从互联网上获取图像。 有没有办法在文本显示时延迟加载图像,UI未锁定并且图像在下载时显示?

图像总数不固定。


Answers

我遵循这个Android培训,我认为它在下载图像方面做得非常出色,并且不会阻塞主UI。 它还处理缓存和处理滚动许多图像: 高效加载大型位图


我写了一篇教程,解释了如何在列表视图中执行延迟加载的图像。 我详细讨论了回收和并发问题。 我也使用固定线程池来防止产生大量线程。

Listview教程中的图像延迟加载


Check my fork of LazyList . Basically, I improve the LazyList by delaying the call of the ImageView and create two methods:

  1. When you need to put something like "Loading image..."
  2. When you need to show the downloaded image.

I also improved the ImageLoader by implementing a singleton in this object.


毕加索

使用杰克沃顿的毕加索图书馆。 (一个完美的ImageLoading库是ActionBarSherlock的开发者)

适用于Android的功能强大的图片下载和缓存库。

图像为Android应用程序添加了非常需要的上下文和视觉风格。 毕加索允许在应用程序中轻松加载图像 - 通常只需一行代码!

Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

毕加索自动处理Android上图像加载的许多常见缺陷:

处理ImageView回收并在适配器中下载取消。 复杂的图像转换与最小的内存使用。 自动内存和磁盘缓存。

毕加索杰克沃顿图书馆

滑行

Glide是一款快速高效的Android开源媒体管理框架,将媒体解码,内存和磁盘缓存以及资源池整合到一个简单易用的界面中。

Glide支持获取,解码和显示视频静像,图像和动画GIF。 Glide包含一个灵活的API,允许开发人员插入几乎任何网络堆栈。 默认情况下,Glide使用基于自定义HttpUrlConnection的堆栈,但也包括实用程序库插入Google的Volley项目或Square的OkHttp库。

Glide.with(this).load("http://goo.gl/h8qOq7").into(imageView);

Glide的主要焦点是尽可能平滑和快速地滚动任何类型的图像列表,但对于几乎任何需要获取,调整大小和显示远程图像的情况,Glide都是有效的。

滑动图像加载库

通过Facebook的壁画

Fresco是一个在Android应用程序中显示图像的强大系统。

Fresco负责图像加载和显示,因此您不必这样做。 它将从网络,本地存储或本地资源中加载图像,并在图像到达之前显示一个占位符。 它有两个级别的缓存; 一个在内存中,另一个在内部存储器中。

壁画Github

在Android 4.x及更低版本中,Fresco将图像放在Android内存的特殊区域。 这可以让你的应用程序运行得更快 - 而且可怕的OutOfMemoryError遭受的次数更少。

壁画文件


1. 毕加索允许在应用程序中轻松加载图像 - 通常只需一行代码!

使用Gradle:

implementation 'com.squareup.picasso:picasso:2.71828'

只需一行代码!

Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(imageView);

Android上图像加载的许多常见缺陷都是由毕加索自动处理的

  • 处理ImageView回收并在适配器中下载取消。
  • 复杂的图像转换与最小的内存使用。
  • 自动内存和磁盘缓存。

2. 滑翔 Android的图像加载和缓存库专注于平滑滚动

使用Gradle:

repositories {
  mavenCentral() // jcenter() works as well because it pulls from Maven Central
}

dependencies {
  compile 'com.github.bumptech.glide:glide:3.7.0'
  compile 'com.android.support:support-v4:19.1.0'
}

//对于一个简单的视图:

@Override public void onCreate(Bundle savedInstanceState) {
  ...
  ImageView imageView = (ImageView) findViewById(R.id.my_image_view);

  Glide.with(this).load("http://i.imgur.com/DvpvklR.png").into(imageView);
}

//对于一个简单的图片列表:

 @Override public View getView(int position, View recycled, ViewGroup container) {
      final ImageView myImageView;
      if (recycled == null) {
        myImageView = (ImageView) inflater.inflate(R.layout.my_image_view, container, false);
      } else {
        myImageView = (ImageView) recycled;
      }

      String url = myUrls.get(position);

      Glide
        .with(myFragment)
        .load(url)
        .centerCrop()
        .placeholder(R.drawable.loading_spinner)
        .crossFade()
        .into(myImageView);

      return myImageView;
}

那么,来自互联网的图像加载时间有很多解决方案。 您也可以使用Android-Query库。 它会给你所有需要的活动。 确保你想要做什么,并阅读图书馆的维基页面。 并解决图片加载限制。

这是我的代码:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if (v == null) {
        LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.row, null);
    }

    ImageView imageview = (ImageView) v.findViewById(R.id.icon);
    AQuery aq = new AQuery(convertView);

    String imageUrl = "http://www.vikispot.com/z/images/vikispot/android-w.png";

    aq.id(imageview).progress(this).image(imageUrl, true, true, 0, 0, new BitmapAjaxCallback() {
        @Override
        public void callback(String url, ImageView iv, Bitmap bm, AjaxStatus status) {
            iv.setImageBitmap(bm);
        }
    ));

    return v;
}

它应该解决你的延迟加载问题。


我推荐开源仪器github.com/nostra13/Android-Universal-Image-Loader 。 它最初基于Fedor Vlasov的LazyList项目,自那时以来得到了极大的改进。

  • 多线程图像加载
  • 广泛调整ImageLoader配置的可能性(线程执行者,下载器,解码器,内存和磁盘缓存,显示图像选项等)
  • 在内存和/或设备的文件系统(或SD卡)上进行图像缓存的可能性
  • 可以“倾听”加载过程
  • 可以使用单独的选项自定义每个显示图像调用
  • 小部件支持
  • Android 2.0+支持

github.com/nostra13/Android-Universal-Image-Loader


I can recommend a different way that works like a charm: Android Query.

You can download that JAR file from here

AQuery androidAQuery = new AQuery(this);

举个例子:

androidAQuery.id(YOUR IMAGEVIEW).image(YOUR IMAGE TO LOAD, true, true, getDeviceWidth(), ANY DEFAULT IMAGE YOU WANT TO SHOW);

It's very fast and accurate, and using this you can find many more features like animation when loading, getting a bitmap (if needed), etc.


这是我创建的用于保存我的应用当前正在显示的图像。 请注意,这里使用的“Log”对象是我在Android内部的最终Log类中的自定义包装。

package com.wilson.android.library;

/*
 Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/
import java.io.IOException;

public class DrawableManager {
    private final Map<String, Drawable> drawableMap;

    public DrawableManager() {
        drawableMap = new HashMap<String, Drawable>();
    }

    public Drawable fetchDrawable(String urlString) {
        if (drawableMap.containsKey(urlString)) {
            return drawableMap.get(urlString);
        }

        Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
        try {
            InputStream is = fetch(urlString);
            Drawable drawable = Drawable.createFromStream(is, "src");


            if (drawable != null) {
                drawableMap.put(urlString, drawable);
                Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
                        + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
                        + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
            } else {
              Log.w(this.getClass().getSimpleName(), "could not get thumbnail");
            }

            return drawable;
        } catch (MalformedURLException e) {
            Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
            return null;
        } catch (IOException e) {
            Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
            return null;
        }
    }

    public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
        if (drawableMap.containsKey(urlString)) {
            imageView.setImageDrawable(drawableMap.get(urlString));
        }

        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message message) {
                imageView.setImageDrawable((Drawable) message.obj);
            }
        };

        Thread thread = new Thread() {
            @Override
            public void run() {
                //TODO : set imageView to a "pending" image
                Drawable drawable = fetchDrawable(urlString);
                Message message = handler.obtainMessage(1, drawable);
                handler.sendMessage(message);
            }
        };
        thread.start();
    }

    private InputStream fetch(String urlString) throws MalformedURLException, IOException {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpGet request = new HttpGet(urlString);
        HttpResponse response = httpClient.execute(request);
        return response.getEntity().getContent();
    }
}

更新:请注意,这个答案现在非常无效。 垃圾收集器在SoftReference和WeakReference上积极行事,所以这段代码不适合新的应用程序。 (相反,尝试其他答案中提到的github.com/nostra13/Android-Universal-Image-Loader等库)。

感谢James提供的代码,以及Bao-Long提供的使用SoftReference的建议。 我在James的代码上实现了SoftReference变更。 不幸的是,SoftReferences导致我的图像太快被垃圾收集。 在我的情况下,没有SoftReference的东西没问题,因为我的列表大小是有限的,而且我的图片很小。

一年前有关于谷歌组的SoftReferences的讨论: 链接到线索 。 作为过早垃圾收集的解决方案,他们建议使用dalvik.system.VMRuntime.setMinimumHeapSize()手动设置VM堆大小的可能性,这对我来说不是很有吸引力。

public DrawableManager() {
    drawableMap = new HashMap<String, SoftReference<Drawable>>();
}

public Drawable fetchDrawable(String urlString) {
    SoftReference<Drawable> drawableRef = drawableMap.get(urlString);
    if (drawableRef != null) {
        Drawable drawable = drawableRef.get();
        if (drawable != null)
            return drawable;
        // Reference has expired so remove the key from drawableMap
        drawableMap.remove(urlString);
    }

    if (Constants.LOGGING) Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
    try {
        InputStream is = fetch(urlString);
        Drawable drawable = Drawable.createFromStream(is, "src");
        drawableRef = new SoftReference<Drawable>(drawable);
        drawableMap.put(urlString, drawableRef);
        if (Constants.LOGGING) Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
                + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
                + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
        return drawableRef.get();
    } catch (MalformedURLException e) {
        if (Constants.LOGGING) Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
        return null;
    } catch (IOException e) {
        if (Constants.LOGGING) Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
        return null;
    }
}

public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
    SoftReference<Drawable> drawableRef = drawableMap.get(urlString);
    if (drawableRef != null) {
        Drawable drawable = drawableRef.get();
        if (drawable != null) {
            imageView.setImageDrawable(drawableRef.get());
            return;
        }
        // Reference has expired so remove the key from drawableMap
        drawableMap.remove(urlString);
    }

    final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            imageView.setImageDrawable((Drawable) message.obj);
        }
    };

    Thread thread = new Thread() {
        @Override
        public void run() {
            //TODO : set imageView to a "pending" image
            Drawable drawable = fetchDrawable(urlString);
            Message message = handler.obtainMessage(1, drawable);
            handler.sendMessage(message);
        }
    };
    thread.start();
}

android-developers.blogspot.com/2010/07/… ,由Gilles Debunne编写的教程。

这来自Android开发人员博客。 建议的代码使用:

  • AsyncTasks
  • 一个硬的,有限的FIFO cache
  • 一个软,容易garbage collect缓存。
  • 占位符在下载时Drawable


你必须试试这个Universal Loader是最好的。 在使用惰性加载完成许多RnD后,我正在使用这个功能。

github.com/nostra13/Android-Universal-Image-Loader

特征

  • 多线程图像加载(异步或同步)
  • ImageLoader的配置(线程执行程序,下载程序,解码器,内存和磁盘缓存,显示图像选项等)的宽泛定制
  • 每个显示图像调用的许多自定义选项(存根图像,缓存切换,解码选项,位图处理和显示等)
  • Image caching in memory and/or on disk (device's file system or SD card)
  • Listening loading process (including downloading progress)

Android 2.0+ support


这是Android上的一个常见问题,许多人已经以多种方式解决了这个问题。 在我看来,我见过的最好的解决方案是名为毕加索的相对较新的图书馆。 以下是亮点:

  • 开源,但由ActionBarSherlock成名的Jake Wharton领导。
  • 用一行代码异步加载来自网络或应用程序资源的图像
  • 自动ListView检测
  • 自动磁盘和内存缓存
  • 可以做自定义转换
  • 许多可配置的选项
  • 超级简单的API
  • 经常更新

Novoda also has a great lazy image loading library and many apps like Songkick, Podio, SecretDJ and ImageSearch use their library.

Their library is hosted here on Github and they have a pretty active issues tracker as well. Their project seems to be pretty active too, with over 300+ commits at the time of writing this reply.


看看Shutterbug ,Applidium的轻量级SDWebImage(iOS上的一个很好的库)端口到Android。 它支持异步缓存,存储失败的URL,很好地处理并发,并包含有用的子类。

拉请求(和错误报告)也是受欢迎的!


All above code have their own worth but with my personal experience just give a try with Picasso.

Picasso is a library specifically for this purpose, in-fact it will manage cache and all other network operations automatically.You will have to add library in your project and just write a single line of code to load image from remote URL.

Please visit here : http://code.tutsplus.com/tutorials/android-sdk-working-with-picasso--cms-22149


我认为这个问题在Android开发人员中非常流行,并且有很多这样的库声称可以解决这个问题,但其中只有少数似乎处于标记状态。 AQuery就是这样一个库,但它比其中的大多数都好,值得一试。


DroidParts has ImageFetcher that requires zero configuration to get started.

  • Uses a disk & in-memory Least Recently Used (LRU) cache.
  • Efficiently decodes images.
  • Supports modifying bitmaps in background thread.
  • Has simple cross-fade.
  • Has image loading progress callback.

Clone DroidPartsGram for an example:


Just a quick tip for someone who is in indecision regarding what library to use for lazy-loading images:

There are four basic ways.

  1. DIY => Not the best solution but for a few images and if you want to go without the hassle of using others libraries

  2. Volley's Lazy Loading library => From guys at android. It is nice and everything but is poorly documented and hence is a problem to use.

  3. Picasso: A simple solution that just works, you can even specify the exact image size you want to bring in. It is very simple to use but might not be very "performant" for apps that has to deal with humongous amounts of images.

  4. UIL: The best way to lazy load images. You can cache images(you need permission of course), initialize the loader once, then have your work done. The most mature asynchronous image loading library I have ever seen so far.


使用滑翔库。它为我工作,并将为你的代码工作。它既适用于图像也适用于gif。

ImageView imageView = (ImageView) findViewById(R.id.test_image); 
    GlideDrawableImageViewTarget imagePreview = new GlideDrawableImageViewTarget(imageView);
    Glide
            .with(this)
            .load(url)
            .listener(new RequestListener<String, GlideDrawable>() {
                @Override
                public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {                       
                    return false;
                }

                @Override
                public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                    return false;
                }
            })
            .into(imagePreview);
}


我用图像做了一个懒惰列表 (位于GitHub) 的简单演示 。 这可能对某人有所帮助。 它在后台线程中下载图像。 图像被缓存在SD卡和内存中。 缓存实现非常简单,对于演示就足够了。 我使用inSampleSize解码图像以减少内存消耗。 我也尝试正确处理回收的视图。


public class ImageDownloader {

Map<String, Bitmap> imageCache;

public ImageDownloader() {
    imageCache = new HashMap<String, Bitmap>();

}

// download function
public void download(String url, ImageView imageView) {
    if (cancelPotentialDownload(url, imageView)) {

        // Caching code right here
        String filename = String.valueOf(url.hashCode());
        File f = new File(getCacheDirectory(imageView.getContext()),
                filename);

        // Is the bitmap in our memory cache?
        Bitmap bitmap = null;

        bitmap = (Bitmap) imageCache.get(f.getPath());

        if (bitmap == null) {

            bitmap = BitmapFactory.decodeFile(f.getPath());

            if (bitmap != null) {
                imageCache.put(f.getPath(), bitmap);
            }

        }
        // No? download it
        if (bitmap == null) {
            try {
                BitmapDownloaderTask task = new BitmapDownloaderTask(
                        imageView);
                DownloadedDrawable downloadedDrawable = new DownloadedDrawable(
                        task);
                imageView.setImageDrawable(downloadedDrawable);
                task.execute(url);
            } catch (Exception e) {
                Log.e("Error==>", e.toString());
            }

        } else {
            // Yes? set the image
            imageView.setImageBitmap(bitmap);
        }
    }
}

// cancel a download (internal only)
private static boolean cancelPotentialDownload(String url,
        ImageView imageView) {
    BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

    if (bitmapDownloaderTask != null) {
        String bitmapUrl = bitmapDownloaderTask.url;
        if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
            bitmapDownloaderTask.cancel(true);
        } else {
            // The same URL is already being downloaded.
            return false;
        }
    }
    return true;
}

// gets an existing download if one exists for the imageview
private static BitmapDownloaderTask getBitmapDownloaderTask(
        ImageView imageView) {
    if (imageView != null) {
        Drawable drawable = imageView.getDrawable();
        if (drawable instanceof DownloadedDrawable) {
            DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable;
            return downloadedDrawable.getBitmapDownloaderTask();
        }
    }
    return null;
}

// our caching functions
// Find the dir to save cached images
private static File getCacheDirectory(Context context) {
    String sdState = android.os.Environment.getExternalStorageState();
    File cacheDir;

    if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
        File sdDir = android.os.Environment.getExternalStorageDirectory();

        // TODO : Change your diretcory here
        cacheDir = new File(sdDir, "data/ToDo/images");
    } else
        cacheDir = context.getCacheDir();

    if (!cacheDir.exists())
        cacheDir.mkdirs();
    return cacheDir;
}

private void writeFile(Bitmap bmp, File f) {
    FileOutputStream out = null;

    try {
        out = new FileOutputStream(f);
        bmp.compress(Bitmap.CompressFormat.PNG, 80, out);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (out != null)
                out.close();
        } catch (Exception ex) {
        }
    }
}

// download asynctask
public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
    private String url;
    private final WeakReference<ImageView> imageViewReference;

    public BitmapDownloaderTask(ImageView imageView) {
        imageViewReference = new WeakReference<ImageView>(imageView);
    }

    @Override
    // Actual download method, run in the task thread
    protected Bitmap doInBackground(String... params) {
        // params comes from the execute() call: params[0] is the url.
        url = (String) params[0];
        return downloadBitmap(params[0]);
    }

    @Override
    // Once the image is downloaded, associates it to the imageView
    protected void onPostExecute(Bitmap bitmap) {
        if (isCancelled()) {
            bitmap = null;
        }

        if (imageViewReference != null) {
            ImageView imageView = imageViewReference.get();
            BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
            // Change bitmap only if this process is still associated with
            // it
            if (this == bitmapDownloaderTask) {
                imageView.setImageBitmap(bitmap);

                // cache the image

                String filename = String.valueOf(url.hashCode());
                File f = new File(
                        getCacheDirectory(imageView.getContext()), filename);

                imageCache.put(f.getPath(), bitmap);

                writeFile(bitmap, f);
            }
        }
    }

}

static class DownloadedDrawable extends ColorDrawable {
    private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;

    public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
        super(Color.WHITE);
        bitmapDownloaderTaskReference = new WeakReference<BitmapDownloaderTask>(
                bitmapDownloaderTask);
    }

    public BitmapDownloaderTask getBitmapDownloaderTask() {
        return bitmapDownloaderTaskReference.get();
    }
}

// the actual download code
static Bitmap downloadBitmap(String url) {
    HttpParams params = new BasicHttpParams();
    params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
            HttpVersion.HTTP_1_1);
    HttpClient client = new DefaultHttpClient(params);
    final HttpGet getRequest = new HttpGet(url);

    try {
        HttpResponse response = client.execute(getRequest);
        final int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != HttpStatus.SC_OK) {
            Log.w("ImageDownloader", "Error " + statusCode
                    + " while retrieving bitmap from " + url);
            return null;
        }

        final HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream inputStream = null;
            try {
                inputStream = entity.getContent();
                final Bitmap bitmap = BitmapFactory
                        .decodeStream(inputStream);
                return bitmap;
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                entity.consumeContent();
            }
        }
    } catch (Exception e) {
        // Could provide a more explicit error message for IOException or
        // IllegalStateException
        getRequest.abort();
        Log.w("ImageDownloader", "Error while retrieving bitmap from "
                + url + e.toString());
    } finally {
        if (client != null) {
            // client.close();
        }
    }
    return null;
 }
}

Give Android-Query a try. It has amazingly simple methods to load and cache images asynchronously.


以下是具有不同图像的简单Listview。首先,您必须复制不同类型的图像并将其粘贴到项目中的res / drawable-hdpi.Images应为.png格式。 然后复制此代码。

在main.xml中

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<TextView
    android:id="@+id/textview"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
/>

<ListView
    android:id="@+id/listview"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
/>
</LinearLayout>

创建listview_layout.xml并粘贴此代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<ImageView
    android:id="@+id/flag"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:contentDescription="@string/hello"
    android:paddingTop="10dp"
    android:paddingRight="10dp"
    android:paddingBottom="10dp"
/>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
>
    <TextView
        android:id="@+id/txt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="15dp"
        android:text="TextView1"
    />

    <TextView
        android:id="@+id/cur"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="10dp"
        android:text="TextView2"
    />
</LinearLayout>
</LinearLayout>

在你的活动中

package com.test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;

public class SimpleListImageActivity extends Activity {

    // Array of strings storing country names
    String[] countries = new String[] {
        "India",
        "Pakistan",
        "Sri Lanka",
        "China",
        "Bangladesh",
        "Nepal",
        "Afghanistan",
        "North Korea",
        "South Korea",
        "Japan"
    };

    // Array of integers points to images stored in /res/drawable-hdpi/
    int[] flags = new int[]{
        R.drawable.image1,         
  //here you have to give image name which you already pasted it in /res/drawable-hdpi/
        R.drawable.image2,   
        R.drawable.image3,
        R.drawable.image4,
        R.drawable.image5,
        R.drawable.image6,
        R.drawable.image7,
        R.drawable.image8,
        R.drawable.image9,
        R.drawable.image10,
    };

    // Array of strings to store currencies
    String[] currency = new String[]{
        "Indian Rupee",
        "Pakistani Rupee",
        "Sri Lankan Rupee",
        "Renminbi",
        "Bangladeshi Taka",
        "Nepalese Rupee",
        "Afghani",
        "North Korean Won",
        "South Korean Won",
        "Japanese Yen"
    };

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Each row in the list stores country name, currency and flag
        List<HashMap<String,String>> aList = new ArrayList<HashMap<String,String>>();

        for(int i=0;i<10;i++){
            HashMap<String, String> hm = new HashMap<String,String>();
            hm.put("txt", "Country : " + countries[i]);
            hm.put("cur","Currency : " + currency[i]);
            hm.put("flag", Integer.toString(flags[i]) );
            aList.add(hm);
        }

        // Keys used in Hashmap
        String[] from = { "flag","txt","cur" };

        // Ids of views in listview_layout
        int[] to = { R.id.flag,R.id.txt,R.id.cur};

        // Instantiating an adapter to store each items
        // R.layout.listview_layout defines the layout of each item
        SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), aList,                R.layout.listview_layout, from, to);

        // Getting a reference to listview of main.xml layout file
        ListView listView = ( ListView ) findViewById(R.id.listview);

        // Setting the adapter to the listView
        listView.setAdapter(adapter);
    }
}

这是完整的代码。您可以根据需要进行更改...欢迎提出意见





android image listview url universal-image-loader