1

J'essaie d'ajouter une animation à ma ListView afin que le texte apparaisse dans des lignes séparées lorsque les résultats proviennent d'une requête HTTP GET. Je sais comment faire le fondu et j'ai déjà un adaptateur ListView personnalisé mais le problème est que ListView met à jour toutes les lignes chaque fois qu'un résultat arrive, déclenchant ainsi l'effet de fondu à chaque fois pour la liste entière.Contrôle d'une seule ligne dans ListView

Comment serais-je capable de contrôler une seule ligne afin que ListView n'anime pas chaque ligne à chaque changement de données?

C'est le code que je l'utilise pour remplir le ListView:

private class CustomAdapter extends ArrayAdapter<Row> { 

    public CustomAdapter() { 
     super(Results.this, R.layout.row, dataList); 
    } 

    public View getView(int position, View convertView, ViewGroup parent) { 
     View row = convertView; 
     RowHolder holder = null; 
     if (row == null) { 
      LayoutInflater inflater = getLayoutInflater(); 

      row = inflater.inflate(R.layout.row, parent, false); 
      holder = new RowHolder(row); 
      row.setTag(holder); 
     } else { 
      holder = (RowHolder) row.getTag(); 
     } 
     try { 
      holder.populateRow(dataList.get(position)); 
     } catch (NullPointerException e) { 
      e.printStackTrace(); 
     } 
     return row; 
    } 

} 

    private class RowHolder { 
     private TextView label = null; 
     private TextView count = null; 
     private TextView result = null; 

     public RowHolder(View row) { 
      label = (TextView) row.findViewById(R.id.list_label); 
      count = (TextView) row.findViewById(R.id.list_count); 
      result = (TextView) row.findViewById(R.id.list_result); 
     } 

     public void populateRow(Row r) { 
      label.setText(r.getLabel()); 
      count.setText(r.getCount()); 
      result.setText(r.getResult()); 
      label.startAnimation(fadeIn); 
      count.startAnimation(fadeIn); 
      result.startAnimation(fadeIn); 
     } 
    } 

Toute aide est appréciée, je vous remercie à l'avance!

Edit 1:

Ma AsyncTask:

private class CheckSource extends AsyncTask<String, Void, String> { 

    protected void onPreExecute() { 
     results.setUnixTime(getUnixTime()); 
     results.setLabel(getString(R.string.label)); 
     results.setCount(null); 
     results.setResult(null); 
     results.setResultLabel(""); 
     results.setShowProgress(true); 
     results.setIconType(null); 
     results.setShowIcon(false); 
     results.setHasResults(false); 
     adapter.notifyDataSetChanged(); 
    } 

    @Override 
    protected String doInBackground(String... params) { 

     String query = params[0]; 
     String httpResults = null; 

     try { 
      httpResults = getResults(query, "source"); 
      jsonObject = new JSONObject(httpResults); 
     } catch (IllegalStateException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (JSONException e) { 
      e.printStackTrace(); 
     } catch (URISyntaxException e) { 
      e.printStackTrace(); 
     } 
     return httpResults; 
    } 

    protected void onPostExecute(String results) { 
     try { 
      parseJSON(results); 
     } catch (JSONException e) { 
      e.printStackTrace(); 
      results.setResultLabel("<br />" 
        + getString(R.string.source_not_available) + "<br />"); 
     } 
     results.setShowProgress(false); 
     adapter.notifyDataSetChanged(); 
    } 

    // Parse the retrieved json results 
    private void parseJSON(String jsonResults) throws JSONException { 
     if (jsonResults == null) { 
      results.setResult(null); 
      results.setHasResults(false); 
      results.setResultLabel("<br />" 
        + getString(R.string.source_not_available) + "<br />"); 
      return; 
     } 
     jsonObject = new JSONObject(jsonResults); 
     String result = null; 
     String resultLabel = null; 
     switch (jsonObject.getInt("count")) { 
     case -1: 
      results.setCount(null); 
      results.setHasResults(false); 
      resultLabel = getString(R.string.no_results); 
      break; 
     case 0: 
      results.setCount(null); 
      results.setHasResults(false); 
      resultLabel = getString(R.string.no_results); 
      break; 
     case 1: 
      results.setHasResults(true); 
      results.setCount(jsonObject.get("count").toString() + " " 
        + getString(R.string.one_result)); 
      result = jsonObject.get("url").toString(); 
      resultLabel = getString(R.string.hyperlink_text); 
      break; 
     default: 
      results.setHasResults(true); 
      results.setCount(jsonObject.get("count").toString() + " " 
        + getString(R.string.multiple_results)); 
      result = jsonObject.get("url").toString(); 
      resultLabel = getString(R.string.hyperlink_text); 
      break; 
     } 
     results.setResult(result); 
     results.setResultLabel("<br />" + resultLabel + "<br />"); 
    } 
} 

Le procédé qui exécute la requête HTTP:

private String getResults(String query, String source) 
     throws IllegalStateException, IOException, URISyntaxException { 

    /* Method variables */ 
    StringBuilder builder = new StringBuilder(); 
    String URL = "url"; 
    URI uri; 
    String phrase = "phrase"; 
    List<NameValuePair> params = new ArrayList<NameValuePair>(); 

    /* HTTP variables */ 
    HttpGet httpGet; 
    DefaultHttpClient httpClient; 
    HttpResponse httpResponse; 
    HttpEntity httpEntity; 
    HttpParams httpParams; 

    int socketTimeout = 10000; 
    int connectionTimeout = 10000; 

    // Set the socket and connection timeout values 
    httpParams = new BasicHttpParams(); 
    HttpConnectionParams 
      .setConnectionTimeout(httpParams, connectionTimeout); 
    HttpConnectionParams.setSoTimeout(httpParams, socketTimeout); 
    httpClient = new DefaultHttpClient(httpParams); 
    // Add parameters to the GET request 
    params.add(new BasicNameValuePair("query", query)); 
    params.add(new BasicNameValuePair("type", source)); 
    String paramString = URLEncodedUtils.format(params, "utf-8"); 
    uri = new URI(URL + paramString); 
    httpGet = new HttpGet(uri); 
    // Execute the GET request 
    httpResponse = httpClient.execute(httpGet); 

    /* Read http response if http status = 200 */ 
    if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 
     httpEntity = httpResponse.getEntity(); 
     InputStream content = httpEntity.getContent(); 
     BufferedReader reader = new BufferedReader(new InputStreamReader(
       content)); 
     String line; 
     while ((line = reader.readLine()) != null) { 
      builder.append(line); 
     } 
    } 
    return builder.toString(); 
} 
+0

Veuillez fournir le code après la demande HTTP GET. –

+0

Désolé pour la réponse tardive, j'ai ajouté le code que vous avez demandé à la poste. – Meatje

Répondre

5

Comme Romain Guy a expliqué un certain temps au cours de la session Google I/O, la façon la plus efficace de mettre à jour une seule vue dans une vue de la liste est quelque chose comme ce qui suit (celui-ci de mettre à jour l'ensemble des données de la vue):

ListView list = getListView(); 
int start = list.getFirstVisiblePosition(); 
for(int i=start, j=list.getLastVisiblePosition();i<=j;i++) 
    if(target==list.getItemAtPosition(i)){ 
     View view = list.getChildAt(i-start); 
     list.getAdapter().getView(i, view, list); 
     break; 
    } 

En supposant que target est un élément de l'adaptateur.

Ce code récupérer le ListView, puis parcourir les vues actuellement affichées, comparer l'élément target que vous recherchez avec chaque éléments de la vue affichée, et si votre cible est parmi ceux-ci, obtenir la vue englobante et exécuter l'adaptateur getView sur cette vue pour actualiser l'affichage.

Comme une note de côté invalidate ne fonctionne pas comme certaines personnes attendent et ne rafraîchir la vue comme getView ne, notifyDataSetChanged reconstruirons toute la liste et finissent par appeler getview pour tous les articles affichés et invalidateViews va également affecter un groupe. Une dernière chose, on peut également obtenir des performances supplémentaires si il a seulement besoin de changer un enfant d'une vue de ligne et pas toute la ligne comme le fait getView. Dans ce cas, le code suivant peut remplacer list.getAdapter().getView(i, view, list); (par exemple pour modifier un texte TextView):

((TextView)view.findViewById(R.id.myid)).setText("some new text"); 

Dans le code, nous faisons confiance.

+0

Merci, une explication très claire et complète. – Meatje

+0

@GriffonRL: Salut, ici la cible représente quoi? – Aerrow

+0

Merci! Énorme aide! –

0

Méthode notifyDataSetChanged force pour appeler getView méthode à tous les éléments visibles de l'ListView . Si vous voulez mettre à jour seulement 1 élément spécifique du ListView vous devez aller cet élément au AsynhTask.