1

ListView画像をリストアイテムとして表示するカスタムを作成しました。リストアイテムとして表示する画像はデバイスに保存されていますInternalStorage。アイテムの数が7を超えると、リストビューのスクロールが遅くなり、スクロール中にアイテムがListViewぎくしゃくすることに気づきました。私のコードに何か問題があるか、私のコードで行うべきことがありません。これを解決するのを手伝ってください。

リスト ビュー アイテムを表示するためのコード

public class ListViewAdapter extends BaseAdapter 
    {
        private Activity activity;
        private ArrayList<String> fileNameArray;
        private LayoutInflater inflater=null;
        public  ImageLoader imageLoader; 

        public ListViewAdapter(Activity a,  ArrayList<String> d) 
        {
            activity = a;
            fileNameArray = d;
            inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            imageLoader = new ImageLoader(activity.getApplicationContext());
        }

        public int getCount() 
        {
            return fileNameArray.size();
        }

        public Object getItem(int position) 
        {
            return position;
        }

        public long getItemId(int position) 
        {
            return position;
        }

        public class ViewHolder
        {
            ImageView image;
        }               

        public View getView(final int position, View convertView, ViewGroup parent) 
        {
            ViewHolder holder;

            if(convertView == null)
            {
                holder = new ViewHolder();
                convertView = inflater.inflate(R.layout.page_list_item, null);

                holder.image = (ImageView)convertView.findViewById(R.id.image); 

                convertView.setTag(holder);
            }
            else
            {
                holder = (ViewHolder)convertView.getTag();
            }           



            // Load image from internalstoarage and display in image view   

            imageLoader.DisplayImage(m_DirectoryPath.getPath() + "/" + fileNameArray.get(position), holder.image, true);

            return convertView;
        }
}

画像ローダー クラスのコード

public class ImageLoader 
{
    MemoryCache memoryCache = new MemoryCache();
    private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
    ExecutorService executorService; 
    Context m_context;
    public ImageLoader(Context context)
    {
        m_context = context;
        executorService = Executors.newFixedThreadPool(5);
    }

    public void DisplayImage(String url, ImageView imageView, boolean useCachedImage)
    {
        imageViews.put(imageView, url);
        Bitmap bitmap = memoryCache.get(url);

        if(bitmap!=null && useCachedImage)
        {
            imageView.setImageBitmap(bitmap);
        }
        else
        {
            queuePhoto(url, imageView);
        }
    }

    private void queuePhoto(String url, ImageView imageView)
    {
        PhotoToLoad p = new PhotoToLoad(url, imageView);
        executorService.submit(new PhotosLoader(p));
    }

    private Bitmap getBitmap(String url) 
    {
        File filePath = new File(url);

        // from internal storage cache
        Bitmap b = decodeFile(filePath);
        if (b != null)
        {
            return b;
        }
        return null;
    }

    // decodes image and scales it to reduce memory consumption
    private Bitmap decodeFile(File filePath)
    {
        try 
        {
            // decode image size
             int Required_Height = 0;

             BitmapFactory.Options option = new BitmapFactory.Options();            
             Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(filePath), null, option);

             WindowManager wm = (WindowManager) m_context.getSystemService(Context.WINDOW_SERVICE);
             Display display = wm.getDefaultDisplay();

             if(display.getWidth() == 480)
             {
                 Required_Height = 150;
             }
             else if(display.getWidth() == 800)
             {
                 Required_Height = 200;
             }

             bitmap = Bitmap.createBitmap(bitmap, 0, 0, option.outWidth, Required_Height);

             return bitmap;
        } 
        catch (FileNotFoundException e){            
        }
        return null;
    }

    // Task for the queue
    private class PhotoToLoad
    {
        public String url;
        public ImageView imageView;
        public PhotoToLoad(String u, ImageView i)
        {
            url = u; 
            imageView=i;
        }
    }

    class PhotosLoader implements Runnable 
    {
        PhotoToLoad photoToLoad;
        PhotosLoader(PhotoToLoad photoToLoad)
        {
            this.photoToLoad = photoToLoad;
        }

        @Override
        public void run() 
        {
            if(imageViewReused(photoToLoad))
                return;

            Bitmap bmp = getBitmap(photoToLoad.url);
            memoryCache.put(photoToLoad.url, bmp);

            if(imageViewReused(photoToLoad))
                return;

            BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);
            Activity a = (Activity)photoToLoad.imageView.getContext();
            a.runOnUiThread(bd);
        }
    }

    boolean imageViewReused(PhotoToLoad photoToLoad)
    {
        String tag = imageViews.get(photoToLoad.imageView);

        if(tag == null || !tag.equals(photoToLoad.url))         
            return true;

        return false;
    }

    // Used to display bitmap in the UI thread
    class BitmapDisplayer implements Runnable
    {
        Bitmap bitmap;
        PhotoToLoad photoToLoad;
        public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}
        public void run()
        {
            if(imageViewReused(photoToLoad))
                return;

            if(bitmap != null)
                photoToLoad.imageView.setImageBitmap(bitmap);
        }
    }

    public void clearCache() 
    {
        memoryCache.clear();
    }

}
4

2 に答える 2

0

PhotosLoaderスレッド オブジェクトの優先順位を設定する必要があります。私はこのようにコンストラクタでそれをやっています。

// Make the background thread low priority. This way it will not affect the UI performance
mImageRequstController.setPriority(Thread.NORM_PRIORITY - 1);

優先順位を通常よりも低くすると、UI に影響を与えず、バックグラウンドで動作し続けます。

于 2012-08-23T06:43:32.123 に答える
0

何が起こっているかというと、速度上の理由から、ビューの外にあるリスト項目は必要になるまでロードされません。ユーザーがリスト項目をスクロールして表示すると、読み込まれます。ただし、SD カードからイメージをロードするのは時間がかかるため、ユーザーが遅延を感じるほどです。

コードは UI スレッドに画像をロードし、リストの更新とスムーズなスクロールをブロックします。代わりに、別のスレッドで画像を読み込む必要がありますが、UI スレッドのリスト項目には、画像が読み込まれるまで進行状況スピナーまたはその他の読み込みインジケーターのみが表示されます。また、リストと同様に、スレッドは一度にすべてではなく、リスト項目が表示されたときにのみ開始する必要があります。

于 2012-08-23T06:43:59.900 に答える