2

私はいくつかのリストを持っている Android アプリを開発しています。ここで説明するよりも複雑ですが、投稿しているシナリオも予期しない動作をします。
Stack Overflow でいくつかの質問を参照してきましたが、この問題を解決できるものは見つかりませんでした。

したがって、質問のために、このシナリオを作成しました。次のように、文字列の配列を持つアクティビティがあります。

public class TestViewlazyloadActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        String[] items = { "lorem", "ipsum", "dolor", "sit", "amet" };

        ListView list = (ListView) findViewById(R.id.testListView);
        TestAdapter adapter = new TestAdapter(this, R.layout.list_item, items);

        list.setAdapter(adapter);
    }
}

このように私の2つのレイアウトであること:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
       android:orientation="vertical" >

    <ListView
        android:id="@+id/testListView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>

そしてこのように:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/testTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>

ものすごく単純。次に、ViewHolder のアイデアを使用して ArrayAdapter クラスを実装しました。この getView() メソッドは次のとおりです。

public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;
    String item = this.getItem(position);

    if(convertView == null) {
        LayoutInflater inflater = ((Activity) this.getContext()).getLayoutInflater();
        convertView = inflater.inflate(R.layout.list_item, null);

        holder = new ViewHolder();
        holder.textView = (TextView) convertView.findViewById(R.id.testTextView);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    final ViewHolder auxHolder = holder;
    LoadingService.capitalizeItemWithDelay(item, new LoadedCallback() {
        public void onItemLoaded(String item) {
            auxHolder.textView.setText(item);
        }
    });

    return convertView;
}

ただLoadedCallbackのインターフェースであることonItemLoaded。そしてLoadingService.capitalizeItemWithDelay()、(遅延ロードをシミュレートするために)ランダムな時間スリープするスレッドを開始し、このコールバックを大文字の文字列で呼び出します。

通常の動作は、ユーザーが 5 つの空白行を含むリストを表示することです。しばらくすると、ランダムなスリープタイマーが与えられたランダムな順序であっても、アイテムがそれぞれの行にスポーンし始めます。

実際に起こることは、項目が最初の行に 1 つずつロードされ、最終的にそれらのいくつかが実際の場所に設定されるということです。auxHolderそれは奇妙なことですが、最初の要素への参照を TextView に保持するようなものです。ビューがリサイクルされているためか、存在していることが原因であると理解してauxHolderfinalます。

何か案は?前もって感謝します。

4

2 に答える 2

1

変数を取り除き、内部クラスに移動しfinalます。ViewHolderViewHolder auxHolder

これを試して:

   ... 
    LoadingService.capitalizeItemWithDelay(item, new LoadedCallback() {
        ViewHolder auxHolder = holder;
        public void onItemLoaded(String item) {
            auxHolder.textView.setText(item);

finalのようなローカル変数でキーワードを使用するauxHolderと、指定した値が最後の値になるということになります。これが問題を抱えている理由です。もう少し詳しく説明するリンクを次に示します: http://www.javapractices.com/topic/TopicAction.do?Id=23

于 2012-08-14T13:04:57.187 に答える
0

UI スレッドで更新していない可能性があります。投稿で読み込みアクションを実行してみて、すべてが修正されることを確認してください。このようなことをしてみてください

convertView.post(new Runnable() {
    @Override
    public void run() {
        LoadingService.capitalizeItemWithDelay(item, new LoadedCallback() {
            ViewHolder auxHolder = holder;
            public void onItemLoaded(String item) {
                auxHolder.textView.setText(item);
            }
        }
   }
});
于 2012-08-14T13:31:16.597 に答える