Androidのテキストビューを効率的に更新するにはどうすればよいですか?

私はパフォーマンスの問題に遭遇するAndroidアプリを開発中です。 私の目標は、AsyncTaskから文字列を受け取ってTextViewに表示することです。 TextViewは最初は空で、他のプロセスが文字列を送信するたびに、テキストビューの現在の内容に文字列を連結します。 私は現在、メインの文字列を格納するためにStringBuilderを使用し、新しい文字列を受け取るたびにStringBuilderに追加して呼び出します

myTextView.setText(myStringBuilder.toString())

問題は、バックグラウンドプロセスが1秒間に最大100個の文字列を送ることができ、私の方法が十分に効率的でないことです。

毎回TextView全体を再描画することは明らかに悪い考え方です(時間複雑度O(N²))が、私は別の解決策を見ていません...

O(N)でこれらの連結を行うことができるTextViewの代替案をご存知ですか?

4

3 答え

文字列間に改行がある限り、ListViewを使用して文字列を追加し、AsyncTaskが文字列を受け取るときに追加するArrayListまたはLinkedListに文字列を保持することができます。

また、TextFieldの無効化を少なくすることも考えられます。例えば10回/秒。これは確かに応答性を改善するでしょう。次のようなことが働く可能性があります:

static long lastTimeUpdated = 0;
if( receivedString.size() > 0 )
{
   myStringBuilder.append( receivedString );
}
if( (System.currentTimeMillis() - lastTimeUpdated) > 100 )
{
    myTextView.setText( myStringBuilder.getChars( 0, myStringBuilder.length() );
}

ストリングがバーストで来た場合 - バースト間隔が2秒以上になるような遅延がある場合は、このコードを再度実行して最後のバーストの末尾部分を取り上げるたびにタイマーをリセットします。

2
追加された

私は最終的にhavexzとGreysonの助けを借りて答えを見つけ、いくつかのコードはここを参照してください。 ストリングが炸裂するにつれて、100ミリ秒ごとにUIを更新することにしました。 レコードについては、私のコードは以下のようになります:

private static boolean output_upToDate = true;

/* Handles the refresh */
private Handler outputUpdater = new Handler();

/* Adjust this value for your purpose */
public static final long REFRESH_INTERVAL = 100;     //in milliseconds

/* This object is used as a lock to avoid data loss in the last refresh */
private static final Object lock = new Object();


private Runnable outputUpdaterTask = new Runnable() {

    public void run() {
       //takes the lock
        synchronized(lock){
            if(!output_upToDate){
               //updates the outview
                outView.setText(new_text);
               //notifies that the output is up-to-date
                output_upToDate = true;
            }
        }
        outputUpdater.postDelayed(this, REFRESH_INTERVAL);
    }

 };

これを私の onCreate()メソッドに入れました:

outputUpdater.post(outputUpdaterTask);

いくつかの説明:私のアプリケーションが onCreate()メソッドを呼び出すと、 outputUpdater ハンドラは 1回しかしこのタスク( outputUpdaterTask )は100ms後にリフレッシュ要求を出します。 lock は、新しい文字列を送信し、output_upToDateをfalseに設定するプロセスと共有されます。

2
追加された

アップデートを抑制してみてください。そのため、世代ごとに100回更新するのではなく、世代ごとに更新するのではなく、文字列ビルダーに100文字列を保存してから、1秒に1回更新します。

コードは次のようになります。

StringBuilder completeStr = new StringBuilder();
StringBuilder new100Str = new StringBuilder();
int counter = 0;

if(counter < 100) {
  new100Str.append(newString);
  counter++;
} else {
  counter = 0;
  completeStr.append(new100Str);
  new100Str = new StringBuilder();
  myTextView.setText(completeStr.toString());
}

注:上記のコードは説明のためのものですので、必要に応じて変更する必要があります。

1
追加された