Я использую этот ArrayAdapter для асинхронной загрузки миниатюр

public class CourierArrayAdapter extends ArrayAdapter<Courier> {
    private Map<String, Bitmap> bitmaps = new HashMap<>();

    private static class ViewHolder{
        TextView txtViewName;
        TextView txtViewNumber;
        CircleImageView imageViewPic;
        int position;
    }

    public CourierArrayAdapter(Context context, List<Courier> requests) {
        super(context, -1, requests);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
        Courier request = getItem(position);

        if (convertView == null) {
            viewHolder = new ViewHolder();
            LayoutInflater layoutInflater = LayoutInflater.from(getContext());
            convertView = layoutInflater.inflate(R.layout.list_item_courier, parent, false);
            viewHolder.txtViewName = (TextView) convertView.findViewById(R.id.textView_list_item_courier_name);
            viewHolder.txtViewNumber = (TextView) convertView.findViewById(R.id.textView_list_item_courier_number);
            viewHolder.imageViewPic = (CircleImageView) convertView.findViewById(R.id.imageView_list_item_courier_pic);
            convertView.setTag(viewHolder);
        }
        else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        viewHolder.txtViewName.setText(request.name);
        viewHolder.txtViewNumber.setText(request.number);
        viewHolder.position = position;

        if (bitmaps.containsKey(request.picURL)) {
            viewHolder.imageViewPic.setImageBitmap(bitmaps.get(request.picURL));
        }
        else
            new LoadImageTask(position, viewHolder).execute(request.picURL);

        return convertView;
    }

    private class LoadImageTask extends AsyncTask<String, Void, Bitmap> {

        private int mPosition;
        private ViewHolder mViewHolder;


        public LoadImageTask(int position, ViewHolder holder) {
            this.mPosition = position;
            this.mViewHolder = holder;
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            Bitmap bitmap = null;
            HttpURLConnection connection = null;

            try {
                URL url = new URL(params[0]); // create URL for image

                connection = (HttpURLConnection) url.openConnection();

                InputStream inputStream = connection.getInputStream();
                try {
                    bitmap = BitmapFactory.decodeStream(inputStream);
                    bitmaps.put(params[0], bitmap);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                finally {
                    inputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                connection.disconnect(); // close the HttpURLConnection
            }

            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            if (mViewHolder.position == mPosition)
                mViewHolder.imageViewPic.setImageBitmap(bitmap);
        }
    }
}

Как видите, я загружаю эти изображения с помощью свойства picURL и загружаю их с помощью частного класса AsyncTask. Проблема в том, что я получаю OutOfMemoryException следующее сообщение об ошибке:

FATAL EXCEPTION: AsyncTask #3
  java.lang.RuntimeException: An error occured while executing doInBackground()
      at android.os.AsyncTask$3.done(AsyncTask.java:304)
      at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
      at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
      at java.util.concurrent.FutureTask.run(FutureTask.java:242)
      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
      at java.lang.Thread.run(Thread.java:818)
   Caused by: java.lang.OutOfMemoryError: Failed to allocate a 37602252 byte allocation with 16776720 free bytes and 29MB until OOM
      at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
      at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
      at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:863)
      at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:839)
      at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:877)
      at net.faraznet.provider.arrayadapters.CourierArrayAdapter$LoadImageTask.doInBackground(CourierArrayAdapter.java:99)
      at net.faraznet.provider.arrayadapters.CourierArrayAdapter$LoadImageTask.doInBackground(CourierArrayAdapter.java:76)
      at android.os.AsyncTask$2.call(AsyncTask.java:292)
      at java.util.concurrent.FutureTask.run(FutureTask.java:237)
      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
      at java.lang.Thread.run(Thread.java:818)

Изображения немного большие по размеру, и, если возможно, я не меняю их размер перед загрузкой в ​​память, но проблема в том, что я не знаю, как выполнить эту задачу или какие-либо другие решения моей проблемы.

0
roostaamir 8 Сен 2016 в 10:06

4 ответа

Лучший ответ

Вы можете использовать стороннюю библиотеку с именем Glide, рекомендованную Google. Чтобы добавить эту библиотеку, добавьте следующую зависимость в файл build.gradle в модуле app.

dependencies {
    compile 'com.github.bumptech.glide:glide:3.5.2'
    compile 'com.android.support:support-v4:22.0.0'
}

А затем вы можете просто загрузить изображение следующим образом

Glide.with(context)
    .load(request.picURL)
    .into(viewHolder.imageViewPic);
0
Mithun Sarker Shuvro 8 Сен 2016 в 07:14

Если вы можете использовать собственные библиотеки, используйте Glide.

Glide более эффективен с точки зрения производительности и управления памятью по сравнению с изображениями, чем Picasso. проверьте это сравнение

Все шаги четко определены в github для использования Glide в приложении.

В качестве альтернативы вы можете увеличить размер кучи приложения с помощью android: largeHeap = "true" < / а>. Но это не будет работать на каких-либо устройствах до Honeycomb.

На устройствах до 2.3 вы можете использовать класс VMRuntime. но это не будет работать с Gingerbread и выше.

VMRuntime.getRuntime().setMinimumHeapSize(BIGGER_SIZE);
1
Sreehari 8 Сен 2016 в 07:18

Недавно я достиг этого, поэтому лучший способ добиться этого - использовать Picasso, используйте этот код в своем адаптере массива

Picasso.with(this)
            .load(url)
            .into(new Target() {
                @Override
                public void onBitmapLoaded (final Bitmap bitmap, Picasso.LoadedFrom from){
            /* Save the bitmap or do something with it here */

                    //Set it in the ImageView

                }

                @Override
                public void onPrepareLoad(Drawable placeHolderDrawable) {

                }

                @Override
                public void onBitmapFailed(Drawable errorDrawable) {

                }
            });

Используйте это в манифесте перед Application.

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

Добавьте следующую строку в dependencies или Gradle.

compile 'com.squareup.picasso:picasso:2.5.2'

Для получения информации перейдите по следующим ссылкам

http://square.github.io/picasso/

https://github.com/square/picasso

Я надеюсь, что это будет полезно.

0
Raju 8 Сен 2016 в 07:24