在ListView中控制单行

Mea*_*tje 1 android android-animation android-listview android-adapter

我正在尝试向ListView添加动画,因此当结果来自HTTP GET请求时,文本将淡入单独的行.我知道如何进行淡入效果并且我已经有一个自定义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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

任何帮助表示赞赏,谢谢!

编辑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 />");
    }
}
Run Code Online (Sandbox Code Playgroud)

执行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();
}
Run Code Online (Sandbox Code Playgroud)

Gri*_*nRL 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;
    }
Run Code Online (Sandbox Code Playgroud)

假设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");
Run Code Online (Sandbox Code Playgroud)

在我们信任的代码中.