3

ユーザーが1つのアクティビティを閉じて前に戻ると、リストの更新に問題があります。問題は非常に一般的ですが、解決できません。

onResumeメソッドをオーバーライドしました:

@Override
public void onResume() {
    super.onResume();
    populateList();
}

PopulateList()は、listViewに文字列のリストを入力するメソッドです。

arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item,list);
listView.setAdapter(arrayAdapter);

問題は、2番目のアクティビティが閉じられると、新しいアイテムがListViewに再度追加されるため、すべてのアイテムが2倍になることです。リフレッシュされていないように。

notifyDataSetChanged()をonResume()に入れると、アクティビティが最初に開始されたときにアダプターが初期化されていないため、nullPointerExceptionがスローされます。

これをどう処理するかわかりません。

public class testActivity extends Activity {


    private int id=1;
    private ListView listView;
    private CustomArrayAdapter arrayAdapter;
    private ArrayList<String> list = new ArrayList<String>();
    ArrayList<Item> objectList = new ArrayList<Item>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);

    }

    @Override
    public void onResume() {
        super.onResume();
        populateList();
    }

    private void populateList() {
        try {
            objectList = new GetAsyncTask(id).execute();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (TimeoutException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        int size = objectList.size();
        String name;

        for (int i = 0; i < size; i++) {
            name = objectList.get(i).getName();
            list.add(name);
        }

        arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item,
                list);
        listView.setAdapter(arrayAdapter);
    }
}
4

4 に答える 4

5

すぐに、アダプターがそうでない場合にのみコマンドを実行する単純な条件ステートメントを使用して、これを簡単にノックアウトできますnull

    if (adapter != null) {
        adapter.notifyDataSetChanged();
    }

しかし、これは、より深いレベルで、必ずしもより機能的であるとは限りませんが、より効率的になるようにコードをいくらかリファクタリングできるように思えます。


次のようにします。

private int id = 1;
private ListView listView;
private CustomArrayAdapter arrayAdapter;
private ArrayList<String> list = new ArrayList<String>();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);
}

@Override
public void onResume() {
    super.onResume();
    populateList();
}

private void populateList() {

    ArrayList<Item> objectList;
    try {
        objectList = new GetAsyncTask(id).execute();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    } catch (TimeoutException e) {
        e.printStackTrace();
    }

    list.clear();
    for (int i = 0; i <objectList.size(); i++) {
        String name = objectList.get(i).getName();
        list.add(name);
    }
    if (arrayAdapter == null) {
        arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item, list);
        listView.setAdapter(arrayAdapter);
    } else {
        arrayAdapter.notifyDataSetChanged();            
    }
}
于 2013-01-09T21:20:28.830 に答える
2

デバイスから list_of_files をキャッチし、それを populateList() のリストに入れます。次に、アダプターを適用します。戻ると、デバイスのリストが変更されるため、同じことを繰り返してリストに入れます。問題は ListView にまだ古い項目があり、新しい項目が最後に追加されていることです。だから重複している。

list.clear()基本的なアプローチの 1 つは、新しいデータを追加する前に呼び出すことです。これにより、古いデータが消去され、重複が防止されます。(しかし、問題のコードを見ずに正確な答えを提供するのは難しいです...)


追加
このコードをonPostExecute()メソッド内に追加する必要がありGetAsyncTaskます。

int size = objectList.size();
String name;

list.clear(); // or list = new ArrayList<String>();
for (int i = 0; i < size; i++) {
    name = objectList.get(i).getName();
    list.add(name);
}

arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item, list);
listView.setAdapter(arrayAdapter);

がアクティビティにネストされていない限り、これを使用GetAsyncTaskするにはいくつかの変数を移動する必要がありますGetAsyncTask。ただし、アクティビティが結果を待つ必要がないため、このアプローチの方が優れています (「アプリケーションが応答していません」というエラーが発生する可能性があります)。

于 2013-01-09T21:34:50.853 に答える
0

あなたはアプリコードの一部しか表示していないので、ここではオフベースかもしれませんが、Cursor をlist使用して変数を返しlist、ArrayAdapter を作成するために使用していると思います...

データを「新鮮」にしたい場合は、LoaderManager で CursorLoader を使用してみませんか? LoaderManager にはいくつかの利点があり (UI スレッドからクエリを移動するなど)、DB の変更を監視する際には、LoaderManager が少し面倒な作業を行います。

非常に役立つブログ投稿があります - http://www.androiddesignpatterns.com/2012/07/understanding-loadermanager.html

これはすべて、データベースからデータを取得していると仮定しています...

于 2013-01-09T21:29:15.337 に答える
0

問題は、最初にリストをクリアせずに関数 populateList() を呼び出していることです。そうすれば、populate list は単純に前のコンテンツに追加するだけです。

これは正しい方法です:

public void onResume() {
super.onResume();
list = new ArrayList<String>();
populateList();  }

関数内にアダプターを設定した理由についてもわかりませんpopulateList()

これを試してみてください。

    private ArrayList<String> list = new ArrayList<String>();

    private ArrayList<String> populateList() {
            try {
                objectList = new GetAsyncTask(id).execute();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (TimeoutException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            int size = objectList.size();
            String name;

            for (int i = 0; i < size; i++) {
                name = objectList.get(i).getName();
                list.add(name);
            }
 return list;
        }
     arrayAdapter = new CustomArrayAdapter(this, R.layout.symbol_item,
                    populateList());
            listView.setAdapter(arrayAdapter);

そうすれば、アダプターを外に出すことで、これを onResume() 関数で簡単に使用できます

public void onResume() {
    super.onResume();
    list = new ArrayList<String>();
    }
于 2014-04-10T20:10:49.373 に答える