Sid Sid - 12 days ago 12
Android Question

Lazy Loading not working properly

I am showing a list of contacts in a recyclerview. I am showing contact profile images, first I am loading these images from server and then storing these images in an external memory.

Then Loading the images from external storage. I can see the images loaded, but as I scroll I can see some images for a second or two then they get disappear and I can see the default image icon.

public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactHolder> {


private List<Contact> contactList;
File myDir1;
private Activity mContext;

private Boolean fileExists;
private File file;
private static final int MY_PERMISSIONS_REQUEST_CALL= 20;

public ContactAdapter(Activity context, List<Contact> contactList) {
this.contactList = contactList;
this.mContext = context;
}

@Override
public ContactHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_layout,null);
ContactHolder mh = new ContactHolder(v);

return mh;
}

@Override
public void onBindViewHolder(final ContactHolder contactHolder, int i) {

final Contact contact = contactList.get(i);
// Log.e("Imagename",""+"http://xesoftwares.co.in/contactsapi/profile_images/85368a5bbd6cffba8a3aa202a80563a2.jpg");//+feedItem.getThumbnail());

Target target = new Target() {

@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {

// your code here ...

bitmap = Bitmap.createScaledBitmap(bitmap,(int)(bitmap.getWidth()*0.8), (int)(bitmap.getHeight()*0.8), true);

contactHolder.thumbnail.setImageBitmap(bitmap);

Log.e("ProfileImage", contact.getmProfileImage());

SaveImages(bitmap, contact.getmProfileImage());

}

@Override
public void onBitmapFailed(Drawable errorDrawable) {
contactHolder.thumbnail.setImageDrawable(errorDrawable);
// do error handling as required
}

@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
contactHolder.thumbnail.setImageDrawable(placeHolderDrawable);
}
};

contactHolder.thumbnail.setTag(target);

String url = ServiceUrl.getBaseUrl() + ServiceUrl.getImageUserUrl() + contact.getmProfileImage();

Log.e("url",url);

if(contact.getmProfileImage().equals(""))

{

file = new File("");

fileExists = file.exists();

contactHolder.thumbnail.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_account_circle_black_48dp));
}
else {

file = new File(Environment.getExternalStorageDirectory() + "/ContactProfileImages/" + contact.getmProfileImage());

fileExists = file.exists();
}

if(fileExists)
{

Log.e("fileExists",file.getAbsolutePath());

BitmapFactory.Options bmOptions = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeFile(file.getPath(), bmOptions);

contactHolder.thumbnail.setImageBitmap(bitmap);

}

else {

Log.e("Picasso",file.getAbsolutePath());

Picasso.with(mContext).load(url)
.error(R.drawable.ic_account_circle_black_24dp)
.placeholder(R.drawable.ic_account_circle_black_24dp)
.into(target);
}

contactHolder.title.setText(contact.getmUserName());
//feedListRowHolder.genre.setText(Html.fromHtml(feedItem.getGenre()));

}

@Override
public int getItemCount() {
return (null != contactList ? contactList.size() : 0);
}

public void SaveImages(Bitmap bitmap,String profileName)
{

try {
String root = Environment.getExternalStorageDirectory().getPath();
File myDir = new File(root +"/ContactProfileImages");

if (!myDir.exists()) {
myDir.mkdirs();
}

// String name = new Date().toString();=
String name = profileName;
File myDir1 = new File(myDir, name);
if(!myDir1.exists()) {
FileOutputStream out = new FileOutputStream(myDir1);
bitmap.compress(Bitmap.CompressFormat.PNG,100,out);

out.flush();
out.close();
}


} catch(Exception e){
// some action
}

//myDir1= imageFilePath1.getprofile();

}


public class ContactHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
protected CircleImageView thumbnail;
protected TextView title;

public ContactHolder(View view) {
super(view);
this.thumbnail = (CircleImageView) view.findViewById(R.id.thumbnail);
this.title = (TextView) view.findViewById(R.id.title);
view.setOnClickListener(this);

}

@Override
public void onClick(View v) {

final Contact contact = contactList.get(getAdapterPosition());

final Dialog dialog = new Dialog(mContext);
dialog.setCanceledOnTouchOutside(true);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.custom);
final Window window = dialog.getWindow();

WindowManager.LayoutParams wlp =window.getAttributes();
wlp.gravity = Gravity.CENTER_HORIZONTAL|Gravity.TOP;
wlp.y=320;
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.setAttributes(wlp);

// set the custom dialog components - text, image and button
TextView txtusername = (TextView) dialog.findViewById(R.id.txtusername);
TextView txtmobile = (TextView) dialog.findViewById(R.id.txtmobile);
TextView txtemail = (TextView) dialog.findViewById(R.id.txtemail);

txtusername.setText(contact.getmUserName());
txtemail.setText(contact.getmEmailId());
txtmobile.setText(contact.getmMobileNo());

SquareImageView image = (SquareImageView) dialog.findViewById(R.id.image);
ImageView image1 = (ImageView) dialog.findViewById(R.id.image1);
ImageView image2 = (ImageView) dialog.findViewById(R.id.image2);
ImageView image3 = (ImageView) dialog.findViewById(R.id.image3);

if(contact.getmProfileImage().equals(""))

{
image.setImageDrawable(ContextCompat.getDrawable(mContext,R.drawable.profile_icon));
}
else {
File file = new File(Environment.getExternalStorageDirectory() + "/ContactProfileImages/" + contact.getmProfileImage());
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeFile(file.getPath(), bmOptions);

image.setImageBitmap(bitmap);
}

image1.setImageResource(R.drawable.ic_call_black_24dp);
image2.setImageResource(R.drawable.ic_textsms_black_24dp);
image3.setImageResource(R.drawable.ic_email_black_24dp);

image2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

Uri sms_uri = Uri.parse("smsto:" + contact.getmMobileNo());
Intent sms_intent = new Intent(Intent.ACTION_SENDTO, sms_uri);
mContext.startActivity(sms_intent);
dialog.dismiss();

}
});

image1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + contact.getmMobileNo()));
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
mContext.startActivity(intent);
dialog.dismiss();
}
});

image3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent email = new Intent(Intent.ACTION_SEND);
email.putExtra(Intent.EXTRA_EMAIL, new String[]{contact.getmEmailId()});
email.setType("message/rfc822");
mContext.startActivity(Intent.createChooser(email, "Choose an Email client :"));

}
});

Button dialogButton = (Button) dialog.findViewById(R.id.dialogButtonOK);
// if button is clicked, view all information custom dialog

dialogButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

((MainActivity)mContext).finish();

Intent intent = new Intent(mContext,DetailViewActivity.class);
intent.putExtra("contact",contact);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
mContext.startActivity(intent);

dialog.dismiss();


}
});
dialog.show();

}
}
}


EDIT : I searched for the same issue with picasso library, when we load images from server, for this I got the solution from SO as :

recyclerView.setHasFixedSize(true);
recyclerView.setItemViewCacheSize(20);
recyclerView.setDrawingCacheEnabled(true);
recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);


And this worked when I am loading the images from server, but when I am loading the images from the external storage still the problem exists.

Can anyone help with this please? Thank you..

Sam Sam
Answer

Then Loading the images from external storage. I can see the images loaded, but as I scroll I can see some images for a second or two then they get disappear and I can see the default image icon.

This is becuase you are using Target callback in picasso. And callbacks are called little bit late when you are scrolling the list. Just remove the target and use the imageview into Picasso, it should work fine. Also you don't need to cache bitmaps on your own as Picasso does it for you.

@Override
    public void onBindViewHolder(final ContactHolder contactHolder, int i) {

        final Contact contact = contactList.get(i);
        //  Log.e("Imagename",""+"http://xesoftwares.co.in/contactsapi/profile_images/85368a5bbd6cffba8a3aa202a80563a2.jpg");//+feedItem.getThumbnail());


        String url = ServiceUrl.getBaseUrl() + ServiceUrl.getImageUserUrl() + contact.getmProfileImage();

        Log.e("url",url);

        if(contact.getmProfileImage().equals(""))

        {

            file = new File("");

            fileExists = file.exists();

            contactHolder.thumbnail.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_account_circle_black_48dp));
        }
        else {

            file = new File(Environment.getExternalStorageDirectory() + "/ContactProfileImages/" + contact.getmProfileImage());

            fileExists = file.exists();
        }


            Log.e("Picasso",file.getAbsolutePath());

            Picasso.with(mContext).load(url)
                    .error(R.drawable.ic_account_circle_black_24dp)
                    .placeholder(R.drawable.ic_account_circle_black_24dp)
                    .into(contactHolder.thumbnail);


        contactHolder.title.setText(contact.getmUserName());
        //feedListRowHolder.genre.setText(Html.fromHtml(feedItem.getGenre()));

    }