-1

I am loading the contact list from phone whenever click Tab. it works fine at first touch, but it leads memory problem from second time. How should I prevent this issue?

here is the code.

String sortOrder = ContactsContract.Contacts.DISPLAY_NAME
            + " COLLATE LOCALIZED ASC";
try {
        contactsCursor= getContentResolver()
        .query(uri, null, null, null,  sortOrder);

        //Log.i("The first one", "" + contactsCursor.getCount());
        if(contactsCursor.getCount()>0){
            if(contactsCursor.moveToFirst()){
                while (contactsCursor.moveToNext()) {

                    String hasPhoneNumber = contactsCursor.getString(contactsCursor
                            .getColumnIndexOrThrow(ContactsContract.Contacts.HAS_PHONE_NUMBER));
                    int contTypeInt=0;
                    String contactType="";
                    ArrayList<String> phoneNumberList= new ArrayList<String>();
                    if (Integer.parseInt(hasPhoneNumber) > 0) {

                        String id = contactsCursor.getString(contactsCursor
                                .getColumnIndexOrThrow(ContactsContract.Contacts._ID));

                        Cursor phones = getContentResolver().query(
                                ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,
                                ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + id, null, null);
                        String phoneNumber = null;
                        if(phones!=null && phones.getCount()>0){
                            while (phones.moveToNext()) {
                                int type= phones.getInt(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
                                if (type == Phone.TYPE_MOBILE){
                                    phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                                    phoneNumberList.add(phoneNumber);
                                }
                            }
                            contTypeInt++;
                            phones.close();
                            phones = null;
                        }
                    }

                    String id = contactsCursor.getString(contactsCursor
                            .getColumnIndexOrThrow(ContactsContract.Contacts._ID));
                    String name = contactsCursor.getString(contactsCursor
                            .getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
                    Cursor emails = getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,null,
                            ContactsContract.CommonDataKinds.Email.CONTACT_ID+ " = " + id, null, null);
                    ArrayList<String> emailAddressList= new ArrayList<String>();
                    if(emails!=null && emails.getCount()>0){
                        while (emails.moveToNext()) 
                           {
                               // This would allow you get several email addresses
                               String emailAddress = emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                               if(strEmails.equals("")){
                                   strEmails= emailAddress;
                               }else{
                                   strEmails= strEmails+","+emailAddress;
                               }
                               Log.v(name+"==>", emailAddress);
                               if ((!emailAddress.equalsIgnoreCase(""))&&(emailAddress.contains("@"))) 
                               {   
                                Log.d("email", emailAddress);
                                   emailAddressList.add(emailAddress);
                               }
                           }
                        emails.close();
                        emails = null;
                    }

                    if(emailAddressList.size()>0){
                        //primaryEmailList.add(emailAddressList.get(0));
                        contTypeInt++;
                    }
                    if(contTypeInt==0){
                        contactType="";
                    }else if(contTypeInt==2){
                        contactType= "both";
                    }else if(contTypeInt==1){
                        if(emailAddressList.size()>0){
                            contactType="email";
                        }else{
                            contactType="phone";
                        }
                    }
                    Log.d(name+" conatctType", contactType);
                    if(name==null){
                        name="";
                    }

                    String []tempArr= name.split(" ");
                    for(int i=0;i<tempArr.length;i++){
                        if(tempArr[i].length()>1){
                            tempArr[i]= tempArr[i].substring(0, 1).toUpperCase() + tempArr[i].substring(1);
                        }
                    }
                    String nameTmp="";
                    for(int i=0;i<tempArr.length;i++){
                        if(nameTmp.equals("")){
                            nameTmp= tempArr[i];
                        }else{
                            nameTmp= nameTmp+" "+tempArr[i];
                        }

                    }
                    Constants.contactsList.add(new ContactsData(id, nameTmp, contactType, phoneNumberList, emailAddressList));
                    phoneNumberList = null;
                    emailAddressList = null;
                    tempArr = null;
                }
            }
        }
        contactsCursor.close();
        contactsCursor = null;
        }
        catch (Exception e) {

        }

Is there anyone to help me? Thanks in advance

wjcoder
  • 29
  • 5
  • Is this code contained in a Fragment? – Don Sep 04 '13 at 16:33
  • nope. It's in activity – wjcoder Sep 04 '13 at 16:37
  • Okay. How are you implementing tabs and how many of them do you have? I normally use fragments to implement tabs (a fragment for each tab). Unless, by "Tab" do you mean you're clicking a button? – Don Sep 04 '13 at 16:49
  • I don't know why you're focusing on activity or fragment. – wjcoder Sep 04 '13 at 16:59
  • Problem is that the activity that loads contact list gets destroyed due to memory leak issue. I just want to know what causes memory issue and how to overcome it. – wjcoder Sep 04 '13 at 17:01
  • How do you know you have "memory issues"? What does that mean? – Simon Sep 04 '13 at 17:13
  • @wjcoder Because, memory leaks with tabs a lot of times are due to improperly managed Fragments. But, if you don't have fragments, you're probably not using a "Tab." It's probably a button. For anyone to help you fix this problem you're going to have provide more information. "It leads to memory problem second time," doesn't really tell us anything since memory problems can be caused by different things (e.g. an improperly managed bitmap). – Don Sep 04 '13 at 17:15
  • I used tabhost and each tab links to activity. – wjcoder Sep 04 '13 at 17:19
  • while loading the contact list second time, it shows GC_EXPLICIT and GC_EXTERNAL_ALLOC in LogCat. It isn't memory issue? – wjcoder Sep 04 '13 at 17:20
  • Okay. That's what I was trying to figure out. A tab host is backed by Fragments. That's why I was asking about Fragments. Hold on, I'll add an answer that should help you out. Can you please post the error that LogCat is giving you? – Don Sep 04 '13 at 17:21
  • GC_EXPLICIT freed 713K, 54% free 4099K/8903K, external 4957K/6190K, paused 37ms – wjcoder Sep 04 '13 at 17:30
  • GC_EXTERNAL_ALLOC freed 113K, 47% free 2940K/5447K, external 1873K/2108K, paused 21ms – wjcoder Sep 04 '13 at 17:30
  • @wjcoder I added an answer that should help you out. – Don Sep 04 '13 at 17:34

2 Answers2

1

You should be using a Content Provider, rather than a cursor. Content providers were designed specifically to avoid this kind of problem with cursors.

Here is an example.

Basically, you should be querying this data all at once. You are querying it a bit at a time. This can cause issues with SQLite and you should probably redesign your code.

Codeman
  • 12,157
  • 10
  • 53
  • 91
  • would you please write the code with Content Provider based on my code? – wjcoder Sep 05 '13 at 00:06
  • No, I won't. "give me the codez" comments aren't appreciated on SO. Not to mention, there are examples in the link I gave you! Don't be lazy, put some work in and try to figure it out. I spent 2 weeks figuring it out myself and learned a lot. – Codeman Sep 05 '13 at 20:55
0

Your error is probably coming from not checking to see if this Fragment that loads your contacts has already been created. To do this, you need to check to see if the Bundle that is passed to your onCreate() method in your Fragment is null. You should only load the contacts if the Fragment is being created for the first time. Example:

public void onCreate (Bundle savedInstanceState) {

    if(savedInstanceState == null) {
        // load the contacts
    }
}

Note that this is important to do in any Fragment since every time the layout changes from portrait to landscape or vice versa, the Fragment will be recreated.

Don
  • 506
  • 2
  • 8
  • 23
  • I didn't use Fragment, used TabActivity – wjcoder Sep 04 '13 at 17:40
  • Okay, well that's mostly likely your problem. The TabActivity class was deprecated in API 13. You should be using Fragments instead. – Don Sep 04 '13 at 17:43
  • I think you're in the wrong way. have you seen the GC_EXPLICIT and GC_EXTERNAL_ALLOC error I indicated? – wjcoder Sep 04 '13 at 17:45
  • @wjcoder No, I'm not. Yes. I saw both of those errors. You can't expect a class that was deprecated 6 APIs ago to perform well at all. The reason you're receiving those memory errors is probably because you're using the TabActivity class which was deprecated (which means it should no longer be used). Use Fragments and it should fix your problem. – Don Sep 04 '13 at 17:48
  • I need a solution suitable for current situation as it needs much work to change them as fragments – wjcoder Sep 04 '13 at 17:51
  • Converting it to Fragments would be time well spent. – Don Sep 04 '13 at 17:56