我需要从网上列出数据,因为我有1张图片和2张文字。我解析所有数据并显示它,但图像显示在列表中非常慢。所以我正在寻找最佳方法。
请帮帮我。
提前致谢
答案 0 :(得分:5)
请复制以下课程。该类是从网上下载图像并存储到 存储卡或应用程序的内部存储器。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Stack;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;
public class Imageloader
{
// the simplest in-memory cache implementation. This should be replaced with
// something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
private HashMap<String, Bitmap> cache = new HashMap<String, Bitmap>();
private File cacheDir = null;
private Bitmap useThisBitmap = null;
@SuppressWarnings("unused")
private Context ctx = null;
public Imageloader(Context context)
{
// Make the background thead low priority. This way it will not affect
// the UI performance
ctx = context;
photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1);
// Find the dir to save cached images
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir = new File(android.os.Environment.getExternalStorageDirectory(),"DownloadImages/AlbumArt/");
else
cacheDir = context.getCacheDir();
if (!cacheDir.exists())
cacheDir.mkdirs();
}
public void DisplayImage(String url, Activity activity, ImageView imageView)
{
if(!url.equals(""))
{
if (cache.containsKey(url))
{
imageView.setImageBitmap(cache.get(url));
}
else
{
queuePhoto(url, activity, imageView);
}
}
}
private void queuePhoto(String url, Activity activity, ImageView imageView)
{
// This ImageView may be used for other images before. So there may be
// some old tasks in the queue. We need to discard them.
photosQueue.Clean(imageView);
PhotoToLoad p = new PhotoToLoad(url, imageView);
synchronized (photosQueue.photosToLoad)
{
photosQueue.photosToLoad.push(p);
photosQueue.photosToLoad.notifyAll();
}
// start thread if it's not started yet
if (photoLoaderThread.getState() == Thread.State.NEW)
photoLoaderThread.start();
}
public Bitmap getBitmap(String url)
{
try
{
// I identify images by hashcode. Not a perfect solution, good for the
// demo.
String filename = String.valueOf(url.hashCode());
File f = new File(cacheDir, filename);
// from SD cache
Bitmap b = decodeFile(f);
if (b != null)
return b;
// from web
try {
Bitmap bitmap = null;
if(!url.equals("")){
InputStream is = new URL(url).openStream();
OutputStream os = new FileOutputStream(f);
Utils.CopyStream(is, os);
os.close();
bitmap = decodeFile(f);
}
return bitmap;
}
catch (Exception ex)
{
ex.printStackTrace();
return null;
}
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
}
/*decodes image and scales it to reduce memory consumption
* @param file path
* @throws FileNotFoundException
* @return bitmap
* */
private Bitmap decodeFile(File f){
Bitmap b = null;
try {
useThisBitmap = null;
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
final int IMAGE_MAX_SIZE = 70;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
int scale = 2;
if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
scale = 2 ^ (int) Math.ceil(Math.log(IMAGE_MAX_SIZE / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5));
}
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
b = BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
useThisBitmap = b;
}
catch (FileNotFoundException e) {
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
System.gc();
}
return useThisBitmap;
}
// Task for the queue
private class PhotoToLoad
{
public String url;
public ImageView imageView;
public PhotoToLoad(String u, ImageView i) {
url = u;
imageView = i;
}
}
private PhotosQueue photosQueue = new PhotosQueue();
// stores list of photos to download
private class PhotosQueue
{
private Stack<PhotoToLoad> photosToLoad = new Stack<PhotoToLoad>();
// removes all instances of this ImageView
private void Clean(ImageView image)
{
for (int j = 0; j < photosToLoad.size();)
{
if (photosToLoad.get(j).imageView == image)
photosToLoad.remove(j);
else
++j;
}
}
}
private class PhotosLoader extends Thread
{
public void run()
{
try
{
while (true)
{
// thread waits until there are any images to load in the
// queue
if (photosQueue.photosToLoad.size() == 0)
synchronized (photosQueue.photosToLoad) {
photosQueue.photosToLoad.wait();
}
if (photosQueue.photosToLoad.size() != 0) {
PhotoToLoad photoToLoad;
synchronized (photosQueue.photosToLoad) {
photoToLoad = photosQueue.photosToLoad.pop();
}
Bitmap bmp = getBitmap(photoToLoad.url);
cache.put(photoToLoad.url, bmp);
if (((String) photoToLoad.imageView.getTag())
.equals(photoToLoad.url)) {
BitmapDisplayer bd = new BitmapDisplayer(bmp,
photoToLoad.imageView);
Activity a = (Activity) photoToLoad.imageView
.getContext();
a.runOnUiThread(bd);
}
}
if (Thread.interrupted())
break;
}
} catch (InterruptedException e) {
// allow thread to exit
}
}
}
private PhotosLoader photoLoaderThread = new PhotosLoader();
// Used to display bitmap in the UI thread
private class BitmapDisplayer implements Runnable
{
private Bitmap bitmap;
private ImageView imageView;
private BitmapDisplayer(Bitmap b, ImageView i)
{
bitmap = b;
imageView = i;
}
public void run()
{
if (bitmap != null)
imageView.setImageBitmap(bitmap);
}
}
public void stopThread()
{
photoLoaderThread.interrupt();
}
public void clearCache()
{
cache.clear();
File[] files = cacheDir.listFiles();
for (File f : files)
f.delete();
}
}
首先创建你的图像Loader类对象。
Imageloader imageLoader = new Imageloader(getApplicationContext());
然后将图片网址设置为imageview的setTag
属性。
imgImageView.setTag(Your Image Url);
然后调用ImageLoader类显示图像功能。需要3个参数。
1)图片网址
2)您当前的班级名称
3)ImageView
imageLoader.DisplayImage(Your Image Url,ClassName.this,imgImageView);
这个功能从网上下载图像并存储到内存中并从内存中显示。
答案 1 :(得分:4)
您可以先下载整个文本,然后只显示图像。不要下载整个图像列表,因为可能大部分图像永远不会被显示。
尝试向用户迈进一步。例如,如果列表在您第一次输入活动时可以显示6个图像,请在切换到此活动之前预取这6个图像,然后通过Intent传递它们。您还可以使用一个线程下载如果用户向下滚动时将显示的以下(3或4)图像。
为了加快这一过程,请考虑预先缩放图像,以便缩小尺寸,下载速度更快。
答案 2 :(得分:2)
使用此类而不是普通的imageview
package sherif.android.ui;
import java.io.IOException;
import java.net.MalformedURLException;
import sherif.caching.R;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.os.Handler.Callback;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
/**
*
* @author Sherif
* thanks Blundell
*
*/
public class ImageViewLoading extends LinearLayout{
private static final int COMPLETE = 0;
private static final int FAILED = 1;
private Context mContext;
private Drawable mDrawable;
private ProgressBar mSpinner;
private ImageView mImage;
/**
* This is used when creating the view in XML
* To have an image load in XML use the tag 'image="http://developer.android.com/images/dialog_buttons.png"'
* Replacing the url with your desired image
* Once you have instantiated the XML view you can call
* setImageDrawable(url) to change the image
* @param context
* @param attrSet
*/
public ImageViewLoading(final Context context, final AttributeSet attrSet) {
super(context, attrSet);
final String url = attrSet.getAttributeValue(null, "image");
if(url != null){
instantiate(context, url);
} else {
instantiate(context, null);
}
}
/**
* This is used when creating the view programatically
* Once you have instantiated the view you can call
* setImageDrawable(url) to change the image
* @param context the Activity context
* @param imageUrl the Image URL you wish to load
*/
//USE THIS TO ADD IMAGEVIEWS
public ImageViewLoading(final Context context, final String imageUrl) {
super(context);
instantiate(context, imageUrl);
}
/**
* First time loading of the LoaderImageView
* Sets up the LayoutParams of the view, you can change these to
* get the required effects you want
*/
private void instantiate(final Context context, final String imageUrl) {
mContext = context;
mImage = new ImageView(mContext);
mImage.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
mSpinner = new ProgressBar(mContext);
mSpinner.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
mSpinner.setIndeterminate(true);
//addView(mSpinner);
//addView(mImage);
if(imageUrl != null){
setImageDrawable(imageUrl);
}
}
/**
* Set's the view's drawable, this uses the internet to retrieve the image
* don't forget to add the correct permissions to your manifest
* @param imageUrl the url of the image you wish to load
*/
public void setImageDrawable(final String imageUrl) {
mDrawable = null;
mSpinner.setVisibility(View.VISIBLE);
mImage.setVisibility(View.GONE);
new Thread(){
public void run() {
try {
mDrawable = getDrawableFromUrl(imageUrl);
imageLoadedHandler.sendEmptyMessage(COMPLETE);
} catch (MalformedURLException e) {
imageLoadedHandler.sendEmptyMessage(FAILED);
} catch (IOException e) {
imageLoadedHandler.sendEmptyMessage(FAILED);
}
};
}.start();
}
/**
* Callback that is received once the image has been downloaded
*/
private final Handler imageLoadedHandler = new Handler(new Callback() {
public boolean handleMessage(Message msg) {
switch (msg.what) {
case COMPLETE:
mImage.setImageDrawable(mDrawable);
mImage.setVisibility(View.VISIBLE);
mSpinner.setVisibility(View.GONE);
break;
case FAILED:
default:
mImage.setImageResource(R.drawable.failed);
mImage.setVisibility(View.VISIBLE);
mSpinner.setVisibility(View.GONE);
// Could change image here to a 'failed' image
// otherwise will just keep on spinning
break;
}
return true;
}
});
/**
* Pass in an image url to get a drawable object
* @return a drawable object
* @throws IOException
* @throws MalformedURLException
*/
private static Drawable getDrawableFromUrl(final String url) throws IOException, MalformedURLException {
return Drawable.createFromStream(((java.io.InputStream)new java.net.URL(url).getContent()), "name");
}
}
答案 3 :(得分:1)
在List中下载和显示图像有点复杂。您需要考虑的一些要点是:
答案 4 :(得分:0)
我认为你应该试试Fedor的Android ListView LazyLoading example,它的效果很好。
Fedor在答案中提到了源代码,你可以从以下源代码获得源代码:
答案 5 :(得分:0)
FYI
Chirag Raval回答有效,但你也需要Utils课程。
import java.io.InputStream;
import java.io.OutputStream;
public class Utils {
public static void CopyStream(InputStream is, OutputStream os)
{
final int buffer_size=1024;
try
{
byte[] bytes=new byte[buffer_size];
for(;;)
{
int count=is.read(bytes, 0, buffer_size);
if(count==-1)
break;
os.write(bytes, 0, count);
}
}
catch(Exception ex){}
}
}
您可以阅读有关此here
的更多信息