#問題のコード
ListWorkActivity.java
public class ListWorkActivity extends AppCompatActivity implements View.OnClickListener {
private ArrayList<Record> listItems = new ArrayList<>();
private DateArrayAdapter arrayAdapter;
private ListView listView;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
//listViewにlistItemsをセットしたい
listView = findViewById(R.id.listView);
{...}
//nullじゃないlistView(ここは省略)と自作のDateArrayAdapter
arrayAdapter = new DateArrayAdapter(this, R.layout.date_list, listItems);
listView.setAdapter(arrayAdapter);
}
//menu内のボタンをクリックするとListViewの中身が逆順になるようにしたい
public boolean onOptionsItemSelected(MenuItem menuItem){
int item = menuItem.getItemId();
switch (item) {
{...}
case R.id.menu_button:
//button
//逆順にする
Collections.reverse(listItems);
arrayAdapter.clear();
arrayAdapter.addAll(listItems);
arrayAdapter.notifyDataSetChanged();
break;
}
return false;
}
##自作のアダプタークラス
ListViewにカスタマイズしたレイアウトで要素を表示するためのクラスです。
DateArrayAdapter.java
public class DateArrayAdapter extends ArrayAdapter<Record> {
private int mResource;
private List<Record> mItems;
private LayoutInflater mInflater;
/**
* コンストラクタ
* @param context コンテキスト
* @param resource レイアウトファイルのリソースID
* @param items リストビューの要素
*/
public DateArrayAdapter(Context context, int resource, ArrayList<Record> items){
super(context, resource, items);
mResource = resource;
mItems = items; //ArrayList -> List
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return mItems.size();
}
@Override
public Record getItem(int position) {
return mItems.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView != null){
view = convertView;
}else{
view = mInflater.inflate(mResource, null);
}
Record record;
//リストビューに表示する要素を取得
record = getItem(position);
//date
TextView textViewDate = view.findViewById(R.id.textViewDate_DateLayout);
textViewDate.setText(record.getDate());
//work
TextView textViewWork = view.findViewById(R.id.textViewWork_DateLayout);
textViewWork.setText(record.getWork());
//memo
TextView textViewMemo = view.findViewById(R.id.textViewMemo_DateLayout);
textViewMemo.setText(record.getMemo());
return view; //may not be null
}
}
Record.javaはデータ格納用のクラスです
Record.java
public class Record {
//日付、work、メモを格納するクラス
private String date;
private String work;
private String memo;
//空のコンストラクタ
public Record(){ }
//コンストラクタ
public Record(String date, String work, String memo){
this.date = date;
this.work = work;
this.memo = memo;
}
public String getDate() {
return date;
}
public String getWork() {
return work;
}
public String getMemo() {
return memo;
}
}
#起こった問題について
####やりたかったこと
・listViewの中身を逆順にして表示する
####実際はどうなったか
・clear()をするとlistItemsが消えた
//onOptionsItemSelected内の処理
Collections.reverse(listItems); //ここでlistItemsを逆順にすることには成功
arrayAdapter.clear(); //listItems の要素数が0になる = listItemsが消えた!?
arrayAdapter.addAll(listItems);
arrayAdapter.notifyDataSetChanged();
これによると、arrayAdapterのコンストラクタでcollectionを渡してしまうと、そのリストは変更不可能になってしまい、clear()を使うと例外が発生するということです。
DateArrayAdapterのコンストラクタではsuper(context, resource, items) (items = listView)を呼び出していたのでうまくいかなかったわけです。
#解決法
ArrayAdapterにはほかにもコンストラクタがあるので、T[]を使わないコンストラクタをt作りました。
DateArrayAdapter.java
public class DateArrayAdapter extends ArrayAdapter<Record> {
private int mResource;
private List<Record> mItems;
private LayoutInflater mInflater;
/**
* コンストラクタ
* @param context コンテキスト
* @param resource レイアウトファイルのリソースID
* @param items リストビューの要素
*/
//問題のコンストラクタ。引数にリストを渡している。
public DateArrayAdapter(Context context, int resource, ArrayList<Record> items){
super(context, resource, items);
mResource = resource;
mItems = items; //ArrayList -> List
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
//新しいコンストラクタ。引数にarrayListは渡していない。
public DateArrayAdapter(Context context, int resource){
super(context, resource);
mResource = resource;
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
//新しいコンストラクタではmItemsを設定できないので、セッターを用いる。
//これがないとほかのメソッドがmItemsを使えなくて動かなくなるので注意
public void setItems(List<Record> mItems) {
this.mItems = mItems;
}
//あとは同じです。
@Override
public int getCount() {
return mItems.size();
}
{...}
}
ListWorkActivity.java
//アダプターをセットするところがこんな感じに変わる
arrayAdapter = new DateArrayAdapter(this, R.layout.date_list);
arrayAdapter.addAll(listItems);
arrayAdapter.setItems(listItems);
listView.setAdapter(arrayAdapter);
ほかにいい解決法がありそうなら教えていただけると嬉しいです。