Android - Recyclerview adapter show Images from External Storage - android

I want create image gallery with RecyclerView where use images from phone. I didn't find any RecyclerView adapter which fill image with File type. Is it possible?

For basic functionality of RecyclerView adapters: http://guides.codepath.com/android/Using-the-RecyclerView
In your onBindViewHolder, you can get your image like this:
String path = Environment.getExternalStorageDirectory() + "/myImage.jpg";
Bitmap bitmap = BitmapFactory.decodeFile(path);
(more info on getting images from external storage)
and use it with an ImageView or something similar.

It's works
#Override
public void onBindViewHolder(RecyclerViewHolders holder, int position) {
holder.countryName.setText("Img");
Bitmap bitmap = BitmapFactory.decodeFile(newList.get(position));
holder.countryPhoto.setImageBitmap(bitmap);
}

Related

How to correctly download firebase storage images into recycelrView

I have recyclerview and in every row I have an image that I load with firebase storage. It seems like the image loading is affecting the scrolling performance of the recyclerView.
I am using glide to load the images that I got from firebase inside onBindViewHolder by calling imageLoadGlide method like this:
//Download image from firebase Storage and set gameImage("ImageView") image.
private void imageLoadGlide(DocumentSnapshot documentSnapshot, final QuestionsHolder questionsHolder) {
//for firebase storage
FirebaseStorage storage = FirebaseStorage.getInstance();
// Create a storage reference from our app
StorageReference storageRef = storage.getReference();
storageRef.child(documentSnapshot
.get("image").toString())
.getDownloadUrl()
.addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
//this part is loading image from url library
Glide
.with(context.getApplicationContext()) // pass Context
.load(uri)// pass the image url
.centerCrop() // optional scaletype
.crossFade() //optional - to enable image crossfading
.transform(new CircleTransform(context))//transfoms the imageView onto circle with the custon class CircleTransform
.into(questionsHolder.gameImage); // the ImageView to which the image is to be loaded
//stop the loading bar from spinning
questionsHolder.loadProgress.setVisibility(View.GONE);
}
});
}
The download works fine but it makes the scrolling super slow.
I have no idea why this is happening because I compress the images before uploading them so I don't think that this is a problem of image weight.
The image compress is made like this :
Bitmap bitmap = ((BitmapDrawable) questionImage.getDrawable()).getBitmap();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 10, baos);
byte[] data = baos.toByteArray();
UploadTask uploadTask = mountainImagesRef.putBytes(data);
Any ideas on why this is happening and how can I avoid this?
Here is onBindViewHolder for #Vadim Eksler request:
#Override
public void onBindViewHolder(#NonNull final QuestionsHolder holder, final int position) {
holder.gameImage.setImageBitmap(null);
setInfoForViews(holder, result.get(position));
imageLoadGlide(result.get(position), holder);
setOnClicksListners(holder, position);
setRankTextView(position, holder);
if (position == result.size() - 1 && !endOfDocs && next != null) {
loadMoreDocs(position);
}
}
This answer is based on all the comments together.
So as mentioned in the comments what I did wrong is that every time that onBindViewHolder was called I have pulled the image from firebase again and again - this causes poorly recyclerView performance.
What I did to fix it:
I have used flyweight design pattern to load the image only for the first time from firebase and after that simply recycle this image for the next time onBindViewHolder will get called.
First I created a map as a global variable:
private Map<String, Bitmap> flyweight = new HashMap<>();
after that when the image is loaded from the first time I will save it for later when onBindViewHolder will get called again:
Inside onBindViewHolder :
if (flyweight.get(result.get(position).get("image").toString()) == null) {
imageLoadGlide(result.get(position), holder); // load the image
} else {
//recycle the image that i already have
holder.gameImage.setImageBitmap(flyweight.get(result.get(position).get("image").toString()));
}
And the last thing is to add my image to the map that I created after the image is successfully pulled :
flyweight.put(documentSnapshot.get("image").toString(), resource);

Load bitmap with picasso into ImageView

i'm building a file explorer application, and i'm trying to load large amount of images (more then 5000...), i'm trying to use picasso but its still slow so i'm trying to load a Thumbimage with picasso and not the whole image file..
....
ImageItem item = data.get(position);
ImageView imageView = holder.image;
Bitmap ThumbImage = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(item.getImage().getPath()), 100, 100);
Picasso.with (context) .load (ThumbImage ) .into (imageView); /*/ doesnt work.. cant load ThumbImage with Picasso
Picasso.with (context) .load (item.getImage()) .into (imageView); //work, but too slow
i cant figure out how can i load Thumbimage into ImageView with Picasso.. there is any why to do that? another way to load faster my images?
First I would recommend using RecyclerView instead of a GridView, considering it handles a lot of the memory management for you. Instead of having to load all of the images at once (or manage it yourself), it will only load the images that fit on the screen. And you can use a GridLayoutManager to have it appear just as it would in a GridView.
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler);
recyclerView.setLayoutManager(new GridLayoutManager(context, 4);
recyclerView.setAdapter(new MyRecyclerViewAdapter(context, data);
Also, let Picasso handle converting the image for you, this way you do not need to use ThumbnailUtils. Picasso handles image resizing and memory management with the resize() function:
String uri = data.get(position);
Picasso.with(context).load(new File(uri)).resize(100, 100)
.centerCrop().into(imageView)
You can do this in the onBindViewHolder() method of the RecyclerView.Adapter so that each image will only be loaded when the View has to be shown.
I am not sure how you are obtaining the images currently, but if you do not know how to obtain the URI of the image, this should work:
String[] projection = {"*"};
List<String> data = new ArrayList<>();
Cursor cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
if(cursor.moveToFirst()) {
do {
data.add(cursor.getString(cursor
.getColumnIndex(MediaStore.Images.Media.DATA)));
} while(cursor.moveToNext());
}
I do not know if this will fix the problem you have with Picasso not loading the images, but if it does not post a stack trace and we can try to figure that out.

Universal Image Loader and BitmapDrawable

We have an image in B64, an we want to use that image as loading image in Universal Image Loader while a better image isn't loaded from an url. So we create a bitmap from that url in b64 and convert it into a BitmapDrawable.
The result is shown fine if I do:
imageView.setImageDrawable(bitmapDrawable)
But, on DisplayImageOptions, if I set that bitmapDrawable as image on loading, the image is never shown. I'm doing the following:
final DisplayImageOptions imageOptions = mDisplayImageOptionsDefaultBuilder.
.showImageOnLoading(bitmapDrawable)
.showImageOnFail(bitmapDrawable)
.showImageForEmptyUri(bitmapDrawable)
.build()
As you can see, I am setting the bitmap drawable not only as image when loading, but as image when fails too (as we don't want that image to change in case of error while loading the better image from an url). The result of that is that the bitmap drawable is never shown. What are we doing wrong?
UPDATE:
After debugging what was happening I've seen that the problem is not the bitmap drawable, it is supported and working fine. The problem was that I am using a default display options builder (mDisplayImageOptionsDefaultBuilder), than at some point did:
final DisplayImageOptions imageOptions = mDisplayImageOptionsDefaultBuilder.
.showImageOnLoading(loadingResource)
.showImageOnFail(errorResource)
.showImageForEmptyUri(errorResource)
.build()
So there's a bug in Universal Image Loader, because now I'm creating a display image options with:
.showImageOnLoading(bitmapDrawable)
Another "solution" is do:
final DisplayImageOptions imageOptions = mDisplayImageOptionsDefaultBuilder.
.showImageOnLoading(0)
.showImageOnLoading(loadingResource)
.showImageOnFail(errorResource)
.showImageForEmptyUri(errorResource)
.build()
But internally it stores that there's a resource stored, so my drawable is not shown but the stored resource instead. Creating a new DisplayImageOptionsBuilder worked for me, but it would be nice that if the showImageOnLoading is set with a drawable, then the old resource was automatically cleared.
Thanks in advance.
UIL only supports the following schemes:
"h t t p://site.com/image.png" // from Web
"file:///mnt/sdcard/image.png" // from SD card
"file:///mnt/sdcard/video.mp4" // from SD card (video thumbnail)
"content://media/external/images/media/13" // from content provider
"content://media/external/video/media/13" // from content provider (video thumbnail)
"assets://image.png" // from assets
"drawable://" + R.drawable.img // from drawables (non-9patch images)
Use these schemes.
Universal Image Loader also provide to use the Background functionality.Please check the below coed for it:-
Here Uri is the path of the folder image OR the URL of the image.
imageLoader.loadImage(YOUR_URL, new SimpleImageLoadingListener() {
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
layout.setBackgroundDrawable(new BitmapDrawable(loadedImage));
}
});

Save RelativeLayout with content as an image

I have relativelayout (A template) where it contain textboxes whose content is populated at runtime.On clicking save button,I need to save the template as an image in SD card.Is it possible.
I referred the below link:
How do I convert a RelativeLayout with an Imageview and TextView to a PNG image?
But the image saved cannot be opened.
Is my requiremnet possible.Or else please advice how can I achieve it.
I am behind this for several days.I am new to ANdroid.Please help.
Thanks in Advance.
You can pass any view or layout to devBitmapFrmViewFnc function and get the bitmap. You can save the bitmap in jpeg using devImjFylFnc.
|==| Dev Bitmap Image from View :
Bitmap devBitmapFrmViewFnc(View viewVar)
{
viewVar.setDrawingCacheEnabled(true);
viewVar.buildDrawingCache();
return viewVar.getDrawingCache();
}
|==| Create a JPG File from Bitmap :
static void devImjFylFnc(String MobUrlVar, Bitmap BitmapVar)
{
try
{
FileOutputStream FylVar = new FileOutputStream(MobUrlVar);
BitmapVar.compress(Bitmap.CompressFormat.JPEG, 100, FylVar);
FylVar.close();
}
catch (Exception ErrVar) { ErrVar.printStackTrace(); }
}

Populate Android Gallery from image file paths?

I have some images that are saved to a directory on the Android device when the application starts--I would like to be able to display these images in a Gallery, but so far I haven't been able to do it.
I was following the sample Gallery code here, but it uses drawable resource IDs instead of file paths. I found this solution that is similar to what I'm looking for, except it uses ImageView instead of Gallery.
So the code using ImageView would look something like this:
File imgFile = new File(“/data/data/com.myproject.example/files/someImage.png”);
if(imgFile.exists()){
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
ImageView myImage = (ImageView) findViewById(R.id.imageviewTest);
myImage.setImageBitmap(myBitmap);
}
The above code works, but I'm not sure how to do it with a Gallery. I have been searching for answers and trying different things, but I'm v new to Android development and I feel like I'm in a bit over my head.
Any help is appreciated. Thank you in advance.
Basically I think you just need to put your two examples together.
Use the HelloGallery example as a start, however you want to change the code inside the getView() method of the ImageAdapter to call setImageBitmap() on the ImageView instead of setImageResource().
You will need an array/collection of file paths of images you want to load.
What you need to do is something like this:
public ImageAdapter(Context c, int itemId) {
context = c;
imgArr = GlobalStore.getItem(itemId).getPhotos();
TypedArray attr = context.obtainStyledAttributes(R.styleable.HelloGallery);
mGalleryItemBackground = attr.getResourceId(R.styleable.HelloGallery_android_galleryItemBackground, 0);
attr.recycle();
}
as you can see this is basically a copy from Gallery tutorial. In the constructor imgArr variable is loaded with an array of JPG file names. These were for example read from a database.
Then in the getView function you have something like this...
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(context);
String tmpStr = appContext.getFilesDir() + File.separator + "photos" + File.separator + imgArr.get(position);
Bitmap bitmap = BitmapFactory.decodeFile(tmpStr);
imageView.setImageBitmap(bitmap);
imageView.setLayoutParams(new Gallery.LayoutParams(350, 300));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setBackgroundResource(mGalleryItemBackground);
return imageView;
}
As you can see getFilesDir() gets your applications data location where it stores files, then let's imagine all photos are in "photos" directory, you build a path and attach a file name from the imgArr array. Since this is called for every photo you just use the passed position variable.
If you don't have an array of photos then maybe the way is to build it by reading the directory where you store photos, load all of the filenames in an array and then do this.
Then you do the rest on the gallery side as in the gallery tutorial.

Categories

Resources