1

Я пытаюсь добавить анимацию в свой ListView, чтобы текст исчезал в отдельные строки, поскольку результаты поступают из запроса HTTP GET. Я знаю, как сделать эффект постепенного исчезновения, и у меня уже есть настраиваемый адаптер ListView, но проблема в том, что ListView обновляет все строки каждый раз, когда приходит результат, тем самым вызывая постепенное выгорание для всего списка.Управление одной строкой в ​​ListView

Как я могу управлять одной строкой, чтобы ListView не анимировал каждую строку при каждом изменении данных?

Это код, я использую для заполнения 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); 
     } 
    } 

Любой помощь ценятся, спасибо заранее!

Edit 1:

Мой 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 />"); 
    } 
} 

Метод, который выполняет запрос 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

Просьба указать код после запроса HTTP GET. –

+0

Извините за поздний ответ, я добавил код, который вы запросили в сообщении. – Meatje

ответ

5

Как Romain Guy объяснил некоторое время назад во время сессии Google I/O, самый эффективный способ обновить только один вид в списке что-то вроде следующего (это одно обновление целое представление данных):

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; 
    } 

Предполагая, что target является одним из элементов адаптера.

Этого код извлечение ListView, а затем просмотреть отображаемое в данный момент точки зрения, сравнить target детали, которую вы ищете с каждым отображаются вид элементов, и если ваша цель среди тех, получить вид ограждающий и выполнить адаптер getView на том, что чтобы обновить дисплей.

В качестве примечания invalidate не работает, как некоторые люди ожидают, и не обновит вид как GetView делает, notifyDataSetChanged будет перестраивать весь список и в конечном итоге вызов getview для каждых отображаемых элементов и invalidateViews также будет влиять на кучу.

Последнее, что также можно получить дополнительную производительность, если ему нужно только изменить дочерний элемент представления строки, а не всю строку, такую ​​как getView. В этом случае, следующий код может заменить list.getAdapter().getView(i, view, list); (пример для изменения TextView текста):

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

В коде мы доверяем.

+0

Спасибо, очень ясное и полное объяснение. – Meatje

+0

@GriffonRL: Привет, здесь цель представляет что? – Aerrow

+0

Спасибо! Огромная помощь! –

0

Метод notifyDataSetChanged силы для вызова getView метод для всех видимых элементов ListView , Если вы хотите обновить только 1 конкретный элемент ListView, вам необходимо пройти этот элемент до AsynhTask.