Hello all…
You may have seen many implementations of Lazy Loading ListView.
Today I will show you my method to create Lazy Loading ListViews.
I dont know whether it can be any more simple than this.
In this I am using AsyncTask to download each image.
So we will start.
Here we have 6 classes.
1. MainPage – This is our main activity that loads the ListView.
2. GetDataFromDB – This class get the image urls and it’s description as a string from the DB server and return that string.
Then we will split that string to seperate the urls and description and then set it to listview.
3. MyCustomArrayAdapter – Custom adapter for the ListView.
4. Model _ this class creates the object to be set for the ListView for each row.
5. PbAndImage – This class has an imageView and ProgressBar to send to the Asynctask.
6. DownloadImageTask – This class Asynchronously downloads the image.
At last the PHP Script which simple echoes the string containing the URLS and description of the image.
Here is the PHP Script.
getImageUrlsAndDescription.php
<?php // get these values from your DB. echo "http://coderzheaven.com/sample_folder/android_1.png,ANDROID0 ## http://coderzheaven.com/sample_folder/coderzheaven.png,ANDROID1 ## http://coderzheaven.com/sample_folder/coderzheaven.png,ANDROID2 ## http://coderzheaven.com/sample_folder/coderzheaven.png,ANDROID3 ## http://coderzheaven.com/sample_folder/android_1.png,ANDROID4 ## http://coderzheaven.com/sample_folder/coderzheaven.png,ANDROID5 ## http://coderzheaven.com/sample_folder/coderzheaven.png,ANDROID6 ## http://coderzheaven.com/sample_folder/android_1.png,ANDROID7 ## http://coderzheaven.com/sample_folder/coderzheaven.png,ANDROID8 ## http://coderzheaven.com/sample_folder/coderzheaven.png,ANDROID9"; ?>
So we will start.
MainPage.java
package com.coderzheaven.lazyloadinglistwithphpconnection; import java.util.ArrayList; import java.util.List; import android.app.ListActivity; import android.app.ProgressDialog; import android.os.Bundle; import android.widget.ArrayAdapter; public class MainPage extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R. layout. contacts_list); final List<Model> list = new ArrayList<Model>(); /** This block is for getting the image url to download from the server **/ final GetDataFromDB getvalues = new GetDataFromDB(); final ProgressDialog dialog = ProgressDialog.show(MainPage.this, "", "Gettting values from DB", true); new Thread (new Runnable() { public void run() { String response = getvalues.getImageURLAndDesciptionFromDB(); System.out.println("Response : " + response); dismissDialog(dialog); if (!response.equalsIgnoreCase("")) { if (!response.equalsIgnoreCase("error")) { dismissDialog(dialog); // Got the response, now split it to get the image Urls and description String all[] = response.split("##"); for(int k = 0; k < all.length; k++){ String urls_and_desc[] = all[k].split(","); // urls_and_desc[0] contains image url and [1] -> description. list.add(get(urls_and_desc[1],urls_and_desc[0])); } } } else { dismissDialog(dialog); } } }).start(); /*************************** GOT data from Server ********************************************/ ArrayAdapter<Model> adapter = new MyCustomArrayAdapter(this, list); setListAdapter(adapter); } public void dismissDialog(final ProgressDialog dialog){ runOnUiThread(new Runnable() { public void run() { dialog.dismiss(); } }); } private Model get(String s, String url) { return new Model(s, url); } }
GetDataFromDB.java
package com.coderzheaven.lazyloadinglistwithphpconnection; import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.BasicResponseHandler; import org.apache.http.impl.client.DefaultHttpClient; public class GetDataFromDB { public String getImageURLAndDesciptionFromDB() { try { HttpPost httppost; HttpClient httpclient; httpclient = new DefaultHttpClient(); httppost = new HttpPost( "http://10.0.2.2/test/getImageUrlsAndDescription.php"); // change this to your URL..... ResponseHandler<String> responseHandler = new BasicResponseHandler(); final String response = httpclient.execute(httppost, responseHandler); return response; } catch (Exception e) { System.out.println("ERROR : " + e.getMessage()); return "error"; } } }
Model.java
package com.coderzheaven.lazyloadinglistwithphpconnection; public class Model { private String name; private String url; public Model(String name, String url) { this.name = name; this.url = url; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getURL() { return url; } public void setURL(String url) { this.url = url; } }
MyCustomArrayAdapter.java
package com.coderzheaven.lazyloadinglistwithphpconnection; import java.util.List; import android.app.Activity; import android.graphics.Color; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; public class MyCustomArrayAdapter extends ArrayAdapter<Model> { private final Activity context; private final List<Model> list; public MyCustomArrayAdapter(Activity context, List<Model> list) { super(context, R.layout.list_layout, list); this.context = context; this.list = list; } static class ViewHolder { protected TextView text; protected ImageView image; protected ProgressBar pb; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = null; if (convertView == null) { LayoutInflater inflator = context.getLayoutInflater(); view = inflator.inflate(R.layout.list_layout, null); final ViewHolder viewHolder = new ViewHolder(); viewHolder.text = (TextView) view.findViewById(R.id.label); viewHolder.text.setTextColor(Color.BLACK); viewHolder.image = (ImageView) view.findViewById(R.id.image); viewHolder.image.setVisibility(View.GONE); viewHolder.pb = (ProgressBar) view.findViewById(R.id.progressBar1); view.setTag(viewHolder); } else { view = convertView; } ViewHolder holder = (ViewHolder) view.getTag(); holder.text.setText(list.get(position).getName()); holder.image.setTag(list.get(position).getURL()); holder.image.setId(position); PbAndImage pb_and_image = new PbAndImage(); pb_and_image.setImg(holder.image); pb_and_image.setPb(holder.pb); new DownloadImageTask().execute(pb_and_image); return view; } }
PbAndImage.java
package com.coderzheaven.lazyloadinglistwithphpconnection; import android.widget.ImageView; import android.widget.ProgressBar; public class PbAndImage { private ImageView img; private ProgressBar pb; public ImageView getImg() { return img; } public void setImg(ImageView img) { this.img = img; } public ProgressBar getPb() { return pb; } public void setPb(ProgressBar pb) { this.pb = pb; } }
DownloadImageTask.java
package com.coderzheaven.lazyloadinglistwithphpconnection; import java.io.InputStream; import java.net.URL; import com.coderzheaven.lazyloadinglistwithphpconnection.PbAndImage; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.os.AsyncTask; import android.view.View; import android.widget.ImageView; import android.widget.ProgressBar; public class DownloadImageTask extends AsyncTask<PbAndImage, Void, Bitmap> { ImageView imageView = null; ProgressBar pb = null; protected Bitmap doInBackground(PbAndImage... pb_and_images) { this.imageView = (ImageView)pb_and_images[0].getImg(); this.pb = (ProgressBar)pb_and_images[0].getPb(); return getBitmapDownloaded((String) imageView.getTag()); } protected void onPostExecute(Bitmap result) { System.out.println("Downloaded " + imageView.getId()); imageView.setVisibility(View.VISIBLE); pb.setVisibility(View.GONE); // hide the progressbar after downloading the image. imageView.setImageBitmap(result); //set the bitmap to the imageview. } /** This function downloads the image and returns the Bitmap **/ private Bitmap getBitmapDownloaded(String url) { System.out.println("String URL " + url); Bitmap bitmap = null; try { bitmap = BitmapFactory.decodeStream((InputStream) new URL(url) .getContent()); bitmap = getResizedBitmap(bitmap, 50, 50); return bitmap; } catch (Exception e) { e.printStackTrace(); } return bitmap; } /** decodes image and scales it to reduce memory consumption **/ public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) { int width = bm.getWidth(); int height = bm.getHeight(); float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; // CREATE A MATRIX FOR THE MANIPULATION Matrix matrix = new Matrix(); // RESIZE THE BIT MAP matrix.postScale(scaleWidth, scaleHeight); // RECREATE THE NEW BITMAP Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false); return resizedBitmap; } }
And the Most important thing – DONT FORGET TO ADD THE INTERNET PERMISSION ON YOUR MANIFEST FILE.
<uses-permission android:name="android.permission.INTERNET"/>
These are the layout files.
contacts_list.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:layout_margin="10dp" > <ListView android:id="@id/android:list" android:layout_width="fill_parent" android:layout_height="0dp" android:dividerHeight="1dp" android:cacheColorHint="#0000" android:clipToPadding="true" android:layout_margin="5dp" android:soundEffectsEnabled="true" android:scrollbars="none" android:layout_weight="1"> </ListView> </LinearLayout>
list_layout.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> <ProgressBar android:id="@+id/progressBar1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:id="@+id/image" android:contentDescription="@drawable/ic_launcher"> </ImageView> <TextView android:text="@+id/label" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/label" android:layout_marginLeft="15dp" android:layout_marginTop="5dp" android:textStyle="bold" android:textSize="20sp"> </TextView> </LinearLayout>
Please leave your comments on this post.
Awsome! 😉
Pingback: How to get table values from a MySQL database and show it in Android as Tables.?
Thank you so much. This will help me a lot.
Thanks for your clear explanation.
Is it possible, when a person clicks an item on the list, it displays a description of the item? please help…
Yes ofcourse write an onclickListener for the Listview and get the item description from the corresponding index in the array.
Hi, i cant find the way to make the items on the listview clickeables. The listview looks like it dont have a handle to work with. I am really confused. i see the id of the listview in the xml is android:list but is not define like a handler anywhere- list is the Listview?
I dont know where to call for the onclick listener if it must be on main or in the array class- My goal is to open diferents layouts on a item click from the listview.
If anybody can help me with the code i will preciate! thanks in advance!! Im New on Android sorry about my english im from Argentina
Hi, you could do this if want get text from textview when trigger click.
holder.text.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getContext(), holder.text.getText().toString(), Toast.LENGTH_LONG ).show();
}
});
Cheers
Nusagates
Please see my reply comment to Jonathan below.
How can i display url from database? can you give us the php code to set urls like you in the getImageUrlsAndDescription.php ???
in other word can we use the select url from image?
It’s in the php scrip, just write the code to bring them from the database.
I have in my database urls, who can i bring them to my application? i have more then 30 image,i can’t write every url in my php script. What i want a script php who brings me url from database then send them to myapplication. I am so sorry for my questions,i am new in android developement. Thanx a lot
can you give us the code to bring them?
Hey, thanks for the example. But I think you have severe bug in the implementation. As long as views being reused in lists implementations, your loaded image could be set for arbitrary image view in the list. For instance, if you display 10 list items at once, only 10 views will be created. That is ok and that is expected, but as soon as you start to scroll the list, new list items will be shown, but NO new views will be created. Existent ones, which were hidden from the screen, will be reused to show new rows. You should use model to store references to loaded images and show them as needed. In addition, you could use file cache.
Pingback: Which is the better way of loading bitmap for multiple screen size : Android Community - For Application Development
Hi
How do I replace listview gridview by using this code?
grateful
Simply replace ListView tag with Gridview and set number of columns.
Can you Send me this project source code.
Can it will work in ASP.net using MySql.
thanks for great post …
it was very useful for us developer android apps…..
Thanks
Hi guys.
Custom ListView just appears if i pull down the status bar.
Can anyone help me?
Thanks
What does that mean? explain please.
It would be very nice if you showed an example of working with a local sqlite.
Thanks in advance!
How to implement search filter on this json response .
What i mean I have a list of cities in listview which is populated from a json data and i want to search filter the same.
Can ya write an example on filtering such data?
Hi,
I get an error on this code line package sample;
Error: Syntax error on tokens, delete these tokens …. I Somebody know how to solve this problem?
Thanks!!!
Sorry I meant this code line: ” package sample;”
plize sample poroject for download
You’re the best!
private Model get(String s, String url) {
return new Model(s, url);
}
Its ok?????????? or must be …
private Model get(String name, String url) {
return new Model(name, url);
}
I debug it and it didnt shows me the description and the image, its look like it get stoped before set the data in the listview.
In the MODEL y have setName – setURL and andorid studio tell me they are dont beeing used.
The array recibe the data from db, that for sure. I can see it when i debug. It make the loop N times geting the php data, and apparetly the debug finish in the line code i write in the biginning.
Can anybody help me with this?
Sorry about my english! 🙁
solved, it refresh the data after press menu button, then the data appears. ;), now im checking to fix that.
The call:
new DownloadImageTask().execute(pb_and_image);
is happening in huge number of times(i.e. everytime getView is executed).
How to restrict that to be executed only for once per row in the listview?