1

The issue I face is that of a listactivity taking too long time to load.

I also know the reason behind this delay but unfortunately unable to fix this glitch.

Basically i have a listview which will display the list of kids which basically is a

person object displaying the following attributes (Name,Age,Sex).

Name : John Connor
Age  : 10 years, 2 months, 11days
Sex  : Male

In order to bind the kid details to a listview i use a binder class which derives from

BaseAdapter. Say KidDataBinder. Inside the getView method of the binder class I

perform the text binding to a TextView (basically this content is a part list_row_item.xml

layout)

The problem starts when i want to display the list of kids with their details including

their age (latest as per current date).

i.e. If i load the kids listactivity today, the entry shall read

Name : John Connor
Age  : 10 years, 2 months, 11days
Sex  : Male
---------------------------------
Name : Sandra Mueller
Age  : 11 years, 1 months, 2days
Sex  : Female
 .... so on 

If i read the same listactivity a day later, it should refresh the age as

Name : John Connor
Age  : 10 years, 2 months, 12days
Sex  : Male
---------------------------------
Name : Sandra Mueller
Age  : 11 years, 1 months, 3days
Sex  : Female
 .... so on 

NOTE: Note the change in the days in the Age

To achieve this, I have a utility method which basically gets the Date of Birth of the Kid

and calculates his latest age.

/* * Returns age in * years months and days format * */ private String calculateAge(String strdob) { int age; String difference; try{

    SimpleDateFormat custDateFormat = new SimpleDateFormat("MM/dd/yyyy");
    Date dob = custDateFormat.parse(strdob);
    Calendar today = Calendar.getInstance();
    Calendar cd = Calendar.getInstance();
    cd.setTime(dob);

    int dateParts[] = {Calendar.MONTH,Calendar.DAY_OF_MONTH,Calendar.YEAR};
    int diff[] = new int[3];
    for(int i = 2; i >= 0; i--)
    {
        while(!custDateFormat.format(cd.getTime()).split("/")[i].equals(custDateFormat.format(today.getTime()).split("/")[i]))
        {
            cd.add(dateParts[i],1);
            diff[i]++;
        }
    }

    difference = ""+(diff[2]+" yrs : "+diff[0])+" months : "+diff[1]+" days";

}
catch(ParseException pex){
    return "--";
}
catch(IllegalArgumentException iex){
    return "--";
}
return difference;

}

So this method helps me in fetching the latest age of the kid but the performance hit is

quite immense. Initially if the time taken to load the list of kids was 10ms. After

including the logic of calculating latest age, the delay is well almost 3500ms!!!

What's happening here is that each time the getView gets the current Kid object It has to access the date of birth(dob) field ---> call the calculateAge passing the dob ---> get the latest age --> finally set the textview item belonging to AGE

Is there a way to perform this calculation part inside the BaseAdapter class on a separate

thread or something so that this delay is minimized.

Thanks for your inputs/responses

VATSAG

this-Me
  • 2,139
  • 6
  • 43
  • 70
  • I think complexity to calculate age is too much, you need some other method(logic) to calculate age.Here its of n^2 it needs to be of n or nlogn. – keshav Dec 03 '13 at 09:34

3 Answers3

2

You need to check out on the logic for the date calculation. You can check this. It requires you to include some utility classes. Or you replace your calculation logic with the following code

GregorianCalendar d1 = new GregorianCalendar(1992, 8 - 1, 17);
GregorianCalendar d2 = new GregorianCalendar(2013, 6 - 1, 18);
d2.add(Calendar.YEAR, -d1.get(Calendar.YEAR));
d2.add(Calendar.MONTH, -d1.get(Calendar.MONTH));
d2.add(Calendar.DAY_OF_MONTH, -d1.get(Calendar.DAY_OF_MONTH) + 1);
int y = d2.get(Calendar.YEAR);
int m = d2.get(Calendar.MONTH);
int d = d2.get(Calendar.DAY_OF_MONTH) - 1;
Community
  • 1
  • 1
Himanshu Soni
  • 264
  • 8
  • 15
  • I dont think the method itself is taking that long to execute. Its the total time taken for executing this method over and over again for every item in the list which is causing the issue. – this-Me Dec 03 '13 at 10:06
  • Actually i tried implementing this logic and the delay has reduced a bit> :) Now the same operation takes around 1500ms. Definitely an improvement. I shall try to implement others suggestion and will accordingly mark as an answer – this-Me Dec 03 '13 at 10:31
1

You can also take logic of calculating age out of getview and calculate it before setting adapter so that each time when getView is called it wont take such a long time.

You can also write your adapter as follow. EDIT Adapter

public class MyAdapter extends Adapter{

ArrayList<Person> kids;
ArrayList<String> ages
public myAdapter(Context context,ArrayList<Person> kids,ArrayList<String> ages){
this.kids=kids;
this.ages=ages;
}

public View getView(......){
...

Person kid=kids.get(position);
String age=ages.get(position);


..
}
}

Calling it:

ArrayList<Person> kids=new ArrayList<Person>();
kids.add(..)
kids.add(..)
kids.add(..)

String[] ages=new String[kids.size()];
int i=0;
for(Person kid:kids){
   ages[i++]=calculateAge(kid.getDOB());
}

MyAdapter adapter=new MyAdapter(this,kids,ages);
vipul mittal
  • 17,343
  • 3
  • 41
  • 44
  • But the d.o.b content is known only inside the getview method for a particular item position. So based on the d.o.b content i have to calculate the age in detail. – this-Me Dec 03 '13 at 10:05
  • If you cannot edit your model class you can iterate person list and generate a separate list of age and pass that list to adapter as well. – vipul mittal Dec 03 '13 at 10:07
0

you can use for it lazyloading.you can calculate their age outside of getview and send to your adapter other object that be consist of name,year,month,day and sex.

zohreh
  • 1,055
  • 1
  • 9
  • 26