John
John

Reputation: 4981

Android gridview scrolling bad loading image

I'm using Picasso to load all my images in a Gridview and DBFlow to save in the Local database. But I have a problem when I download the images for the first time and if I'm scrolling in the gridview. The next images have the previous images and 1 second later the good image is loaded. I have to scroll 5 times or more and when all images is loaded I don't have this problem but for the first time yes.

Have you an idea to optimize my code ?

Gridview

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@+id/gridview"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:columnWidth="130dp"
      android:numColumns="auto_fit"
      android:verticalSpacing="10dp"
      android:horizontalSpacing="10dp"
      android:stretchMode="columnWidth"
      android:gravity="center"
      android:background="@color/colorAppBackground"/>

Item Grid

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="130dp">

<ImageView
    android:id="@+id/iv_thumbnail"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:adjustViewBounds="true"
    android:scaleType="centerCrop"/>

<TextView
    android:id="@+id/text_thumb"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:gravity="center"
    android:textColor="@android:color/white"
    android:background="#99000000"/>

</RelativeLayout>

Activity

public class GalleryActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_gallery);

    Bundle bundle = getIntent().getExtras();
    int idAccount = bundle.getInt("idAccount");

    callAdminPictures(idAccount);
}

public void callAdminPictures(final int idAccount){

    // Build REST Adapter
    Retrofit restAdapter = new Retrofit.Builder()
            .baseUrl(Globals.SERVER_NAME)
            .addConverterFactory(SimpleXmlConverterFactory.create())
            .build();

    // Create the App Service
    ApplicationService appService = restAdapter.create(ApplicationService.class);

    // Call Get admin pictures WS
    Call<AdminPictures> getAdminPicturesWS = appService.getAdminPictures(idAccount);

    getAdminPicturesWS.enqueue(new Callback<AdminPictures>() {
        @Override
        public void onResponse(Call<AdminPictures> call, Response<AdminPictures> response) {
            AdminPictures apResponse = response.body();
            List<PictureInfos> pictureInfos = apResponse.getPicturesList();

            for (PictureInfos infos : pictureInfos) {
                if (infos.exists()) {
                    infos.update();
                } else {
                    infos.save();
                }
            }

            List<PictureInfos> tablePictureInfos = new Select()
                    .from(PictureInfos.class)
                    .where(PictureInfos_Table.idAccount.is("" + idAccount))
                    .orderBy(PictureInfos_Table.idPicture, false)
                    .queryList();

            GridView gridView = (GridView) findViewById(R.id.gridview);

            gridView.setAdapter(new ImageAdapter(GalleryActivity.this, tablePictureInfos));
            gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Toast.makeText(GalleryActivity.this, "" + position, Toast.LENGTH_SHORT).show();
                }
            });
        }

        @Override
        public void onFailure(Call<AdminPictures> call, Throwable t) {
            if (t.getMessage() != null) {
                Log.e("AdminPictures WS Fail", t.getMessage());
            }
        }
    });
}

Adapter

public class ImageAdapter extends BaseAdapter {

private Context mContext;
private LayoutInflater mLayoutInflater;
private List<PictureInfos> mPInfoList;
private boolean mToSave;

public ImageAdapter(Context context, List<PictureInfos> pInfoList) {
    mContext = context;
    mPInfoList = pInfoList;
    mLayoutInflater = LayoutInflater.from(context);
}

@Override
public int getCount() {
    return mPInfoList.size();
}

@Override
public Object getItem(int position) {
    return null;
}

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

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

    View view;
    final ImageView imageView;
    final TextView legend;

    if(convertView == null){
        view = mLayoutInflater.inflate(R.layout.thumbnail_gallery, parent, false);
    }else{
        view = convertView;
    }

    imageView = (ImageView) view.findViewById(R.id.iv_thumbnail);
    legend = (TextView) view.findViewById(R.id.text_thumb);

    final File file = new File(mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES), mPInfoList.get(position).getFilename());
    mToSave = !file.exists();

    Target target = new Target() {
        @Override
        public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
            if(mToSave) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            FileOutputStream fileOutput = new FileOutputStream(file);
                            Log.i("catch", mPInfoList.get(position).getFilename());
                            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutput);
                            fileOutput.close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }

            imageView.setImageBitmap(bitmap);
            if (mPInfoList.get(position).getFilename() != null) {
                legend.setText(mPInfoList.get(position).getLegend());
            }

        }

        @Override
        public void onBitmapFailed(Drawable errorDrawable) {

        }

        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {

        }
    };

    String pic = Globals.SERVER_NAME+Globals
                        .ACCOUNT_SERVER_PATH+mPInfoList
                        .get(position).getFolderPath()+"/"+
                        VgzTools.addSuffix(mPInfoList.get(position).getFilename(), "-thumb");

    imageView.setTag(target);

    if(!file.exists()){
        Picasso.with(mContext)
                .load(pic)
                .into(target);
        mToSave = true;
    }else{
        Picasso.with(mContext)
                .load(file)
                .into(target);
        mToSave = false;
    }

    return view;
}

Upvotes: 0

Views: 1168

Answers (2)

Ankit Aggarwal
Ankit Aggarwal

Reputation: 5375

Inside getView() put this line

imageView.setImageDrawable(null);

The previous image is coming because of view recycling. For each item you don't always get a new view, instead views are recycled to save memory. So once you scrolled the initially visible items, you will get the view from previous item which already has image set in it. So you have to remove it explicitly.

Upvotes: 2

Kas Hunt
Kas Hunt

Reputation: 3188

My guess is that because you're not explicitly clearing the imageView in your getView(), it's retaining the current image when it's recycled (IE - when it's passed in as convertView). Picasso will eventually call onBitmapLoaded(), but until then, you're left with the 'old' image.

Try explicitly clearing the image.

Upvotes: 1

Related Questions