listview中的位图加载是平滑的,缓存到SD但是滞后于应用程序

时间:2014-05-21 19:27:24

标签: android listview bitmap

首先我要说的是,我有一个非常不寻常的图像来源。我正在获取需要从mp3文件上的ID3标签加载的位图。

每当我加载封面并将其保存到SD存储空间时,我都会得到lagg。奇怪的是,所有加载和保存都发生在后台线程上,所以它不应该影响UI线程。 +我一次只运行一个操作,但仍然滞后。

一旦我将所有图像保存到磁盘,我构建了一个包含所保存文件的所有路径名的数组,它像黄油一样滚动,所有图像加载没有任何延迟。所以问题显然是对SD的缓存,这在UI线程上没有发生。 (我可能错了,所以这就是你们进来的地方)从文件加载的图像是使用Universal Image Loader btw完成的,但这不会导致任何问题:)

以下是我的代码片段,用于存储封面图片:

public ExecutorService executor = Executors.newFixedThreadPool(1);

//this is where I schedule tasks for all mp3 files to be executed using the threadpool, 
//it is interrupted as soon as the user interacts with the listview (which should not be
//nessecary as it is not running any code on the UI thread)

public void preloadImages(){
    for(int i = 0; i < items.length; i++){
        if(scrolling){
            return;
        }
        if(items[i].type.equalsIgnoreCase("music") && imagePathArray[i] == null){
            ImageRunnable imgr = new ImageRunnable(items[i].pathname, null, i);
            executor.execute(imgr);
        }
        if(scrolling){
            return;
        }
    }
}

自定义runnable

//the custom runnable used to call the getCover method on separate thread
private class ImageRunnable implements Runnable {
    private String url;
    private final WeakReference<ImageView> imageViewReference;
    private boolean running = true;
    private int position;

    public ImageRunnable(String path, ImageView img, int pos) {
        url = path;
        imageViewReference = new WeakReference<ImageView>(img);
        position = pos;
    }

    public void terminate() {
        running = false;
    }

    @Override
    public void run() {
        android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
        final String coverPath = getCover(url, position);
    }
}

getcover方法

private String getCover(String filepath, boolean refresh, int pos){
    Log.d(LOG_TAG, "BEGIN function");
    File file = new File(filepath);
    Log.d(LOG_TAG, "File read");
    MusicMetadataSet meta = null;

    try {
        meta = new MyID3().read(file);
        Log.d(LOG_TAG, "id3 read");
    } catch (IOException e) {
        Log.d(LOG_TAG, "error reading id3 tag of file");
        return null;
    }
    if(meta != null) {
        try {
            MusicMetadata metasimple = (MusicMetadata) meta.getSimplified();
            Log.d(LOG_TAG, "simplified");
            int length = filepath.length();
            String albumname = filepath.substring(length-15, length-5).replaceAll("[^a-zA-Z0-9.-]", "_");
            String path = Environment.getExternalStorageDirectory().toString();
            OutputStream fOut = null;
            Log.d(LOG_TAG, "album string");
            File fileo = new File(path, "id3tag/"+albumname+"_icon.jpg");
            Log.d(LOG_TAG, "file created");
            File dir = new File(path, "id3tag/");
            if(!dir.isDirectory()){
                dir.mkdirs();
            }
            if(!fileo.exists() || refresh){
                try {
                    fileo.createNewFile();
                    fOut = new FileOutputStream(fileo);

                    Vector<ImageData> fileList = metasimple.getPictureList();
                    Log.d(LOG_TAG, "got pic list");
                    ImageData data = fileList.lastElement();
                    if(fileList.size() == 0){
                        imagePathArray[pos] = "error";
                        return imagePathArray[pos];
                    }
                    byte[] rawimage = data.imageData;
                    Log.d(LOG_TAG, "got raw");
                    Bitmap bitmap = BitmapFactory.decodeByteArray(rawimage, 0, rawimage.length);
                    Log.d(LOG_TAG, "decoded bmp");
                    bitmap = bitmap.createScaledBitmap(bitmap, 64, 64, false);
                    Log.d(LOG_TAG, "scaled bmp");
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
                    Log.d(LOG_TAG, "compr bmp");
                    fOut.flush();
                    fOut.close();
                    bitmap.recycle();
                    Log.d(LOG_TAG, "recycled");

                    meta = null;
                    rawimage = null;
                    fileList = null;
                    options = null;
                    metasimple = null;
                    bitmap = null;
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            imagePathArray[pos] = Uri.decode(fileo.toURI().toString().replace("file:/", "file:///"));
            return imagePathArray[pos];
        }catch (NoSuchElementException e){
            return null;
        }
    }
    return null;
}

3 个答案:

答案 0 :(得分:0)

我目前正在处理同样的问题。

对我来说,它似乎是多个GC调用,它会暂停所有线程,包括UI线程,以便找到可以释放的资源!

检查您的LogCat消息以确认,查找标记为dalvikm

的条目

答案 1 :(得分:0)

尽量减少新位图的分配。首先,您可以制作一个64x64的位图并在其中绘制而不是使用creatScaledBitmap。

其次,你可以通过BitmapFactory.Options将它传递给decodeByteArray来重用位图进行解码

答案 2 :(得分:0)

好的我发现了这个问题,但还没有解决方法。谢谢大家帮助到目前为止!瓶颈似乎是对ID3对象的读操作。为什么以及如何阻止主线程我不知道,但我会尝试最小化该对象的使用情况,看看它在哪里引导我:)

执行此操作后,它只会落后于每个文件只发生一次的初始缓存,所以没什么大不了的。