1

HTMLページを読み込んで特定のデータを取得するAndroidアプリケーションを作成しています。私はAndroid4.0を使用してテストしましたが、すべて問題ありませんでした。今日、私はそれをandroid 2.2(froyo)で実行しようとしましたが、予期せず深刻なパフォーマンスリークに直面しました。私のコードは次のとおりです。

    ArrayList<News> news = new ArrayList<News>();
    HttpPost httpPost = new HttpPost(BASE_URL
            + "news_view.php");
    List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
    nameValuePairs.add(new BasicNameValuePair("start", String
            .valueOf(start)));
    httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8));
    HttpResponse response = getHttpClientInstance().execute(httpPost);
    HtmlCleaner cleaner = new HtmlCleaner();
    String s = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);
    TagNode root = cleaner.clean(s);
    TagNode[] list = root.getAllElements(false)[1].getAllElements(false);
    if (list.length == 0)
        throw new ParsingException();
    for (int i = 0; i < list.length; i++) {
        String header = list[i].getElementsByName("h3", true)[0].getText()
                .toString();
        TagNode footer = list[i].getElementsByName("h3", true)[1];

        String date = footer.getElementsByName("span", true)[0].getText()
                .toString();
        String author = footer.getElementsByName("a", true)[0].getText()
                .toString();
        String target = footer.getElementsByName("a", true)[1]
                .getAttributeByName("href");
(!)     String text = list[i].getText().toString().replace(header, "")
                .replace(footer.getText().toString(), "")
                .replace('\n', ' ').replace("&nbsp;", " ").trim();
        header = header.replace("&nbsp;", " ").trim();
        date = date.replace("&nbsp;", " ").trim();
        text += "\n" + date;
        News n = new News(header, text, target, author, date,
                News.NEWS_PROJECT);
        news.add(n);
    }

でマークされた行でアプリケーションがフリーズし、(!)続行しません。はい、String.replaceが悪であることは知っていますが、Android ICSに遅れがないため、アプリケーションがそれほどひどく動かなくなるとは思っていませんでした。誰かが私に何が起こっているのか説明できますか?

編集。(!)でマークされている行を次のコードに 置き換えました。

String text0 = list[i].getText().toString();
String text1 = text0.replace(header, "");
String text2 = text1.replace(footer.getText().toString(), "");
String text3 = text2.replace('\n', ' ');
String text4 = text3.replace("&nbsp;", " ");
String text5 = text4.trim();

何も変わっていません。私のアプリケーションは最初の置換(text1)でスタックします。

4

1 に答える 1

0

Android 2.2でのString.replace()の実装にバグがあるようです。Android 2.2の正確なソースコードは見つかりませんでしたが、Android2.1のソースコードを見つけることができました。replaceメソッドの実装は次のとおりです。

public String replace(CharSequence target, CharSequence replacement) {
    if (target == null) {
        throw new NullPointerException("target should not be null");
    }
    if (replacement == null) {
        throw new NullPointerException("replacement should not be null");
    }
    String ts = target.toString();
    int index = indexOf(ts, 0);

    if (index == -1)
        return this;

    String rs = replacement.toString();
    StringBuilder buffer = new StringBuilder(count);
    int tl = target.length();
    int tail = 0;
    do {
        buffer.append(value, offset + tail, index - tail);
        buffer.append(rs);
        tail = index + tl;
    } while ((index = indexOf(ts, tail)) != -1);
    //append trailing chars
    buffer.append(value, offset + tail, count - tail);

    return buffer.toString();
}

targetreplacementが空の文字列である場合、do-whileループは終了しません。indexとは両方ともtailゼロに初期化されます。indexOf(ts, tail)ゼロの値を返しますtail。とは両方ともゼロであるため、tail = index + tl増加しません。tailindextl

これは、観察された動作を説明しています。user1256821がAndroid2.2で同じ動作を観察したので、このバグはAndroid2.2でもまだ存在していたと思います。

于 2012-12-27T15:39:26.650 に答える