So I am trying to load about 25 images at once using the AsyncTask class.
In short I'm calling this inside the AsyncTask to download the image from the server:
Url = new URL(url);
HttpURLConnection urlConnection = (HttpURLConnection) Url.openConnection();
bitmap = BitmapFactory.decodeStream(urlConnection.getInputStream());
urlConnection.disconnect();
As you can see in this video, it results in poor performance. Presumably because it is loading the images one at a time as the AsyncTask queues each of them up, I think?
http://www.youtube.com/watch?v=7dqVqLn5Ibs
So the solution would be to load them all asynchronously, but I dont know how I would achieve this without needed a whole lot of new code?
You can do that easily using Universal image loader.
It loads each image in separate thread.It is very easy to use and takes care of most of the things like caching..etc.
Ex usage:
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(context));
imageLoader.displayImage(imageUrl, imageView);
Related
Help please solve my problem. I use the code for asynchronous image downloading from this site http://www.technotalkative.com/android-asynchronous-image-loading-in-listview/. With HTTP it works as it should, but if I change the piece when with
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setInstanceFollowRedirects(true);
InputStream is=conn.getInputStream();
On this one
Socket socket1 = new Socket();
socket1.connect(new InetSocketAddress(mSettings.getString(APP_PREFERENCES_IPSERVER, ""), 30100), 5000);
ObjectOutputStream outp1 = new ObjectOutputStream(socket1.getOutputStream());
ObjectInputStream inp1 = new ObjectInputStream(socket1.getInputStream());
outp1.writeObject("ASprUserEdir,-,fileget,-," + url);
outp1.flush();
String messageReceived = (String) inp1.readObject();
int file_size = Integer.valueOf(messageReceived.split(",-,")[1]);
InputStream is=socket1.getInputStream();
Then if the connection is slow, if you scroll the Sheet, the picture is not displayed in its place. How can this be fixed? Maybe need a different code for this.
Thank you!
When you try to download an image you need to consider few problem. Example caching, out of memory due to the image size and more and more.
The simlest way is using library such as Picasso or glide. They download the image asynchronous, caching the image, memory caching to prevent out of memory etc. It is easy to learn and use.
Use Library Picasso or Glide
and then used following code
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
Please go through the following link for more detail on Picasso
I've tried lots of different ways to download images and none of them actually worked, i have managed to get something working but its not perfect.
I made a new thread for downloading the bitmaps, im not storing them on the system storage or caching them in the memory for later use. If i keep opening this activity over and over, the ram usage for this app keeps getting higher and higher, and i do not want that at all!
URL url = new URL("http://10.0.0.21:80/1.png");
bitmapOne = BitmapFactory.decodeStream(url.openStream());
URL url2 = new URL("http://10.0.0.21:80/2.png");
bitmapTwo = BitmapFactory.decodeStream(url2.openStream());
runOnUiThread(new Runnable() {
#Override
public void run() {
image.setImageBitmap(bitmapOne);
image2.setImageBitmap(bitmapTwo);
}});
Thank you all for your answers! but...
I would only like to use pure java and no third party libraries for loading images, I was looking for a way to reduce memory usage and not so much of finding another way of downloading them. Im also not sure that having two urls and loading each stream looks very professional as the client could disconnect at any given moment (lets just pretend it does) and it does not load them both which are extremely required!
Use Picasso library, everything will be a breeze:
ImageView imageView = (ImageView) findViewById(R.id.imageView);
Picasso.with(this)
.load("http://SomeUrl/CodeFeature.jpg")
.into(imageView);
A good tutorial can be found here.
https://github.com/zetbaitsu/Compressor
Usage:
compressedImageBitmap = Compressor.getDefault(this).compressToBitmap(actualImageFile);
This library maybe helpful for you.
You can visit GitHub. search "Android", sort by: "Most Stars"
, lots of awesome library you will found.
Volley can be a good alternative too, with the ability of displaying animated gifs. This snippet illustrate the basic use, here with image cache, something that can make your app not to be memory and network too demanding:
ImageLoader.ImageCache imageCache = new BitmapLruCache();
ImageLoader imageLoader = new ImageLoader(Volley.newRequestQueue(getApplicationContext()), imageCache);
NetworkImageView myImage = (NetworkImageView) findViewById(R.id.myImageView);
myImage.setImageUrl(""+mSpeaker.getHeadshotUrl(), imageLoader);
loadBitmap("http://yourdomain.com/yourImage.jpg", myImage);
For this to work all you need is the Volley library and BitmapLruCache.java
So my app lists all the files and folders in a given Dropbox folder. They are listed in a custom ListView using an adapter.
Currently I use drawables for the image and folder icons. I loop through the Dropbox folder structure and add the needed drawable to a Bitmap array. This is done in an Async Task (doInBackground).
I then call the Adapter in the PostExecute like this :
adapter = new ImageAdapter(this, pix, paths);
lstView.setAdapter(adapter);
This then shows all the files and images (with default drawable icons) in the ListView.
The next step I want to do is start loading the thumbnails from dropbox.
So for every image in the List, I want to replace the drawable with a thumbnail retreived from dropbox.
Again this should be done in an Async task so the user can still scroll through the listview.
With dropbox, you can load thumbails like this:
if(fileInfo.thumbExists)
{
file = fileSystem.openThumbnail(fileInfo.path, ThumbSize.XS, ThumbFormat.PNG);
Bitmap image = BitmapFactory.decodeStream(file.getReadStream());
thumbs.add(image);
file.close();
}
In the code above, thumbs is a Bitmap Array.
I was planning on using Universal Image Loader or Picasso. But you cannot pass in a Bitmap Array into either of those. It has to be a URL or URI.
How can I achieve this? I'm guessing I need another async task, but I'm not sure how to update my adapter.
Considerations:
I don't want to wait until all thumbnails are downloaded before
starting to display them
Are there memory considerations if there are lots of thumbails?
Can you only display thumnails in the Visibile part of the
listview, and start loading more when they scroll?
Remember - I am using an array of Bitmaps, I don't have any URLS. Would I be best saving each Bitmap to the sd card and then using UIL or Picasso to load using the URI? But how would you know which images went to which position in the ListView?
SO the steps in my code would ideally be:
-Load the Listview with the files and folders with dummy images (already doing this!)
-Get the thumbnails from the decodeStream and load into the Bitmap Array
-Load the thumbnails into the correct position into the ListView
For each row of the list view, run a separate thread to download and show the thumbnail image.
I guess, you can avoid the use of a bitmap array and directly feed the downloaded image to the list view row.
I) Modify your getView() call back of the adapter like the one below:
ImageView thumbnail=Container.findViewById(R.id.thumbnail)
loadImageInBackground(thumbnail,URL).execute();
II) loadImageInBackground will be a class that implements AsyncTask
a) data members: ImageView thumbnail,String URL
b) Constructor: Initialize these data members with instances passed.
c) onPostExecute: Set a dummy image to the thumbnail here, that will appear until the required image is downloaded.You can even set an animating image here to give it a better feel.
d) doInBackground:
mUrl = new URL(strUrl);
HttpURLConnection conn = (HttpURLConnection) mUrl.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bmImg = BitmapFactory.decodeStream(is);
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
e) onPostExecute: associate the this.thumbnail to this.bmImg.
This way for each row of your list view an object of loadImageInBackground class will be initialized and will download the image from URL and set it to the image View container of the corresponding row.
The images will be displayed on the Thumbnail as soon as they are downloaded. There will be no Blocking, I mean, the user can interact with the app even when the images are being downloaded.
If you have implemented a lazy loading methodology, then this approach will not cause any outOfMemory exceptions in any case.And also, new images will only be downloaded when the user scrolls.
Point II.c provides for setting loading animation/image on the thumbnail until the actual image has been downloaded.
I am still a beginner in Android and java. I am trying to load an image from a server by using AsyncTask. The size of the image is around 50kb. Yet it takes several seconds to show up. The following code is used to download the image from the server.
public static Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
BufferedInputStream bis = new BufferedInputStream(input);
Bitmap myBitmap = BitmapFactory.decodeStream(bis);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
Can someone please tell me how to speed up this process. What are the factors this process depends on apart from the network speed?
Thank you in advance.
Firstly, I suggest you to search image size reduce algorithms. Then, you can choose some methologies to load picture. For example, in first step, you can load low sized images. After that , you can load normal size images in background and update each reduced sized images to normal sized images.
Here is a great resource on loading Bitmaps efficiently.
Android Developer site - Loading Large Bitmaps Efficiently
It also includes a code sample.
I am writing an app that is essentially a flipcard that shows word/hint on one side and picture on other side relevant to it.I am using viewflipper for the two views.Problem is that the picture loads from internet.App access the db,extracts url and then loads picture.That means the change in view takes as much time as it takes to download the picture.I want to flip card immediately and load picture so that user do not thinks that app is slow.Rather they should know that picture is being loaded,hence the delay.Pls suggest improvement in code.My code for loading picture in flipcard is:
public void setBMP(String s) //String passed is url extracted from column of db uing
{ //internal db
try{
//String url1 = "c.getString(3)";
String url1= s;
System.out.println(url1);
URL ulrn = new URL(url1);
HttpURLConnection con = (HttpURLConnection)ulrn.openConnection();
InputStream is = con.getInputStream();
Bitmap bmp = BitmapFactory.decodeStream(is);
if (null != bmp)
{
im.setImageBitmap(bmp);
}
else
System.out.println("The Bitmap is NULL");
}catch(Exception e){}
}
}
For changing view, i have set up actionListener.As soon as user touches screen card flips and image loads.
Also is it possible to preload the images in background while user is viewing some other card.Or is it possible to cache the cards viewed?
I would go the asnyctask route, because that way you can load/disable spinners (or wahtever loading animations) as well. Check out this answer for a really simple example. If you want to add spinners you need to start them in the onPreExecute() of the asnyctask (just add it to the example) and disable them in onPostExecute after you image is downloaded.
Using AsyncTask to load Images in ListView
it seems to me that creating a Runnable that gets the bmp and saves it to a hash map file and then, when it's needed if downloaded, it opens the file, and if not it downloads it from the web.
try looking at fedorvlasov's Lazy adapter for reference.
you can use his Image loader