recyclerview vieholder is not getting recycled

时间:2019-01-18 19:02:21

标签: android memory-management android-recyclerview memory-leaks out-of-memory

developing an image picker using recyclerview with all images in devices for an android app, facing an issue when user scroll through images its memory usage keeps increasing eventually if lots of images there is oom exception, have searched for this issue over the internet, have applied several techniques but it is of little use, i have seen other app(whatsapp, olx) its picker scrolling is nice and no oom, i also tried dump heap in android studio to detect memory leakage, i found that there are as many viewholders as number of images, its not being recycled, am not able to find the reason, please help me in detecting the issue, attaching code..

/** adapter class for grid recyclerview*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private ArrayList<CreateList> galleryList;
    private Context context;
    private List<String> imageUrls = new ArrayList<>(3);
    private List<Integer> positionList = new ArrayList<>(3);
    int count = 0;
    RequestOptions options;
    RequestBuilder glide;
    RequestManager glideMain;
    int imgWidth;

public MyAdapter(Context context, ArrayList<CreateList> galleryList, RequestOptions options, RequestBuilder<Bitmap> glide, RequestManager glideMain, int imgWidth) {
    this.galleryList = galleryList;
    this.context = context;
    this.options = options;
    this.glide = glide;
    this.glideMain = glideMain;
    this.imgWidth = imgWidth;
}

@Override
public void onViewRecycled(@NonNull ViewHolder holder) {
        holder.img.setOnClickListener(null);
        holder.img.setColorFilter(null);
        holder.img.setImageDrawable(null);
        if(holder.title.getText().toString().equals("1")){

        }
        //holder.itemView.setOnClickListener(null);
        glideMain.clear(holder.img);
    super.onViewRecycled(holder);
}

@Override
public void onViewDetachedFromWindow(@NonNull ViewHolder holder) {
  /*  holder.img.setOnClickListener(null);
    holder.img.setColorFilter(null);*/
        holder.img.setImageDrawable(null);
        // holder.itemView.setOnClickListener(null);
        glideMain.clear(holder.img);
    super.onViewDetachedFromWindow(holder);
}

@Override
public void onViewAttachedToWindow(@NonNull final ViewHolder holder) {
  /*  holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            holder.handleThumbnail(view);
        }
    });*/
    super.onViewAttachedToWindow(holder);
}

public ArrayList<CreateList> getGalleryList() {
    return galleryList;
}

public void setGalleryList(ArrayList<CreateList> galleryList) {
    this.galleryList = galleryList;
}

public List<Integer> getPositionList() {
    return positionList;
}

public void setPositionList(List<Integer> positionList) {
    this.positionList = positionList;
}

public List<String> getImageUrls() {
    return imageUrls;
}

public void setImageUrls(List<String> imageUrls) {
    this.imageUrls = imageUrls;
}

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

@Override
public int getItemViewType(int position) {
    return position;
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.cell_layout, viewGroup, false);

    //img.setOnClickListener();

    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(final MyAdapter.ViewHolder viewHolder, int pos) {


    glide
            .load(galleryList.get(pos).getImage_Location())
            .thumbnail(0.1F)
            .apply(options)
            .into(viewHolder.img);

    if (positionList.contains(pos)){
        // view not selected
        //viewHolder.parent.setBackgroundColor(Color.LTGRAY);
        viewHolder.title.setVisibility(View.VISIBLE);
        viewHolder.title.setText(String.valueOf(positionList.indexOf(pos)+1));
        viewHolder.img.setColorFilter(viewHolder.getColorWithAlpha(Color.GREEN, 0.3f));
    }
}

@Override
public int getItemCount() {
    return galleryList.size();
}


public class ViewHolder extends RecyclerView.ViewHolder{
    private TextView title;
    private ImageView img;

    public ViewHolder(View view) {
        super(view);

        title = (TextView)view.findViewById(R.id.highlightText);
        img = (ImageView) view.findViewById(R.id.img);
       /* view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                handleThumbnail(v);
            }
        });*/
       /* img = view.findViewById(R.id.img);*/
        img.setLayoutParams(new ConstraintLayout.LayoutParams(imgWidth, imgWidth));
        /*img.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // This is OnClick of any list Item
                handleThumbnail(v);
            }

        });*/
      /*  img.setOnTouchListener(new View.OnTouchListener() {
            private Rect rect;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if(event.getAction() == MotionEvent.ACTION_DOWN){
                    img.setColorFilter(Color.argb(50, 0, 0, 0));
                    rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
                }
                if(event.getAction() == MotionEvent.ACTION_UP){
                    img.setColorFilter(Color.argb(0, 0, 0, 0));
                }
                if(event.getAction() == MotionEvent.ACTION_MOVE){
                    if(!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())){
                        img.setColorFilter(Color.argb(0, 0, 0, 0));
                    }
                }
                return false;
            }
        });*/
    }

    public void handleThumbnail(View v) {
        if(!imageUrls.contains(galleryList.get(getAdapterPosition()).getImage_Location())) {
            if(count<3) {
                positionList.add(getAdapterPosition());
                String selectedImgUrl = galleryList.get(getAdapterPosition()).getImage_Location();
                imageUrls.add(selectedImgUrl);
                //img.setBackground(context.getResources().getDrawable(R.drawable.button_background_checked));
                img.setColorFilter(getColorWithAlpha(Color.GREEN, 0.3f));
                //title.setVisibility(View.VISIBLE);
                //title.setText(String.valueOf(count+1));
                //View viewSelected =  gridRecycler.findViewHolderForAdapterPosition(position).itemView;
                title.setVisibility(View.VISIBLE);
                title.setText(String.valueOf(count+1));
                count++;


            } else {
                Toast.makeText().show();
            }
        } else {
            imageUrls.remove(galleryList.get(getAdapterPosition()).getImage_Location());
            positionList.remove(new Integer(getAdapterPosition()));
            //imageUrls.remove( Integer.parseInt(title.getText().toString()));
            title.setVisibility(View.GONE);
            count--;
           // img.setBackground(context.getResources().getDrawable(R.drawable.button_background));
            img.setColorFilter(Color.argb(0, 0, 0, 0));
            EventBus.getDefault().post(new MessageEvent(imageUrls, positionList));
        }
    }

    public int getColorWithAlpha(int color, float ratio) {
        int newColor = 0;
        int alpha = Math.round(Color.alpha(color) * ratio);
        int r = Color.red(color);
        int g = Color.green(color);
        int b = Color.blue(color);
        newColor = Color.argb(alpha, r, g, b);
        return newColor;
    }

}

activity code using background thread to load data and set in adapter:

private class PrepareData extends AsyncTask<Void, Void, Void> {
    @Override
    protected Void doInBackground(Void... voids) {

        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int imgWidth = (int) (displayMetrics.widthPixels*0.32);
        RequestOptions options = new RequestOptions()
                .diskCacheStrategy(DiskCacheStrategy.NONE)
                .override(imgWidth/3)
                .dontAnimate()
                .centerCrop()
                .skipMemoryCache(true);

        final RequestManager glide = Glide.with(gridRecycler.getContext());

        RequestBuilder builder = glide.asBitmap();
        gridRecycler.setHasFixedSize(true);
        final RecyclerView.LayoutManager layoutManager = new GridLayoutManager(gridRecycler.getContext(), 3);

        createLists = getAllFolderImages(this);

        adapter = new MyAdapter(this, createLists, options, builder, glide, imgWidth);

        gridRecycler.addOnScrollListener(new  RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
            }

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    glide.resumeRequests();
                }
                if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL || newState==AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
                    glide.pauseRequests();
                    System.gc();
                }
            }
        });
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                gridRecycler.setLayoutManager(layoutManager);
                gridRecycler.setAdapter(adapter);
                //put the code here that is giving exception
            }
        });

        return null;
    }
}

android profiling screen-shot, its visible that viewholder is consuming lots of memory and has lots of instances. enter image description here

0 个答案:

没有答案