web-dev-qa-db-ja.com

Android ArrayListが変更されたときにArrayListおよびListViewを含むArray Adapterが更新されない

AndroidアプリとListViewで構成される画面を備えたアプリがあり、これを使用してデバイスのリストを表示しています。これらのデバイスは配列に保持されています。

ArrayAdapterを使用して、配列の内容を画面のリストに表示しようとしています。

SetupActivityクラスを最初にロードしたときに機能しますが、addDevice()メソッドに新しいデバイスを追加する機能があります。これは、デバイスを保持する配列が更新しました。

リストを更新することになっているnotifyDataSetChanged()を使用していますが、動作しないようです。

public class SetupActivity extends Activity
{   
    private ArrayList<Device> deviceList;

    private ArrayAdapter<Device> arrayAdapter;

    private ListView listView;

    private DevicesAdapter devicesAdapter;

    private Context context;

    public void onCreate(Bundle savedInstanceState)  //Method run when the activity is created
    {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.setup);  //Set the layout

        context = getApplicationContext();  //Get the screen

        listView = (ListView)findViewById(R.id.listView);

        deviceList = new ArrayList<Device>();

        deviceList = populateDeviceList();  //Get all the devices into the list

        arrayAdapter = new ArrayAdapter<Device>(this, Android.R.layout.simple_list_item_1, deviceList);

        listView.setAdapter(arrayAdapter);  
    }

    protected void addDevice()  //Add device Method (Simplified)
    {
        deviceList = createNewDeviceList();    //Add device to the list and returns an updated list

        arrayAdapter.notifyDataSetChanged();    //Update the list
}
}

誰かが私が間違っているところを見ることができますか?

12

ArrayAdapterの場合、notifyDataSetChangedは、アダプタでaddinsertremove、およびclear関数を使用する場合にのみ機能します。

  1. アダプターをクリアするには、clearを使用します-arrayAdapter.clear()
  2. Adapter.addAllを使用して、新しく形成されたリストを追加します-arrayAdapter.addAll(deviceList)
  3. NotifyDataSetChangedを呼び出す

代替案:

  1. 新しいデバイスリストが形成された後、この手順を繰り返します-これは冗長です

    arrayAdapter = new ArrayAdapter<Device>(this, Android.R.layout.simple_list_item_1, deviceList);
    
  2. より柔軟なBaseAdapterおよびListAdapterから派生した独自のクラスを作成します。これが最も推奨されます。
37
Vrashabh Irde

受け入れられた答えは問題を解決しますが、理由の説明は正しくありません。これは重要な概念なので、明確にしようと思いました。 addinsertremove、またはclearがアダプターで呼び出された場合にのみnotifyDataSetChanged()が機能するというSlartibartfastの説明は正しくありません。その説明はsetNotifyOnChange()メソッドにも当てはまります。このメソッドがtrueに設定されている場合(デフォルトでは)、これらの4つのアクションのいずれかが発生すると、自動的にnotifyDataSetChanged()が呼び出されます。ポスターは2つの方法を混同したと思います。 notifyDatasetChanged()自体にはこれらの制限はありません。これは、アダプタに、見ているリストが変更されたことを通知するだけであり、リストへの変更が実際にどのように行われたかは関係ありません。 createNewDeviceList()のソースコードが表示されませんが、作成した元のリストを参照するアダプターがあり、createNewDeviceList()、そしてアダプターがまだ古いリストを指しているため、変更を確認できませんでした。前述のslartibartfastのソリューションは、アダプターをクリアし、更新されたリストをそのアダプターに明確に追加するため機能します。したがって、アダプタが間違った場所を指しているという問題はありません。これが誰かを助けることを願っています!

11
Laura

メソッドaddDeviceが無限ループを引き起こしています。ここで行っているように、それ自体からメソッドを呼び出さないでください。

deviceList = addDevice();
0
petey