Bonjour,

J'ai besoin de récupérer un assez grand nombre d'informations depuis un serveur, et je parse donc un fichier XML.
J'ai beaucoup d'entrées dans ce fichier XML, et je créé environ 3000 objets Client qui seront stockés dans une liste ArrayList<Client>.

Pour information, j'utilise toutes les informations (toutes les balises, tous les attributs...) du fichier XML.
Je n'ai donc pas spécialement besoin d'un système qui saute plein de balises/tags ou autre.

Je connais donc plusieurs moyens pour parser un fichier XML : DOMDocument, XmlPullParser, et SAX.
J'ai effectué plusieurs tests, et voici ce qui en sort dans mon cas :
- SAX est le plus rapide, mais on voit plusieurs actions du Garbage Collector dans le logcat.
- DOMDocument est le moins rapide, et on voit plusieurs actions du Garbage Collector (c'est sans doute le pire, et je m'en doutais).
- XmlPullParser est au milieu en terme de rapidité, et c'est celui qui demande le moins d'action du Garbage Collector.

Code Trace du logcat à l'exécution : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
01-28 09:01:02.923: E/SAX(2063): début SAX
01-28 09:01:03.113: D/dalvikvm(2063): GC_CONCURRENT freed 92K, 3% free 6337K/6471K, paused 27ms+5ms, total 74ms
01-28 09:01:04.273: D/dalvikvm(2063): GC_CONCURRENT freed 29K, 2% free 6735K/6855K, paused 29ms+35ms, total 126ms
01-28 09:01:05.163: D/dalvikvm(2063): GC_CONCURRENT freed 12K, 2% free 7129K/7239K, paused 30ms+4ms, total 106ms
01-28 09:01:06.043: D/dalvikvm(2063): GC_CONCURRENT freed 14K, 2% free 7515K/7623K, paused 29ms+55ms, total 138ms
01-28 09:01:06.713: D/dalvikvm(2063): GC_CONCURRENT freed 16K, 2% free 7894K/8007K, paused 23ms+22ms, total 124ms
01-28 09:01:06.873: E/SAX(2063): fin SAX
 
 
01-28 09:01:29.313: E/DOM(2114): début DOM
01-28 09:01:29.534: D/dalvikvm(2114): GC_CONCURRENT freed 96K, 4% free 6332K/6535K, paused 20ms+15ms, total 74ms
01-28 09:01:31.894: D/dalvikvm(2114): GC_CONCURRENT freed 30K, 2% free 6726K/6855K, paused 22ms+28ms, total 176ms
01-28 09:01:33.713: D/dalvikvm(2114): GC_CONCURRENT freed 15K, 2% free 7126K/7239K, paused 30ms+21ms, total 134ms
01-28 09:01:35.523: D/dalvikvm(2114): GC_CONCURRENT freed 16K, 2% free 7507K/7623K, paused 19ms+22ms, total 98ms
01-28 09:01:37.126: D/dalvikvm(2114): GC_CONCURRENT freed 79K, 2% free 7850K/8007K, paused 29ms+18ms, total 144ms
01-28 09:01:37.723: E/DOM(2114): fin DOM
 
 
01-28 09:01:57.684: E/XmlPullParser(2166): début XmlPullParser
01-28 09:01:57.884: D/dalvikvm(2166): GC_CONCURRENT freed 97K, 4% free 6334K/6535K, paused 9ms+13ms, total 91ms
01-28 09:02:01.714: D/dalvikvm(2166): GC_CONCURRENT freed 67K, 3% free 6686K/6855K, paused 31ms+9ms, total 112ms
01-28 09:02:02.744: E/XmlPullParser(2166): fin XmlPullParser

Code Aperçu du fichier XML : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
 
<?xml version="1.0" encoding="UTF-8"?>
<clients>
	<client machin="fesfse" truc="sfeg" />
	<client machin="srg" truc="dfhjjtr" />
	... 
</client>

Code Aperçu de l'asynctask : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
 
public class XMLTask extends AsyncTask<Void, Void, ClientAdapter>
{
 
	private String url;
	private Context context;
        private MonListener monListener;
 
	public XMLTask(String url, Context context, MonListener monListener)
	{
		this.url = url;
		this.context = context;
                this.monListener = monListener;
	}
 
 
	@Override
    protected ClientAdapter doInBackground(Void... params)
    {
		try
		{
			List<Client> clients;
 
 
Log.e("ClientXmlParser", "début");
				ClientXmlParser parser = new ClientXmlParser();
				clients = parser.parse(Network.streamUrl(this.url));
Log.e("ClientXmlParser", "fin");
 
 
 
 
Log.e("DOM", "début");	
				URL mUrl = new URL(this.url);
				DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
				Document doc = builder.parse(new InputSource(mUrl.openStream()));
 
				Element racine = doc.getDocumentElement();
 
				NodeList liste = racine.getElementsByTagName("client");
				Element client;
 
 
				// Parcours des clients
				clients = new ArrayList<Client>();
				int nbClient = liste.getLength();
 
				for (int i = 0; i < nbClient; i++)
				{
					client = (Element) liste.item(i);
 
					clients.add(new Client(client.getAttribute("truc"), client.getAttribute("machin"), ...));					
				}
Log.e("DOM", "fin");
 
 
 
Log.e("SAX", "début");
				URL url = new URL(this.url);
				ClientHandler handler = new ClientHandler();
 
				XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();			    
			    xmlReader.setContentHandler(handler);
 
			    xmlReader.parse(new InputSource(url.openStream()));
			    clients = handler.getClientsList();
Log.e("SAX", "fin");
 
 
 
 
				if (clients == null || clients.size() == 0) { return null; }
				else { return new ClientAdapter(clients, this.context, R.layout.clientList); }
 
 
	    }		
		catch (Exception e) { return null; }
    }
 
 
	@Override
	protected void onPostExecute(ClientAdapter adapter)
	{		
		if (adapter != null)
		{
			this.monListener.onSuccess(adapter);
		}
		else
		{
			this.monListener.onError();
		}
	}
 
}

Code Aperçu de la classe ClientHandler (SAX) : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
public class ClientHandler extends DefaultHandler
{
 
    private List<Client> clients_list;
 
	public ClientHandler() 
    {
        this.clients_list = new ArrayList<Client>();
    }
 
 
	@Override
    public void startElement(String nameSpaceURI, String localName, String qName, Attributes attributs) throws SAXException 
    {
    	if (localName.equals("client"))
    	{        
    		String machin = attributs.getValue("machin");
    		String truc = attributs.getValue("truc"); 
 
			this.clients_list.add(new Client(machin, truc));
    	}
    }
 
 
	public List<Client> getClientsList()
	{
		return this.clients_list;
	}
 
}

Code Aperçu de la classe ClientXmlParser (XmlPullParser) : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
 
public class ClientXmlParser
{
 
	private static final String namespace = null; // pas de namespace
 
 
	public List<Client> parse(InputStream inputStream) throws XmlPullParserException, IOException
	{
		try
		{
			XmlPullParser parser = Xml.newPullParser();
 
			parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
			parser.setInput(inputStream, null);
			parser.nextTag();
 
			return readClients(parser);
		}
		finally
		{
			inputStream.close();
		}
	}
 
 
 
	private List<Client> readClients(XmlPullParser parser) throws XmlPullParserException, IOException
	{
		List<Client> clients = new ArrayList<Client>();
 
		parser.require(XmlPullParser.START_TAG, namespace, "clients");
 
		while (parser.next() != XmlPullParser.END_TAG)
		{
			if (parser.getEventType() != XmlPullParser.START_TAG)
			{
				continue;
			}
 
 
			String name = parser.getName();
 
			if (name.equals("client"))
			{
				clients.add(readClient(parser));
			}
			else
			{
				skip(parser);
			}
		}
 
		return clients;
	}
 
 
 
	private Client readClient(XmlPullParser parser) throws IOException, XmlPullParserException
	{
		parser.require(XmlPullParser.START_TAG, namespace, "client");
 
		String machin = parser.getAttributeValue(null, "machin");
		String truc = parser.getAttributeValue(null, "truc");
		...	
 
		// TODO : nextTag + require OU next ?
 
		//parser.nextTag();
		//parser.require(XmlPullParser.END_TAG, namespace, "client");
		parser.next();
 
		return new Client(machin, truc, ...);
	}
 
 
 
	private void skip(XmlPullParser parser) throws XmlPullParserException, IOException
	{
		if (parser.getEventType() != XmlPullParser.START_TAG)
		{
			throw new IllegalStateException();
		}
 
 
		int depth = 1;
		while (depth != 0)
		{
			switch (parser.next())
			{
				case XmlPullParser.END_TAG:
					depth--;
					break;
 
				case XmlPullParser.START_TAG:
					depth++;
					break;
			}
		}
	}
}


Question 1 : Est-ce mieux d'utiliser XML ou JSON ? Pourquoi ?

Question 2 : Est-ce que mon code est correcte ?

Question 3 : Par rapport à ce dont j'ai besoin, quelle est le meilleur parser XML selon vous ?

Question 4 : Que signifie ces différentes actions du Garbage Collector ?

Question 5 : Pourquoi la mémoire ne redescends pas ? (nombres en gras : GC_CONCURRENT freed 111K, 2% free, 14394K/14599K, paused 24ms+6ms total 173ms)
Une fois que je quitte l'activité qui affiche la liste, les objets ne sont-ils pas censés être détruits/désalloués état donné que je ne m'en sert pas en dehors de cette activité ?
Pire, si je lance plusieurs fois de suite l'activité de récupération/création de la liste, on voit bien que la mémoire augmente et on arrive même à un message "Clamp target GC heap...".
D'ailleurs, j'ai testé avec 20.000 entrées et le système force l'application à se fermer (sauf avec XMLPullParser).

Code Trace du logcat après plusieurs exécutions : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
 
01-28 08:58:05.751: D/dalvikvm(1993): GC_CONCURRENT freed 92K, 3% free 6341K/6535K, paused 29ms+9ms, total 89ms
01-28 08:58:07.001: D/dalvikvm(1993): GC_CONCURRENT freed 26K, 2% free 6735K/6855K, paused 26ms+4ms, total 78ms
01-28 08:58:07.770: D/dalvikvm(1993): GC_CONCURRENT freed 12K, 2% free 7134K/7239K, paused 29ms+4ms, total 98ms
01-28 08:58:08.550: D/dalvikvm(1993): GC_CONCURRENT freed 13K, 2% free 7513K/7623K, paused 22ms+4ms, total 104ms
01-28 08:58:09.250: D/dalvikvm(1993): GC_CONCURRENT freed 16K, 2% free 7898K/8007K, paused 37ms+57ms, total 154ms
01-28 08:58:12.560: D/dalvikvm(1993): GC_CONCURRENT freed 50K, 2% free 8372K/8519K, paused 23ms+4ms, total 176ms
01-28 08:58:13.860: D/dalvikvm(1993): GC_CONCURRENT freed 39K, 2% free 9024K/9159K, paused 22ms+21ms, total 127ms
01-28 08:58:17.340: D/dalvikvm(1993): GC_CONCURRENT freed 61K, 2% free 9899K/10055K, paused 52ms+24ms, total 274ms
01-28 08:58:19.590: D/dalvikvm(1993): GC_CONCURRENT freed 63K, 2% free 11052K/11207K, paused 27ms+0ms, total 136ms
01-28 08:58:24.331: D/dalvikvm(1993): GC_CONCURRENT freed 81K, 2% free 12568K/12743K, paused 22ms+34ms, total 183ms
01-28 08:58:29.841: I/dalvikvm-heap(1993): Clamp target GC heap from 16.094MB to 16.000MB
01-28 08:58:29.841: D/dalvikvm(1993): GC_CONCURRENT freed 111K, 2% free 14394K/14599K, paused 24ms+6ms, total 173ms



Merci d'avance pour votre aide.