Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/186.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android如何高效地将可绘制图像加载到imageview_Android_Performance_Android Imageview_Android Drawable - Fatal编程技术网

Android如何高效地将可绘制图像加载到imageview

Android如何高效地将可绘制图像加载到imageview,android,performance,android-imageview,android-drawable,Android,Performance,Android Imageview,Android Drawable,我需要将drawable文件夹中的一组图像加载到imageview列表中。我得到了一个java.lang.OutOfMemoryError:分配17280012字节分配失败,有8452164个空闲字节和8MB,直到OOM错误 下面是一个数组文件,其中列出了可绘制文件夹中需要加载的所有图像名称 <?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="photo_frames"&g

我需要将drawable文件夹中的一组图像加载到imageview列表中。我得到了一个java.lang.OutOfMemoryError:分配17280012字节分配失败,有8452164个空闲字节和8MB,直到OOM错误

下面是一个数组文件,其中列出了可绘制文件夹中需要加载的所有图像名称

 <?xml version="1.0" encoding="utf-8"?>
 <resources>
<string-array name="photo_frames">
    <item>pf1</item>
    <item>pf2</item>
    <item>pf3</item>
    <item>pf4</item>
    <item>pf5</item>
    <item>pf6</item>
    <item>pf7</item>
    <item>pf8</item>
    <item>pf9</item>
    <item>pf10</item>
    <item>pf11</item>
    <item>pf12</item>
     </string-array>
 </resources>

如果我有一些图片,它加载的很好,但是有点滞后。当有更多图像要加载到imageView时,它会返回一个错误,谢谢。

17280012字节相当于2078 x 2078像素的图像这比大多数设备屏幕的分辨率都高。您应该一次加载0-1个图像,而不是12个图像

如果您的图像具有那样的高分辨率,请降低其分辨率


如果您的图像分辨率已经较低,但您将其置于
res/drawable/
中,请将其移动到
res/drawable nodpi/
或计划为不同密度创建不同版本的可绘制图像。没有位图属于
res/drawable/
,因为这只是
res/drawable mdpi/
的同义词,因此Android将在密度更高的屏幕上对图像重新采样。

17280012字节相当于2078 x 2078像素图像这比大多数设备屏幕的分辨率都高。您应该一次加载0-1个图像,而不是12个图像

如果您的图像具有那样的高分辨率,请降低其分辨率


如果您的图像分辨率已经较低,但您将其置于
res/drawable/
中,请将其移动到
res/drawable nodpi/
或计划为不同密度创建不同版本的可绘制图像。没有位图属于
res/drawable/
,因为这只是
res/drawable mdpi/
的同义词,所以Android将在高密度屏幕上对图像进行重采样。

这取决于图像的大小,当您在计算机上读取图像大小时,Android似乎会分配比图像大小多一点的空间。所以

  • 你可以用小一点的图像
  • 谷歌实际上已经发布了一个避免OutOfMemory错误的指南 这将帮助很多,虽然我不得不使用较小的图像大小 还有
  • 一种几乎肯定有效的方法是设置 在清单中,在应用程序之间 标签。这将增加你的堆大小,但可能会使你的应用程序滞后 很少
  • 您可以尝试使用Glide,谷歌推荐的库来加载图像

也许对你来说,这些想法的结合会起作用。

这取决于你的图像有多大,当你在电脑上读取图像大小时,Android似乎会分配比图像大小多一点的空间。所以

  • 你可以用小一点的图像
  • 谷歌实际上已经发布了一个避免OutOfMemory错误的指南 这将帮助很多,虽然我不得不使用较小的图像大小 还有
  • 一种几乎肯定有效的方法是设置 在清单中,在应用程序之间 标签。这将增加你的堆大小,但可能会使你的应用程序滞后 很少
  • 您可以尝试使用Glide,谷歌推荐的库来加载图像

也许对你来说,这些想法的结合会起作用。

你也可以使用缓存机制

下面的一个示例可能会让您了解如何使用图像缓存:

public class FlowerAdapter extends ArrayAdapter<Flower> {

    private Context context;
    private List<Flower> flowerList;

    //set the LRU (Least Recently Used) object as an image cache
    private LruCache<Integer,Bitmap> imageCache;

    public FlowerAdapter(Context context, int resource, List<Flower> objects) {
        super(context, resource, objects);
        this.context = context;
        this.flowerList = objects;

        //initialize the cache in the constructor
        //determine the maximum amount of memory of the device
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory());
        //set the cache size to be one-eight of the maximum memory
//      final int cacheSize = maxMemory/9999999; //using this number you can see the effects
        final int cacheSize = maxMemory/8; //real-life situation
        //create the image cache (instantiate it)
        imageCache = new LruCache<>(cacheSize);
    }

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

        LayoutInflater inflater = 
                (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.item_flower, parent, false);

        //Display flower name in the TextView widget
        Flower flower = flowerList.get(position);
        TextView tv = (TextView) view.findViewById(R.id.textView1);
        tv.setText(flower.getName());

        //Display flower photo in ImageView widget
        //verify if the flower exists in cache
        Bitmap bitmap = imageCache.get(flower.getProductId());
        if (bitmap != null) {
            ImageView image = (ImageView) view.findViewById(R.id.imageView1);
            image.setImageBitmap(bitmap);
        }
        else {
            FlowerAndView container = new FlowerAndView();
            container.flower = flower;
            container.view = view;

            ImageLoader loader = new ImageLoader();
            loader.execute(container);
        }


        return view;
    }

    class FlowerAndView {
        public Flower flower;
        public View view;
        public Bitmap bitmap;
    }

    private class ImageLoader extends AsyncTask<FlowerAndView, Void, FlowerAndView> {

        @Override
        protected FlowerAndView doInBackground(FlowerAndView... params) {

            FlowerAndView container = params[0];
            Flower flower = container.flower;

            try {
                String imageUrl = MainActivity.PHOTOS_BASE_URL + flower.getPhoto();
                InputStream in = (InputStream) new URL(imageUrl).getContent();
                Bitmap bitmap = BitmapFactory.decodeStream(in);
                flower.setBitmap(bitmap);
                in.close();
                container.bitmap = bitmap;
                return container;
            } catch (Exception e) {
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPostExecute(FlowerAndView result) {
            ImageView image = (ImageView) result.view.findViewById(R.id.imageView1);
            image.setImageBitmap(result.bitmap);
//          result.flower.setBitmap(result.bitmap);
            //put the image in the cache
            imageCache.put(result.flower.getProductId(),result.bitmap);
        }

    }

}
公共类FlowerAdapter扩展了ArrayAdapter{
私人语境;
私人名册;
//将LRU(最近使用最少的)对象设置为图像缓存
专用LruCache图像缓存;
公共适配器(上下文、int资源、列表对象){
超级(上下文、资源、对象);
this.context=上下文;
this.flowerList=对象;
//初始化构造函数中的缓存
//确定设备的最大内存量
final int maxMemory=(int)(Runtime.getRuntime().maxMemory());
//将缓存大小设置为最大内存的八分之一
//final int cacheSize=maxMemory/9999999;//使用此数字可以看到效果
final int cacheSize=maxMemory/8;//实际情况
//创建映像缓存(实例化它)
imageCache=新的LruCache(缓存大小);
}
@凌驾
公共视图getView(int位置、视图转换视图、视图组父视图){
排气充气机
(LayoutInflater)context.getSystemService(Activity.LAYOUT\u flater\u SERVICE);
视图=充气机。充气(R.layout.item_-flower,父项,false);
//在TextView小部件中显示花朵名称
花卉=花卉列表。获取(位置);
TextView tv=(TextView)view.findViewById(R.id.textView1);
tv.setText(flower.getName());
//在ImageView小部件中显示花朵照片
//验证缓存中是否存在花
位图Bitmap=imageCache.get(flower.getProductId());
if(位图!=null){
ImageView image=(ImageView)view.findViewById(R.id.imageView1);
setImageBitmap(位图);
}
否则{
FlowerAndView容器=新建FlowerAndView();
容器。花=花;
container.view=视图;
ImageLoader=新的ImageLoader();
执行(容器);
}
返回视图;
}
类和视图{
公共花卉;
公众观点;
公共位图;
}
私有类ImageLoader扩展了异步任务{
@凌驾
受保护的花卉和视图背景(花卉和视图…参数){
FlowerAndView容器=参数[0];
花=容器。花;
试一试{
字符串imageUrl=MainActivity.PHOTOS\u BASE\u URL+flower.getPhoto();
InputStream in=(InputStream)新URL(imageUrl)。
public class FlowerAdapter extends ArrayAdapter<Flower> {

    private Context context;
    private List<Flower> flowerList;

    //set the LRU (Least Recently Used) object as an image cache
    private LruCache<Integer,Bitmap> imageCache;

    public FlowerAdapter(Context context, int resource, List<Flower> objects) {
        super(context, resource, objects);
        this.context = context;
        this.flowerList = objects;

        //initialize the cache in the constructor
        //determine the maximum amount of memory of the device
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory());
        //set the cache size to be one-eight of the maximum memory
//      final int cacheSize = maxMemory/9999999; //using this number you can see the effects
        final int cacheSize = maxMemory/8; //real-life situation
        //create the image cache (instantiate it)
        imageCache = new LruCache<>(cacheSize);
    }

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

        LayoutInflater inflater = 
                (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.item_flower, parent, false);

        //Display flower name in the TextView widget
        Flower flower = flowerList.get(position);
        TextView tv = (TextView) view.findViewById(R.id.textView1);
        tv.setText(flower.getName());

        //Display flower photo in ImageView widget
        //verify if the flower exists in cache
        Bitmap bitmap = imageCache.get(flower.getProductId());
        if (bitmap != null) {
            ImageView image = (ImageView) view.findViewById(R.id.imageView1);
            image.setImageBitmap(bitmap);
        }
        else {
            FlowerAndView container = new FlowerAndView();
            container.flower = flower;
            container.view = view;

            ImageLoader loader = new ImageLoader();
            loader.execute(container);
        }


        return view;
    }

    class FlowerAndView {
        public Flower flower;
        public View view;
        public Bitmap bitmap;
    }

    private class ImageLoader extends AsyncTask<FlowerAndView, Void, FlowerAndView> {

        @Override
        protected FlowerAndView doInBackground(FlowerAndView... params) {

            FlowerAndView container = params[0];
            Flower flower = container.flower;

            try {
                String imageUrl = MainActivity.PHOTOS_BASE_URL + flower.getPhoto();
                InputStream in = (InputStream) new URL(imageUrl).getContent();
                Bitmap bitmap = BitmapFactory.decodeStream(in);
                flower.setBitmap(bitmap);
                in.close();
                container.bitmap = bitmap;
                return container;
            } catch (Exception e) {
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPostExecute(FlowerAndView result) {
            ImageView image = (ImageView) result.view.findViewById(R.id.imageView1);
            image.setImageBitmap(result.bitmap);
//          result.flower.setBitmap(result.bitmap);
            //put the image in the cache
            imageCache.put(result.flower.getProductId(),result.bitmap);
        }

    }

}
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer-array name="photo_frames">
        <item>@drawable/pf1</item>
        <item>@drawable/pf2</item>
        .....
    </integer-array>
</resources>
// load array into CONSTRUCTOR
TypedArray photoFrameArray = getResources().obtainTypedArray(R.array.photo_frames);

// or set you ImageView's resource to the id
imgPhotoFrames.setImageResource(photoFrameArray.getResourceId(position, R.drawable.default_drawable));
photoFrameArray.recycle();