So I'm making an app that displays captured images. I first save the snapped images in a static ArrayList of String (In the code below: methods.locationPath), and then converts these strings to bitmaps and save them in an ArrayList of Bitmap (In the code below: images).
for (String path : methods.locationPath) {
Bitmap bitmap = BitmapFactory.decodeFile(path);
images.add(bitmap);
}
gr = (GridView) findViewById(R.id.grid);
GridAdapter gridAdapter = new GridAdapter(this, values,images);
gr.setAdapter(gridAdapter);
this method, however, takes too long. Is there a way to make this loop faster with as small changes as possible?
Thanks
Instead of changing the image path into Bitmap object. You can directly pass the path of the Image and on Adapter class set the Image like
Picasso.with(mContext).load(new File(imageUrl)).resize(100,100).into(myViewHolder.imageView, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
}
});
Related
I am developing an Android app which should display a list of video thumbnails in RecyclerView. A new activity will then play the video for selected thumbnail.
How do I set com.vimeo.networking.model.Picture to Android ImageView?
My code:
mVimeoClient.fetchNetworkContent(VIDEO_URI, new ModelCallback<VideoList>(VideoList.class) {
#Override
public void success(VideoList videoList) {
ArrayList<Video> videoArrayList = videoList.data;
Video video = videoArrayList.get(0);
ArrayList<com.vimeo.networking.model.Picture> arrayListPics = video.pictures.sizes;
// imageView.setImageDrawable((Drawable) pictureAL.get(0));
imageView.setImageBitmap( (Bitmap) arrayListPics.get(0));
}
#Override
public void failure(VimeoError error) {
}
});
}
The setImageBitmap() And setImageDrawable() throws
java.lang.ClassCastException
The Picture object (the one returned from arrayListPics.get(0)) in the vimeo-networking library isn't a Bitmap and therefore can't be cast to one. The Picture object has a field on it called mLink which can be access via Picture#getLink(). This will return a URI string which you then can set on your ImageView.
The simplest code you could use to get this working is:
// The ImageView you want to put the thumbnail in
ImageView yourImageView = <insert your ImageView here>;
// The video whose thumbnail you want
Video yourVideo = <insert your Video here>;
// The collection of `Picture` objects associated with this video.
// Each `Picture` in this "collection" is a different size
PictureCollection yourVideosPictures = yourVideo.getPictures();
// Get the first thumbnail/picture from this collection (not recommended)
Picture videoThumbnailPicture = yourVideosPictures.getPictures().get(0);
// The URI to the image of the thumbnail
String videoThumbnailUri = videoThumbnailPicture.getLink();
// Convert the String URI to an actual URI object
final Uri uri = Uri.parse(videoThumbnailUri);
yourImageView.setImageURI(uri);
I say this is the simplest because there are more things you should do when setting an image uri. One thing is you should base the Picture your grab from yourVideosPictures based on the width of your ImageView so that you're not needlessly pulling down a larger image than you need.
You should also probably not just set the image URI directly onto yourImageView, but instead you should use some image caching library (or some caching implementation).
I'd suggest looking into Picasso, Glide, or Fresco. Or just google "Image caching on Android".
Here's a solution using Glide 4.x.
First of all, import the lib on your project:
implementation 'com.github.bumptech.glide:glide:4.6.1'
Since the Pictures class contains an Uri as the others stated, you can use Glide to download the image for you effortlessly as follows.
// Get your ImageView
ImageView iv = findViewById(R.id.your_image_view);
// Get your thumbnails
ArrayList<com.vimeo.networking.model.Picture> arrayListPics = video.pictures.sizes;
// Load them using Glide
Glide.with(this) // Assuming "this" is your Activity, but you can also use any context here
.load(arrayListPics.get(0).getLink())
.into(iv);
That way it won't matter where is the thumbnail located (Network, file, resources), Glide will load it for you.
You can also apply some transformations or use placeholders by using Glide's RequestOptions class. Read more on how to use it here.
Please user Picasso library to load image in Image-view.
In gradle
implementation 'com.squareup.picasso:picasso:2.71828'
in your adapter class
mVimeoClient.fetchNetworkContent(VIDEO_URI, new ModelCallback<VideoList>(VideoList.class) {
#Override
public void success(VideoList videoList) {
ArrayList<Video> videoArrayList = videoList.data;
Video video = videoArrayList.get(0);
ArrayList<Pictures> arrayListPics = video.pictures.sizes;
Picasso.get().load(arrayListPics.get(0).getpath).into(view);
}
#Override
public void failure(VimeoError error) {
}
});
}
if(!imglist.containsKey(temp.getString("event_image_thumb"))) {
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.loadImage(temp.getString("event_image_thumb"), new SimpleImageLoadingListener() {
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
imglist.put(imageUri, loadedImage);
messageHandler.sendEmptyMessage(0);
}
});
else
{
holder.thum1.setImageBitmap(null);
holder.thum2.setImageBitmap(null);
holder.thum1.setImageBitmap(imglist.get(temp.getString("event_image_thumb")));
holder.thum2.setImageBitmap(imglist.get(temp.getString("event_image_thumb")));
}
final int position = grid.getPositionForView((View)v.getParent());
Intent touch =new Intent(context,Touch.class);
touch.putExtra("data",getItem(position));
context.startActivity(touch);
}
};
The problem I am facing is The image is not passed into the activity class
I think object that you ar passing by following line has a bitmap
touch.putExtra("data",getItem(position));
passing a bitmap can harm the app. possibly it can be big and can have outofmemmory error
So if your object do have bitmap inside than i sugest dont do that
Solution is
1. cache your image in your internal or external storage
if you dont want any one to see this image than store it in internal with MODE_PRIVATE
2. send image uri in your extras only
3. access this uri from your second activity and get this image from that uri and show in second activity
I am using displayImage() method of UniversalImageLoader library in the adapter class, which sets images(from url) in the list items. i want if i reset adapter in my listview, images should not reload if the urls are same as previous urls.
There is two solution already posted in the issue section of Universal Image Loader.
Solution #1:
You can use custom displayer:
new FadeInBitmapDisplayer(300) {
#Override
public Bitmap display(Bitmap bitmap, ImageView imageView, LoadedFrom loadedFrom) {
if (loadedFrom != LoadedFrom.MEMORY_CACHE) {
return super.display(bitmap, imageView, loadedFrom);
} else {
imageView.setImageBitmap(bitmap);
return bitmap;
}
}
}
Solution #2:
BitmapDisplayer displayer = new FadeInBitmapDisplayer(500) {
#Override
public Bitmap display(Bitmap bitmap, ImageView imageView,
LoadedFrom loadedFrom) {
if (loadedFrom != LoadedFrom.MEMORY_CACHE) {
return super.display(bitmap, imageView, loadedFrom);
} else {
imageView.setImageBitmap(bitmap);
return bitmap;
}
}
};
DisplayImageOptions options = new DisplayImageOptions.Builder()
.cacheInMemory(true).resetViewBeforeLoading(true)
.showImageForEmptyUri(R.drawable.thumbnail_no_image)
.showImageOnFail(R.drawable.thumbnail_no_image)
.displayer(displayer).build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
context).defaultDisplayImageOptions(options)
.memoryCacheSize(2 * 1024 * 1024).build();
sLoader.init(config);
I faced the same problema and went with a solution as follows
Inside the getview method after declaring your imageview try the following line as first line
myImageView.setImageResource(R.drawable.adefaultimage);
this will first show a defaultimage in the imagview and will avoid duplication of images till imageloader loads the real one
To achieve this :
Use android Lru cache in your list adapter. First time its looking very complex but its have more benifits.
Using Lru cache your image store in cache and when it will display then check from cache if it will exist then it will not down load and it will use from stored cache memory. You can also give cache memory size for your application and clear it.
Below have some links:
Tutorials:
http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
http://developer.android.com/reference/android/util/LruCache.html
Example :
http://android-er.blogspot.in/2012/07/caching-bitmaps-with-lrucache.html
http://android-er.blogspot.in/2012/07/apply-lrucache-on-gridview.html
I tried above solutions but not find usefull, Finally i solved my problem by saving images from url to device(as bitmap) then get in list view from there.
I generate a ImageView in my AndroidLauncher and need to use it in one of my screen classes, so I created an interface. How can I pass that image and use it in my screen class? Do I need to make it into a Bitmap first?
What I got right now is:
Uri selectedImage = data.getData();
selectedImagePath = getPath(selectedImage);
imageView.setImageURI(selectedImage);
and my interface:
public interface purchInterface{
public void getSelectedImage();
}
and in AndroidLauncher:
#Override
public void getSelectedImage() {
imageView.getDrawable();
}
Im in deep water here. Note that I need to be able to draw this Image in my screen class.
You need to return the image encoded in some format from getSelectedImage method. Otherwise your implementation is retrieving the drawable and dropping it immediately.
You should refer to Converting Android Bitmap to LibGdx's Texture
So your interface could be
public interface purchInterface {
public byte[] getSelectedImage();
}
And implementation could be
#Override
public byte[] getSelectedImage() {
// Convert image into bitmap, encode in a byte array.
}
You can call the interface's method and decode the byte array using method described in above question.
Hope this helps.
Good luck.
Use singleton class and store image in it using setter() and later u can use getter ().
Or you convert the image to string using base64 encoding and save it shared preferences or file or database or external storage or pass as intent data to next activity and then decode it to bitmap
this is very big trouble for me, I have been working for hours on this, and no clue !
I having a problem with Asynchronous image loading in ListView.
I'm using Parse.com as my application's Backend, i'm retrieving Messages and their images from the Parse.com class.
Everything is working fine, when I scroll Up/Down, or Load the list view again, the Pictures Mixed, and all pictures Reload in another order, and after few seconds they will ordered as I want, but this is a big issue for me.
I think this is happening because I'm using class like this to Upload images
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap>
Anyway my adapter class is the following :
public class adapterview extends ArrayAdapter<Message> {
Bitmap image;
public adapterview(Context context, ArrayList<Message> Messages) {
super(context, 0, Messages);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
final Message m = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.custom2, parent, false);
}
TextView message = (TextView) convertView.findViewById(R.id.message);
TextView date = (TextView) convertView.findViewById(R.id.date);
TextView user = (TextView) convertView.findViewById(R.id.user);
message.setText(m.getMessage());
user.setText(m.getUser());
new DownloadImageTask((ImageView) convertView.findViewById(R.id.imageView1))
.execute(m.getImage());
return convertView;
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
and this is my message class :
public class Message {
String message;
String user;
String phone;
String image;
String date;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
and this how i'm adding items to my list :
contacts c = new contacts();
c.setName(object.get("name").toString());
c.setNumero(object.get("phone").toString());
ParseFile image = (ParseFile)object.get("Profil");
c.setProfil(image.getUrl());
messagelist.addcontact(c);
and this is the code how i'm filling the list view from the MainActivity :
adapterview adapter = new adapterview(MainActivity.this, (ArrayList<Message>) messagelist);
list.setAdapter(adapter);
Here is two screenshots when I scroll Down and then Up so the picture of the first listItem changes !! for no reason and then get back to the normal picture after some seconds.
If you can suggest a new way on how I can upload the images from URL to ImageView, that would be great.
What you are observing is i think due to the viewholder pattern of the listview.You are trying to download and set image to the images via aysnctask in getview() but when you scrollup or down the view get recycled and when you again go to that position your getview called for that position so the asynctask is again executed and it download the set the image in imageview again therefore you see the delay,i would suggest you to use PICASSO libraray from square it is quite efficient for image downloads and caches your images also here is the link http://square.github.io/picasso/ or use Glide which is now officially recommended by Google,here is the github link Glide
last time I also used manual downloading avatars of contacts, but it's bad.
Your problem I think:
Download avatar, then set to ImageView
But, you are using ViewHolder pattern, so new downloaded avatar will set to many imageview > wrong avatar for specified contact (This only run well when all avatars are downloaded)
First, check Universal Image Loader library, set avatar URL to the view and it will automatically download, cache your avatars into memory.
Then post here if you still get wrong avatar problem.
the Pictures Mixed, and all pictures Reload in another order, and
after few seconds they will ordered as I want
This weird behavior happening due to AsyncTask in getView method without View Holder Pattern.
To avoid rendering already rendered thumbnail images again and load new images from network in listview on scroll use View Holder pattern.
See following useful tutorial for creating ListView with good scroll and loading performace using View Holder:
Performance Tips for Android’s ListView
That happens because ListView recycle the views when you scroll, and then when you call your async task for downloading of the pictures and scroll, the download finish but the reference points to a recycled view and one or more async task pointing to the same view. One way you could avoid this its tagging you view when a download start, and when the download end, before you draw the image check if its the actual reference the correct and then draw the image.
You could tag the view with the URL of the image because its a unique value.
In the preExecute of the download you must tag the ImageView with the URL(String).
imageView.setTag(url);
And when the task finish and before draw the image, recover the tag and check it.
String tag = (String)imageView.getTag();
if(tag != null && tag.equals(url)){
//Draw the image
} else {
//Draw the placeholder or clean the ImageView
}
And you can upgrade the performance of you ListView using the ViewHolder pattern, and why you download the image manually when Parse can perform it by their API, for the Parse way and using a Cache policy, when you download a image automatically cached the bitmap, and when you ask again for the download just retrieved the cached result.
Cheers!
I solved by using Recycle view's onBindViewHolder
#Override
public void onBindViewHolder(final MyViewHolder viewHolder, int i) {
CartsViewModel currentData = data.get(i);
ParseFile image = currentData.getParseImage();
if(image!=null){
Log.d(TAG,"image not null. Downloading....");
image.getDataInBackground(new GetDataCallback() {
#Override
public void done(byte[] bytes, ParseException e) {
if(e==null){
Log.d(TAG,"donload finished");
Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
viewHolder.cartImage.setImageBitmap(bmp);
}else{
viewHolder.cartImage.setImageBitmap(null);
}
}else{
viewHolder.cartImage.setImageBitmap(null);
}
});
}
viewHolder.cartName.setText(currentData.getCartName());
viewHolder.cartAddress.setText(currentData.getCartAddress());
viewHolder.rating.setText(currentData.getRating());
viewHolder.reviewCount.setText(currentData.getReviewCount());
}
works like charm with the parse method.
What is the listview cell layout xml file?
I think the Android can't determine the cell size of listview. This causes some issues.
If you want to use async loading images, one way to escape the issue is to fix the image size. For example
<ImageView
android:id="#+id/row_icon1"
android:layout_width="60dip"
android:layout_height="60dip"
android:layout_gravity="center_vertical"
/>