Let's consider personality application where going to display actor's name, actor's description, actor's image etc.,
Let's take a json sample form this link..
https://dl.dropboxusercontent.com/s/jv2trufpmgr2gjz/actors.json?dl=0
Structure looks like this..
{
"actors": [
{
"name": "Brad Pitt",
"description": "William Bradley 'Brad' Pitt is an American actor and film producer. He has received a Golden Globe Award, a Screen Actors Guild Award, and three Academy Award nominations in acting categories",
"dob": "December 18, 1963",
"country": "United States",
"height": "1.80 m",
"spouse": "Jennifer Aniston",
"children": "Shiloh Nouvel Jolie-Pitt, Maddox Chivan Jolie-Pitt",
"image": "http://microblogging.wingnity.com/JSONParsingTutorial/brad.jpg"
},
{
"name": "Will Smith",
"description": "Willard Carroll 'Will' Smith, Jr. is an American actor, producer, and rapper. He has enjoyed success in television, film, and music.",
"dob": "September 25, 1968",
"country": "United States",
"height": "1.88 m",
"spouse": "Jada Pinkett Smith",
"children": "Jaden Smith, Willow Smith, Trey Smith",
"image": "http://microblogging.wingnity.com/JSONParsingTutorial/will.jpg"
}
]
}
Persons.java:
public class Persons {
private String name;
private String description;
private String dob;
private String country;
private String height;
private String spouse;
private String children;
private String image;
public Persons(){
}
public Persons(String name,String description,String dob,String country,String height,String spouse,String children, String image){
this.name=name;
this.description=description;
this.dob=dob;
this.country=country;
this.height=height;
this.spouse=spouse;
this.children=children;
this.spouse=spouse;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDob() {
return dob;
}
public void setDob(String dob) {
this.dob = dob;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
public String getSpouse() {
return spouse;
}
public void setSpouse(String spouse) {
this.spouse = spouse;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getChildren() {
return children;
}
public void setChildren(String children) {
this.children = children;
}
}
GridUI.java:
import java.io.IOException;
import java.util.ArrayList;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.personality.caches.ImageLoader;
import android.app.Activity;
import android.app.ProgressDialog;
import android.net.ParseException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.GridView;
import android.widget.Toast;
public class GridUI extends Activity {
ArrayList<Persons> personsList;
GridView gridView;
GridAdapter gridAdapter;
private static final String url="https://dl.dropboxusercontent.com/s/jv2trufpmgr2gjz/actors.json?dl=0";
private ImageLoader loader;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gridview);
personsList= new ArrayList<Persons>();
new JSONAsyncTask().execute(url);
gridView=(GridView)findViewById(R.id.gridview);
loader=new ImageLoader(GridUI.this);
gridAdapter = new GridAdapter(this, R.layout.gridview_row, personsList);
gridView.setAdapter(gridAdapter);
}
class JSONAsyncTask extends AsyncTask<String, Void, Boolean> {
ProgressDialog dialog;
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
dialog=new ProgressDialog(GridUI.this);
dialog.setMessage("Loading, please wait");
dialog.setTitle("Connecting server");
dialog.show();
dialog.setCancelable(false);
}
@Override
protected Boolean doInBackground(String... urls) {
try {
//------------------>>
HttpGet httppost = new HttpGet(urls[0]);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httppost);
// StatusLine stat = response.getStatusLine();
int status = response.getStatusLine().getStatusCode();
if(status==200){
HttpEntity entity = response.getEntity();
String data = EntityUtils.toString(entity);
JSONObject jsono=new JSONObject(data);
JSONArray jarray = jsono.getJSONArray("actors");
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i);
Persons actor = new Persons();
actor.setName(object.getString("name"));
actor.setDescription(object.getString("description"));
actor.setDob(object.getString("dob"));
actor.setCountry(object.getString("country"));
actor.setHeight(object.getString("height"));
actor.setSpouse(object.getString("spouse"));
actor.setChildren(object.getString("children"));
actor.setImage(object.getString("image"));
personsList.add(actor);
}
return true;
}
//------------------>>
} catch (ParseException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
@Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
dialog.cancel();
gridAdapter.notifyDataSetChanged();
if(result == false)
Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.splash, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
GridAdapter.java:
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import com.personality.caches.ImageLoader;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class GridAdapter extends BaseAdapter {
public ImageLoader loader;
private final ArrayList<Persons> itemLists;
public static final String NAME="name";
public static final String DOB="dob";
public static final String HEIGHT="height";
public static final String COUNTRY="country";
public static final String DESCRIPTION="description";
public static final String SPOUSE="spouse";
public static final String CHILDREN="children";
public static final String image="image";
LayoutInflater layoutInflater;
int Resource;
ViewHolder viewHolder;
Activity activity;
public GridAdapter(Activity a, int resource, ArrayList<Persons> itemList) {
layoutInflater = (LayoutInflater) a
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Resource = resource;
itemLists=itemList;
activity=a;
loader=new ImageLoader(a.getApplicationContext());
}
@Override
public int getCount() {
return itemLists.size();
}
@Override
public Object getItem(int position) {
return itemLists.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v= convertView;
try {
if(v==null){
viewHolder = new ViewHolder();
v = layoutInflater.inflate(Resource, null);
viewHolder.tvName=(TextView)v.findViewById(R.id.tvname);
viewHolder.imageview=(SquareImageView)v.findViewById(R.id.picture);
v.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) v.getTag();
}
final String actorImage=itemLists.get(position).getImage();
final String name=itemLists.get(position).getName();
final String dob=itemLists.get(position).getDob();
final String height=itemLists.get(position).getHeight();
final String country=itemLists.get(position).getCountry();
final String description=itemLists.get(position).getDescription();
final String spouse=itemLists.get(position).getSpouse();
final String children=itemLists.get(position).getChildren();
final String search = itemLists.get(position).getName().toString();
//
Ion.with(viewHolder.imageview).placeholder(R.drawable.ic_launcher).error(R.drawable.ic_launcher).load(actorImage);
viewHolder.tvName.setText(itemLists.get(position).getName());
loader.DisplayImage(actorImage,viewHolder.imageview);
itemLists.get(position).getImage();
viewHolder.imageview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if(search.contains("Brad Pitt")){
Toast.makeText(activity, "Bradss", Toast.LENGTH_SHORT)
.show();}
else{
}
// TODO Auto-generated method stub
Intent intent=new Intent(activity,DetailsActivity.class);
intent.putExtra(NAME, name);
intent.putExtra(DOB, dob);
intent.putExtra(HEIGHT, height);
intent.putExtra(COUNTRY, country);
intent.putExtra(DESCRIPTION, description);
intent.putExtra(SPOUSE, spouse);
intent.putExtra(CHILDREN, children);
intent.putExtra(image, actorImage);
activity.startActivity(intent);
}
});
// TODO Auto-generated method stub
}
catch (Exception ex) {
ex.printStackTrace();
}
return v;
}
static class ViewHolder {
public SquareImageView imageview;
public TextView tvName;
}
}
gridview.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:id="@+id/gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:verticalSpacing="0dp"
android:horizontalSpacing="0dp"
android:stretchMode="columnWidth"
android:numColumns="2" />
</FrameLayout>
gridviewrow.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.personality.SquareImageView
android:id="@+id/picture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
/>
<TextView
android:id="@+id/tvname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="15dp"
android:paddingBottom="15dp"
android:layout_gravity="bottom"
android:textColor="@android:color/white"
android:background="#55000000"
/>
</FrameLayout>
DetailsActivity.java:
package com.personality;
import com.personality.caches.ImageLoader;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;
public class DetailsActivity extends Activity {
ImageView imageView;
TextView name,dob,height,country,description,spouse,children;
private Bundle bundle;
public ImageLoader loader;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.details);
loader=new ImageLoader(DetailsActivity.this);
name=(TextView)findViewById(R.id.tvName);
dob=(TextView)findViewById(R.id.tvDateOfBirth);
height=(TextView)findViewById(R.id.tvHeight);
country=(TextView)findViewById(R.id.tvCountry);
description=(TextView)findViewById(R.id.tvDescriptionn);
spouse=(TextView)findViewById(R.id.tvSpouse);
children=(TextView)findViewById(R.id.tvChildren);
imageView=(ImageView)findViewById(R.id.ivImage);
bundle = this.getIntent().getExtras();
if(bundle != null && bundle.containsKey(GridAdapter.NAME) && bundle.containsKey(GridAdapter.CHILDREN) && bundle.containsKey(GridAdapter.COUNTRY) && bundle.containsKey(GridAdapter.DESCRIPTION) && bundle.containsKey(GridAdapter.DOB)&& bundle.containsKey(GridAdapter.HEIGHT) && bundle.containsKey(GridAdapter.image) && bundle.containsKey(GridAdapter.SPOUSE)){
String names=bundle.getString(GridAdapter.NAME);
String childrens=bundle.getString(GridAdapter.CHILDREN);
String dobs=bundle.getString(GridAdapter.DOB);
String heights=bundle.getString(GridAdapter.HEIGHT);
String countrys=bundle.getString(GridAdapter.COUNTRY);
String descriptions=bundle.getString(GridAdapter.DESCRIPTION);
String spouses=bundle.getString(GridAdapter.SPOUSE);
String images=bundle.getString(GridAdapter.image);
name.setText(names);
dob.setText(dobs);
children.setText(childrens);
height.setText(heights);
country.setText(countrys);
description.setText(descriptions);
spouse.setText(spouses);
loader.DisplayImage(images,imageView);
}
}
}
details.xml:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:id="@+id/LinearLayouts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:layout_width="300dp"
android:layout_height="300dp"
>
<ImageView
android:id="@+id/ivImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:layout_gravity="center"
android:src="@drawable/ic_launcher" />
</LinearLayout>
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Tom Cruise"
android:textColor="#166CED"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/tvDateOfBirth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#D64530"
android:text="Date of Birth: July 3, 1962" />
<TextView
android:id="@+id/tvHeight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Height: 1.80 m"
android:textColor="#D64530"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/tvCountry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#D64530"
android:text="United States" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/tvDescriptionn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#009A57"
android:text="Description" />
<TextView
android:id="@+id/tvSpouse"
android:layout_width="wrap_content" android:textColor="#166CED"
android:layout_height="wrap_content"
android:text="Spouse: Katie Holmes" />
<TextView
android:id="@+id/tvChildren"
android:layout_width="wrap_content" android:textColor="#166CED"
android:layout_height="wrap_content"
android:text="Children: Suri Cruise, Isabella Jane Cruise, Connor Cruise" />
</LinearLayout>
</ScrollView>
Add imageLoader.jar files.
FileCache.java:
import java.io.File;
import android.content.Context;
public class FileCache {
private File cacheDir;
public FileCache(Context context){
//Find the dir to save cached images
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"TTImages_cache");
else
cacheDir=context.getCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
}
public File getFile(String url){
//I identify images by hashcode. Not a perfect solution, good for the demo.
String filename=String.valueOf(url.hashCode());
//Another possible solution (thanks to grantland)
//String filename = URLEncoder.encode(url);
File f = new File(cacheDir, filename);
return f;
}
public void clear(){
File[] files=cacheDir.listFiles();
if(files==null)
return;
for(File f:files)
f.delete();
}
}
imageLoader.java:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.personality.R;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;
public class ImageLoader {
ImageLoader imageLoader;
MemoryCache memoryCache=new MemoryCache();
FileCache fileCache;
private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
ExecutorService executorService;
public ImageLoader(Context context){
fileCache=new FileCache(context);
executorService=Executors.newFixedThreadPool(5);
}
final int stub_id=R.drawable.ic_launcher;
public void DisplayImage(String url, ImageView imageView)
{
imageViews.put(imageView, url);
Bitmap bitmap=memoryCache.get(url);
if(bitmap!=null)
imageView.setImageBitmap(bitmap);
else
{
queuePhoto(url, imageView);
imageView.setImageResource(stub_id);
}
}
private void queuePhoto(String url, ImageView imageView)
{
PhotoToLoad p=new PhotoToLoad(url, imageView);
executorService.submit(new PhotosLoader(p));
}
private Bitmap getBitmap(String url)
{
File f=fileCache.getFile(url);
//from SD cache
Bitmap b = decodeFile(f);
if(b!=null)
return b;
//from web
try {
Bitmap bitmap=null;
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setInstanceFollowRedirects(true);
InputStream is=conn.getInputStream();
OutputStream os = new FileOutputStream(f);
Utils.CopyStream(is, os);
os.close();
bitmap = decodeFile(f);
return bitmap;
} catch (Throwable ex){
ex.printStackTrace();
if(ex instanceof OutOfMemoryError)
memoryCache.clear();
return null;
}
}
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=200;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
//Task for the queue
private class PhotoToLoad
{
public String url;
public ImageView imageView;
public PhotoToLoad(String u, ImageView i){
url=u;
imageView=i;
}
}
class PhotosLoader implements Runnable {
PhotoToLoad photoToLoad;
PhotosLoader(PhotoToLoad photoToLoad){
this.photoToLoad=photoToLoad;
}
@Override
public void run() {
if(imageViewReused(photoToLoad))
return;
Bitmap bmp=getBitmap(photoToLoad.url);
memoryCache.put(photoToLoad.url, bmp);
if(imageViewReused(photoToLoad))
return;
BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad);
Activity a=(Activity)photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}
boolean imageViewReused(PhotoToLoad photoToLoad){
String tag=imageViews.get(photoToLoad.imageView);
if(tag==null || !tag.equals(photoToLoad.url))
return true;
return false;
}
//Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable
{
Bitmap bitmap;
PhotoToLoad photoToLoad;
public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}
public void run()
{
if(imageViewReused(photoToLoad))
return;
if(bitmap!=null)
photoToLoad.imageView.setImageBitmap(bitmap);
else
photoToLoad.imageView.setImageResource(stub_id);
}
}
public void pause(){
imageLoader.pause();
}
public void resume(){
imageLoader.resume();
}
public void stop() {
imageLoader.stop();
}
}
MemoryCache.java:
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import android.graphics.Bitmap;
import android.util.Log;
public class MemoryCache {
private static final String TAG = "MemoryCache";
private Map<String, Bitmap> cache=Collections.synchronizedMap(
new LinkedHashMap<String, Bitmap>(10,1.5f,true));//Last argument true for LRU ordering
private long size=0;//current allocated size
private long limit=1000000;//max memory in bytes
public MemoryCache(){
//use 25% of available heap size
setLimit(Runtime.getRuntime().maxMemory()/4);
}
public void setLimit(long new_limit){
limit=new_limit;
Log.i(TAG, "MemoryCache will use up to "+limit/1024./1024.+"MB");
}
public Bitmap get(String id){
try{
if(!cache.containsKey(id))
return null;
//NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78
return cache.get(id);
}catch(NullPointerException ex){
ex.printStackTrace();
return null;
}
}
public void put(String id, Bitmap bitmap){
try{
if(cache.containsKey(id))
size-=getSizeInBytes(cache.get(id));
cache.put(id, bitmap);
size+=getSizeInBytes(bitmap);
checkSize();
}catch(Throwable th){
th.printStackTrace();
}
}
private void checkSize() {
Log.i(TAG, "cache size="+size+" length="+cache.size());
if(size>limit){
Iterator<Entry<String, Bitmap>> iter=cache.entrySet().iterator();//least recently accessed item will be the first one iterated
while(iter.hasNext()){
Entry<String, Bitmap> entry=iter.next();
size-=getSizeInBytes(entry.getValue());
iter.remove();
if(size<=limit)
break;
}
Log.i(TAG, "Clean cache. New size "+cache.size());
}
}
public void clear() {
try{
//NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78
cache.clear();
size=0;
}catch(NullPointerException ex){
ex.printStackTrace();
}
}
long getSizeInBytes(Bitmap bitmap) {
if(bitmap==null)
return 0;
return bitmap.getRowBytes() * bitmap.getHeight();
}
}
Utils.java:
import java.io.InputStream;
import java.io.OutputStream;
public class Utils {
public static void CopyStream(InputStream is, OutputStream os)
{
final int buffer_size=1024;
try
{
byte[] bytes=new byte[buffer_size];
for(;;)
{
int count=is.read(bytes, 0, buffer_size);
if(count==-1)
break;
os.write(bytes, 0, count);
}
}
catch(Exception ex){}
}
}