Massive refactoring of ContactList.
authorDa Risk <darisk972@gmail.com>
Thu, 27 May 2010 01:41:27 +0200
changeset 757 1a5cb28a1c4d
parent 756 c86eb188de1c
child 758 565942fdf426
Massive refactoring of ContactList. Filtering is now done before the displaying.
src/com/beem/project/beem/ui/ContactList.java
--- a/src/com/beem/project/beem/ui/ContactList.java	Thu May 27 01:37:12 2010 +0200
+++ b/src/com/beem/project/beem/ui/ContactList.java	Thu May 27 01:41:27 2010 +0200
@@ -43,11 +43,15 @@
 package com.beem.project.beem.ui;
 
 import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.Iterator;
 
 import org.jivesoftware.smack.util.StringUtils;
 
@@ -58,6 +62,7 @@
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.SharedPreferences;
+import android.content.Context;
 import android.graphics.drawable.LevelListDrawable;
 import android.os.Bundle;
 import android.os.Handler;
@@ -99,7 +104,6 @@
  */
 public class ContactList extends Activity {
 
-    // private static final String TAG = "CONTACTLIST_ACT";
     private static final Intent SERVICE_INTENT = new Intent();
     static {
 	SERVICE_INTENT.setComponent(new ComponentName("com.beem.project.beem", "com.beem.project.beem.BeemService"));
@@ -109,9 +113,9 @@
     private static final String SETTINGS_HIDDEN_CONTACT = "settings_key_hidden_contact";
     private static final String TAG = "ContactList";
     private final BeemContactList mAdapterContactList = new BeemContactList();
-    private final BeemBanner mAdapterBanner = new BeemBanner();
     private final List<String> mListGroup = new ArrayList<String>();
     private final Map<String, List<Contact>> mContactOnGroup = new HashMap<String, List<Contact>>();
+    private final BeemContactListOnClick mOnContactClick = new BeemContactListOnClick();
     private final Handler mHandler = new Handler();
     private final ServiceConnection mServConn = new BeemServiceConnection();
     private final BeemBroadcastReceiver mReceiver = new BeemBroadcastReceiver();
@@ -120,11 +124,12 @@
     private final BeemRosterListener mBeemRosterListener = new BeemRosterListener();
     private List<Contact> mListContact;
     private IRoster mRoster;
-    private String mCurGroup;
     private Contact mContact;
     private IXmppFacade mXmppFacade;
     private SharedPreferences mSettings;
     private LayoutInflater mInflater;
+    private BeemBanner mAdapterBanner;
+    private boolean mBinded;
 
     /**
      * Constructor.
@@ -164,9 +169,6 @@
 	}
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
 	super.onCreateContextMenu(menu, v, menuInfo);
@@ -182,9 +184,6 @@
 	menu.setHeaderTitle(mContact.getJID());
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public boolean onContextItemSelected(MenuItem item) {
 	Intent in;
@@ -250,10 +249,6 @@
 	return super.onContextItemSelected(item);
     }
 
-    /*
-     * (non-Javadoc)
-     * @see android.app.Activity#onActivityResult(int, int, android.content.Intent)
-     */
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 	super.onActivityResult(requestCode, resultCode, data);
@@ -266,9 +261,6 @@
 	}
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     protected void onCreate(Bundle saveBundle) {
 	super.onCreate(saveBundle);
@@ -278,23 +270,19 @@
 	this.registerReceiver(mReceiver, new IntentFilter(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED));
 
 	mInflater = getLayoutInflater();
+	mAdapterBanner = new BeemBanner(mInflater, mListGroup);
+	mListContact = new ArrayList<Contact>();
+	ListView listView = (ListView) findViewById(R.id.contactlist);
+	listView.setOnItemClickListener(mOnContactClick);
+	registerForContextMenu(listView);
+	listView.setAdapter(mAdapterContactList);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     protected void onResume() {
 	super.onResume();
-	if (mXmppFacade == null)
-	    bindService(SERVICE_INTENT, mServConn, BIND_AUTO_CREATE);
-	else {
-	    if (!mSettings.getBoolean("settings_key_hide_groups", false))
-		buildBanner();
-	    else
-		hideGroups();
-	    buildContactList();
-	}
+	if (!mBinded)
+	    mBinded = bindService(SERVICE_INTENT, mServConn, BIND_AUTO_CREATE);
     }
 
     /**
@@ -312,13 +300,10 @@
 	    Log.d("ContactList", "Remote exception", e);
 	}
 	unbindService(mServConn);
+	mBinded = false;
 	mXmppFacade = null;
     }
 
-    /*
-     * (non-Javadoc)
-     * @see android.app.Activity#onDestroy()
-     */
     @Override
     protected void onDestroy() {
 	super.onDestroy();
@@ -327,38 +312,15 @@
     }
 
     /**
-     * Comparator Contact by Name.
-     */
-    @SuppressWarnings("unused")
-    private class ComparatorContactListByName<T> implements Comparator<T> {
-	/**
-	 * Constructor.
-	 */
-	public ComparatorContactListByName() {
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public int compare(T c1, T c2) {
-	    return ((Contact) c1).getName().compareToIgnoreCase(((Contact) c2).getName());
-	}
-    }
-
-    /**
      * Comparator Contact by status and name.
      */
-    private class ComparatorContactListByStatusAndName<T> implements Comparator<T> {
+    private static class ComparatorContactListByStatusAndName<T> implements Comparator<T> {
 	/**
 	 * Constructor.
 	 */
 	public ComparatorContactListByStatusAndName() {
 	}
 
-	/**
-	 * {@inheritDoc}
-	 */
 	@Override
 	public int compare(T c1, T c2) {
 	    if (((Contact) c1).getStatus() < ((Contact) c2).getStatus()) {
@@ -373,30 +335,25 @@
     /**
      * Contact List construction.
      */
-    private void buildContactList() {
-	if (mCurGroup != null) {
-	    mListContact = mContactOnGroup.get(mCurGroup);
-	}
+    private void buildContactList(String group) {
+	mListContact = mContactOnGroup.get(group);
+	Log.d(TAG, "buildContactList for group " + group);
 	sortBeemContactList();
-	ListView listView = (ListView) findViewById(R.id.contactlist);
-	listView.setOnItemClickListener(new BeemContactListOnClick());
-	registerForContextMenu(listView);
-	listView.setAdapter(mAdapterContactList);
     }
 
     /**
-     * buildBanner.
+     * showGroups.
      */
-    private void buildBanner() {
+    private void showGroups() {
 
 	ViewStub stub = (ViewStub) findViewById(R.id.contactlist_stub);
-	if (stub != null)
-	    stub.inflate();
-	else
+	if (stub != null) {
+	    View v = stub.inflate();
+	    Gallery g = (Gallery) v.findViewById(R.id.contactlist_banner);
+	    g.setOnItemClickListener(new OnItemClickGroupName());
+	    g.setAdapter(mAdapterBanner);
+	} else
 	    ((LinearLayout) findViewById(R.id.contactlist_groupstub)).setVisibility(View.VISIBLE);
-	Gallery g = (Gallery) findViewById(R.id.contactlist_banner);
-	g.setOnItemClickListener(new OnItemClickGroupName());
-	g.setAdapter(mAdapterBanner);
     }
 
     /**
@@ -434,8 +391,8 @@
 
 	@Override
 	public void onItemClick(AdapterView<?> arg0, View v, int i, long l) {
-	    mCurGroup = mListGroup.get(i);
-	    buildContactList();
+	    String group = mListGroup.get(i);
+	    buildContactList(group);
 	}
     }
 
@@ -443,7 +400,9 @@
      * Sort the contact list.
      */
     private void sortBeemContactList() {
+	Log.d(TAG, "Sort ");
 	Collections.sort(mListContact, mComparator);
+	mAdapterContactList.notifyDataSetChanged();
     }
 
     /**
@@ -483,21 +442,20 @@
 	 */
 	@Override
 	public void onEntriesAdded(List<String> addresses) throws RemoteException {
+	    boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
 	    for (String newName : addresses) {
 		Contact c = mRoster.getContact(newName);
-		mContactOnGroup.get(getString(R.string.contact_list_all_contact)).add(c);
-		if (c.getGroups().size() == 0)
-		    mContactOnGroup.get(getString(R.string.contact_list_no_group)).add(c);
-		else {
+		if (!hideDisconnected || Status.statusOnline(c.getStatus())) {
+		    mContactOnGroup.get(getString(R.string.contact_list_all_contact)).add(c);
+		    if (c.getGroups().size() == 0)
+			mContactOnGroup.get(getString(R.string.contact_list_no_group)).add(c);
 		    for (String group : c.getGroups()) {
 			if (!mListGroup.contains(group)) {
 			    mListGroup.add(mListGroup.size() - 1, group);
-			    List<Contact> tmplist = new ArrayList<Contact>();
+			    List<Contact> tmplist = new LinkedList<Contact>();
 			    mContactOnGroup.put(group, tmplist);
 			}
 			mContactOnGroup.get(group).add(c);
-			if (group.equals(mCurGroup) && !mListContact.contains(c))
-			    mListContact.add(c);
 		    }
 		}
 	    }
@@ -509,20 +467,13 @@
 	 */
 	@Override
 	public void onEntriesDeleted(List<String> addresses) throws RemoteException {
+	    Log.d(TAG, "onEntries deleted " + addresses);
 	    for (String cToDelete : addresses) {
-		for (Contact c : mListContact) {
-		    if (c.getJID().equals(cToDelete)) {
-			for (String group : mListGroup) {
-			    mContactOnGroup.get(group).remove(c);
-			    if (mContactOnGroup.get(group).size() == 0) {
-				//mContactOnGroup.remove(group);
-				//mListGroup.remove(group);
-			    }
-			}
-			mListContact.remove(c);
-			break;
-		    }
+		Contact contact = mRoster.getContact(cToDelete);
+		for (List<Contact> contactByGroups : mContactOnGroup.values()) {
+		    contactByGroups.remove(contact);
 		}
+		cleanBannerGroup();
 	    }
 	    mListContact = mContactOnGroup.get(getString(R.string.contact_list_all_contact));
 	    mHandler.post(new RunnableChange());
@@ -533,42 +484,67 @@
 	 */
 	@Override
 	public void onEntriesUpdated(List<String> addresses) throws RemoteException {
+	    boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
 	    for (String adr : addresses) {
 		Contact c = mRoster.getContact(adr);
-		if (c.getGroups() != null) {
-		    if (mContactOnGroup.get(getString(R.string.contact_list_no_group)).contains(c)) {
-			mContactOnGroup.get(getString(R.string.contact_list_no_group)).remove(c);
+		List<String> groups = c.getGroups();
+		for (Map.Entry<String, List<Contact>> entry : mContactOnGroup.entrySet()) {
+		    List<Contact> contactByGroups = entry.getValue();
+		    contactByGroups.remove(c);
+		}
+		if (!hideDisconnected || Status.statusOnline(c.getStatus())) {
+		    mContactOnGroup.get(getString(R.string.contact_list_all_contact)).add(c);
+		    if (c.getGroups().size() == 0)
+			mContactOnGroup.get(getString(R.string.contact_list_no_group)).add(c);
+		    for (String group : c.getGroups()) {
+			if (!mListGroup.contains(group)) {
+			    mListGroup.add(mListGroup.size() - 1, group);
+			    List<Contact> tmplist = new LinkedList<Contact>();
+			    mContactOnGroup.put(group, tmplist);
+			}
+			mContactOnGroup.get(group).add(c);
 		    }
 		}
 	    }
+	    cleanBannerGroup();
 	    mHandler.post(new RunnableChange());
 	}
 
-	/**
-	 * {@inheritDoc}
-	 */
 	@Override
 	public void onPresenceChanged(PresenceAdapter presence) throws RemoteException {
 	    String from = presence.getFrom();
-	    boolean resfound = false;
-	    int foundIdx = 0;
-	    boolean found = false;
+	    boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
 	    Contact contact = mRoster.getContact(StringUtils.parseBareAddress(from));
-	    for (int i = 0; i < mListContact.size(); i++) {
-		Contact curContact = mListContact.get(i);
-		if (curContact.getJID().equals(contact.getJID())) {
-		    found = true;
-		    foundIdx = i;
-		    break;
+	    for (Map.Entry<String, List<Contact>> entry : mContactOnGroup.entrySet()) {
+		List<Contact> contactByGroups = entry.getValue();
+		if (contactByGroups.contains(contact)) {
+		    contactByGroups.remove(contact);
+		    if (!hideDisconnected || Status.statusOnline(contact.getStatus())) {
+			contactByGroups.add(contact);
+		    }
+		} else {
+		    if (Status.statusOnline(contact.getStatus())) {
+			List<String> groups = contact.getGroups();
+			if (groups.contains(entry.getKey())) {
+			    contactByGroups.add(contact);
+			}
+		    }
 		}
 	    }
-	    if (found){
-		mListContact.set(foundIdx, contact);
-	    } else {
-		mListContact.add(contact);
-	    }
+	    Log.d(TAG, "presence");
 	    mHandler.post(new RunnableChange());
 	}
+
+	private void cleanBannerGroup() {
+	    for (Iterator<String> it = mListGroup.iterator(); it.hasNext(); ){
+		String group = it.next();
+		if (mContactOnGroup.get(group).size() == 0) {
+		    mContactOnGroup.remove(group);
+		    it.remove();
+		}
+	    }
+	}
+
     }
 
     /**
@@ -587,16 +563,7 @@
 	 */
 	@Override
 	public int getCount() {
-	    if (mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false)) {
-		int res = 0;
-		for (Contact c : mListContact) {
-		    if (Status.statusOnline(c.getStatus()))
-			res++;
-		}
-		return res;
-	    } else {
-		return mListContact.size();
-	    }
+	    return mListContact.size();
 	}
 
 	/**
@@ -604,20 +571,7 @@
 	 */
 	@Override
 	public Object getItem(int position) {
-	    Contact c = null;
-	    if (mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false)) {
-		int res = 0;
-		for (Contact cur : mListContact) {
-		    if (res == position && Status.statusOnline(cur.getStatus())) {
-			c = cur;
-			break;
-		    }
-		    if (Status.statusOnline(cur.getStatus()))
-			res++;
-		}
-	    } else
-		c = mListContact.get(position);
-	    return c;
+	    return mListContact.get(position);
 	}
 
 	/**
@@ -637,19 +591,7 @@
 	    if (convertView == null) {
 		v = mInflater.inflate(R.layout.contactlistcontact, null);
 	    }
-	    Contact c = null;
-	    if (mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false)) {
-		int res = 0;
-		for (Contact cur : mListContact) {
-		    if (res == position && Status.statusOnline(cur.getStatus())) {
-			c = cur;
-			break;
-		    }
-		    if (Status.statusOnline(cur.getStatus()))
-			res++;
-		}
-	    } else
-		c = mListContact.get(position);
+	    Contact c = mListContact.get(position);
 	    if (mRoster != null) {
 		try {
 		    c = mRoster.getContact(c.getJID());
@@ -657,11 +599,7 @@
 		    e.printStackTrace();
 		}
 	    }
-	    if (mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false) && !Status.statusOnline(c.getStatus())) {
-		v.setVisibility(View.GONE);
-	    } else {
-		bindView(v, c);
-	    }
+	    bindView(v, c);
 	    return v;
 	}
 
@@ -687,57 +625,45 @@
     /**
      * Adapter banner list.
      */
-    private class BeemBanner extends BaseAdapter {
+    private static class BeemBanner extends BaseAdapter {
+	private List<String> mGroups;
+	private LayoutInflater mInflater;
+
 	/**
 	 * Constructor.
 	 */
-	public BeemBanner() {
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public int getCount() {
-	    return mListGroup.size();
+	public BeemBanner(LayoutInflater inflater, List<String> groups) {
+	    mGroups = groups;
+	    mInflater = inflater;
 	}
 
-	/**
-	 * {@inheritDoc}
-	 */
+	@Override
+	public int getCount() {
+	    return mGroups.size();
+	}
+
 	@Override
 	public Object getItem(int position) {
-	    return mListGroup.get(position);
+	    return mGroups.get(position);
 	}
 
-	/**
-	 * {@inheritDoc}
-	 */
 	@Override
 	public long getItemId(int position) {
 	    return position;
 	}
 
-	/**
-	 * {@inheritDoc}
-	 */
 	@Override
 	public View getView(int position, View convertView, ViewGroup parent) {
 	    View v = convertView;
 	    if (convertView == null) {
 		v = mInflater.inflate(R.layout.contactlist_group, null);
 	    }
-	    ((TextView) v).setText(mListGroup.get(position));
+	    ((TextView) v).setText(mGroups.get(position));
 	    return v;
 	}
-
     }
 
     /**
-     * Create dialog resend subscription.
-     */
-
-    /**
      * The service connection used to connect to the Beem service.
      */
     private class BeemServiceConnection implements ServiceConnection {
@@ -754,6 +680,7 @@
 	    try {
 		mRoster = mXmppFacade.getRoster();
 		if (mRoster != null) {
+		    Log.d(TAG, "add roster listenet");
 		    mRoster.addRosterListener(mBeemRosterListener);
 		    List<Contact> tmpContactList = mRoster.getContactList();
 		    List<String> tmpGroupList = mRoster.getGroupsNames();
@@ -763,30 +690,13 @@
 		    mListGroup.add(getString(R.string.contact_list_all_contact));
 		    mListGroup.addAll(tmpGroupList);
 		    mListGroup.add(getString(R.string.contact_list_no_group));
-		    mContactOnGroup.clear();
-		    if (tmpGroupList.size() > 0) {
-			List<Contact> tmpNoGroup = new ArrayList<Contact>();
-			for (String s : tmpGroupList) {
-			    List<Contact> tmpList = new ArrayList<Contact>();
-			    for (Contact c : tmpContactList) {
-				if (c.getGroups().size() == 0 && !tmpNoGroup.contains(c))
-				    tmpNoGroup.add(c);
-				else if (c.getGroups().contains(s))
-				    tmpList.add(c);
-			    }
-			    mContactOnGroup.put(s, tmpList);
-			}
-			mContactOnGroup.put(getString(R.string.contact_list_no_group), tmpNoGroup);
-		    } else {
-			mContactOnGroup.put(getString(R.string.contact_list_no_group), tmpContactList);
-		    }
-		    mContactOnGroup.put(getString(R.string.contact_list_all_contact), tmpContactList);
-		    mCurGroup = getString(R.string.contact_list_all_contact);
+		    assignContactToGroups(mRoster.getContactList(), tmpGroupList);
 		    if (!mSettings.getBoolean("settings_key_hide_groups", false))
-			buildBanner();
+			showGroups();
 		    else
 			hideGroups();
-		    buildContactList();
+		    String group = getString(R.string.contact_list_all_contact);
+		    buildContactList(group);
 		}
 	    } catch (RemoteException e) {
 		e.printStackTrace();
@@ -805,6 +715,7 @@
 	    mListContact.clear();
 	    mListGroup.clear();
 	    mContactOnGroup.clear();
+	    mBinded = false;
 	}
     }
 
@@ -817,8 +728,36 @@
      * Hide the groups view.
      */
     private void hideGroups() {
-	ViewStub stub = (ViewStub) findViewById(R.id.contactlist_stub);
-	if (stub == null)
-	    ((LinearLayout) findViewById(R.id.contactlist_groupstub)).setVisibility(View.GONE);
+	View v = findViewById(R.id.contactlist_groupstub);
+	if (v != null)
+	    v.setVisibility(View.GONE);
+    }
+
+    private void assignContactToGroups(List<Contact> contacts, List<String> groupNames) {
+	boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
+	mContactOnGroup.clear();
+	List<Contact> all = new LinkedList<Contact>();
+	List<Contact> noGroups = new LinkedList<Contact>();
+	for (Contact c : contacts) {
+	    if (hideDisconnected && !Status.statusOnline(c.getStatus())) {
+		continue;
+	    }
+	    all.add(c);
+	    List<String> groups = c.getGroups();
+	    if (groups.size() == 0)
+		noGroups.add(c);
+	    else {
+		for (String currentGroup : groups) {
+		    List<Contact> contactsByGroups = mContactOnGroup.get(currentGroup);
+		    if (contactsByGroups == null) {
+			contactsByGroups = new LinkedList<Contact>();
+			mContactOnGroup.put(currentGroup, contactsByGroups);
+		    }
+		    contactsByGroups.add(c);
+		}
+	    }
+	}
+	mContactOnGroup.put(getString(R.string.contact_list_no_group), noGroups);
+	mContactOnGroup.put(getString(R.string.contact_list_all_contact), all);
     }
 }