2016-08-18 9 views
1

カスタムBaseAdapterクラスを作成して、ListViewに登録キーを表示しました。リストに別のキーを追加してnotifyDataSetChanged()を呼び出すと、リストビューは視覚的にうまく更新されます。私のデータ構造は、単にいくつかのStringとintを含む単純な構造のArrayListです。ただし、キーリストをクリアしてnotifyDataSetChanged()に電話すると、視覚的に何も起こりません。私が閉じると、アプリを開くと、リストは空である必要があります。 notifyDataSetChanged()に電話する前に、私は今notifyDataSetInvalidated()と呼んでいます。これにより、キーをクリアするとすぐにビジュアルが正しく更新されますが、そのアダプタを使用して完全に終了していない限り、Googleのdocumentationはその方法の使用を警告します。私はそれらを拭き取った後にさらに多くのキーを登録すると、それでもListViewに表示され、notifyDataSetInvalidated()が実用的な解決策であるように見えます。 ListViewに同じBaseAdapterとArrayListを使用し続けると、このメソッドに関連する危険がありますか?より良い解決策はありますか?ここに私のカスタムBaseAdapterの実装です:BaseAdapterでアイテムが正しく表示されない

class KeyAdapter extends BaseAdapter implements Database.KeyRegistrationListener { 

    private ArrayList<Database.KeyDetails> keyInfo; 

    public KeyAdapter(ArrayList<Database.KeyDetails> keyInfo) { 

     this.keyInfo = keyInfo; 

    } 

    @Override 
    public int getCount() { 

     return keyInfo.size(); 

    } 

    @Override 
    public Database.KeyDetails getItem(int position) { 

     return keyInfo.get(position); 

    } 

    @Override 
    public long getItemId(int position) { 

     return position; 

    } 

    @Override 
    public View getView(int pos, View convertView, ViewGroup parent) { 

     TextView userID; 
     TextView appName; 
     TextView date; 
     TextView time; 

     if (convertView == null) { 

      convertView = getLayoutInflater().inflate(R.layout.registration_item, parent, false); 

      userID = (TextView) convertView.findViewById(R.id.user_id); 
      appName = (TextView) convertView.findViewById(R.id.app_name); 
      date = (TextView) convertView.findViewById(R.id.date_used); 
      time = (TextView) convertView.findViewById(R.id.time_used); 

      convertView.setTag(R.id.user_id, userID); 
      convertView.setTag(R.id.app_name, appName); 
      convertView.setTag(R.id.date_used, date); 
      convertView.setTag(R.id.time_used, time); 

     } else { 

      userID = (TextView) convertView.getTag(R.id.user_id); 
      appName = (TextView) convertView.getTag(R.id.app_name); 
      date = (TextView) convertView.getTag(R.id.date_used); 
      time = (TextView) convertView.getTag(R.id.time_used); 

     } 

     Database.KeyDetails key = getItem(pos); 

     userID.setText(key.userID); 
     appName.setText(key.appName); 
     date.setText(key.date); 
     time.setText(key.time); 

     return convertView; 

    } 

    @Override 
    public void notifyKeysUpdated(Database.KeyDetails newKeyDesc) { 

     if (newKeyDesc == null) { 

      keyInfo.clear(); 
      notifyDataSetInvalidated(); 
      notifyDataSetChanged(); 

     } else{ 

      keyInfo.add(newKeyDesc); 
      notifyDataSetChanged(); 

     } 

    } 

} 

私はデータベースにキーを追加するたびにnotifyKeysUpdated()メソッドはSQLiteのデータベースのための私のラッパークラスによって呼び出されます。私のデータベースオブジェクトがリスナーnullにフィードしている場合は、データベース内のすべてのキーがクリアされ、ListViewが視覚的に空であることを意味します。

編集:私はnotifyDataSetInvalidated()を使い始めて以来 、ListViewコントロールは、もはや私は新しいキーを登録する際など、何も表示されません。

答えて

0

結局のところ、この問題は自分のデータへの参照でエラーになることがわかりました。 Javaは非常に安全な言語であり、明示的なポインタを許可していないので、私はListViewに更新しようとしていたものを渡すのではなく、データオブジェクトのコピーを作ったと思います。コードを簡素化し、可能な限りシンプルな方法でテーブルにデータを作成して渡すと、完全に機能します。

1

アンドロイドでBaseAdapterとリストビューのソースコードも、この質問(Android - What does adapter.notifyDataSetInvalidated do?

にいくつかの研究を行った後、あなたは確かかもしれない最初の事はあなたのデータがアダプタに完全に拘束するものではない、です。通常、BaseAdapterはインターフェイスのコレクションにすぎず、arraylistのフィールドは含まれていません。それはサイズを意味し、データを取得することがあなたにあります。データセットがもう有効でないことを示すには、notifyDataSetInvalidated()メソッドをオーバーライドする必要があります。

私のプロジェクトにあなたのコードをコピーしようとしました。 notifyDataSetInvalidated()メソッドとnotifyDataSetChanged()メソッドの両方がリスト全体を更新し、arraylistはアダプタに完全にバインドされていません。これは単なるデータのリストを取得するためのアダプタです。私はGoogleのドキュメントは、このメソッドで何をすべきかを明確に説明していないのだろうかと思っています。

+0

私が見た他のすべてのBaseAdapter実装では、カスタムサブクラスはそれ自身のデータ構造を格納しており、私が行ったいくつかのメソッドを実装しました。リストは確実に更新されています。何らかの理由で、リストに追加するとビューのみが更新されますが、アイテムを削除すると更新されません。私は、私のアプリに登録されているキーが最初にSQLiteデータベースに保存されていることを考慮して、代わりにCursorAdapterに変更できると思います。しかし、努力をいただきありがとうございます! –