why my custom listview only display the latest data (only one row in the listview) that was typed in the EditText by clicking the "add" button in that window, by right it should append in the next line of listview items and save and read the data into the .dat file. Could anyone assist me with my code below?
Here's my MainActivity code:
public class MainActivity extends AppCompatActivity implements
View.OnClickListener {
private EditText edText;
private Button btnAdd;
private DatePickerDialog.OnDateSetListener dpdDateTimePicker;
private TextView tvDate;
private TextView tvListItem;
private TextView tvListDate;
private ArrayList<Items> arrItem;
private ItemListAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edText = findViewById(R.id.edText);
btnAdd = findViewById(R.id.btnAdd);
tvDate = findViewById(R.id.tvDate);
tvListItem = findViewById(R.id.tvItem);
tvListDate = findViewById(R.id.tvDate);
ListView lvItemList = (ListView) findViewById(R.id.lvItem);
//Date start
tvDate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
int day = cal.get(Calendar.DAY_OF_MONTH);
DatePickerDialog dialog = new DatePickerDialog(MainActivity.this,
android.R.style.Theme_Holo_Dialog_MinWidth,
dpdDateTimePicker,
year, month,day);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.show();
}
});
dpdDateTimePicker = new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
month = month + 1;
String date = dayOfMonth + "/" + month + "/" + year;
tvDate.setText(date);
}
};
//Date end
//Read Data
arrItem = FileHelper.readData(this);
adapter = new ItemListAdapter(this, R.layout.adapter_view_layout, arrItem);
lvItemList.setAdapter(adapter);
btnAdd.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btnAdd:
ListView lvItemList = (ListView) findViewById(R.id.lvItem);
String itementered = edText.getText().toString();
String dateentered = tvDate.getText().toString();
Items item1 = new Items(itementered, dateentered);
ArrayList<Items> ItemList = new ArrayList<>();
ItemList.add(item1);
FileHelper.writeData(ItemList, this);
adapter = new ItemListAdapter(this, R.layout.adapter_view_layout, ItemList);
lvItemList.setAdapter(adapter);
//Clear TextView and EditText
edText.setText("");
tvDate.setText("");
Toast.makeText(this,"Task Added", Toast.LENGTH_SHORT).show();
break;
}
}
}
FileHelper class to read/write the item into .dat
public class FileHelper {
public static final String FILENAME = "ItemList.dat";
public static void writeData(ArrayList<Items> item, Context context){
try {
FileOutputStream fos = context.openFileOutput(FILENAME, Context.MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(item);
oos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static ArrayList<Items> readData(Context context){
ArrayList<Items> arItemList = null;
try {
FileInputStream fis = context.openFileInput(FILENAME);
ObjectInputStream ois = new ObjectInputStream(fis);
arItemList = (ArrayList<Items>) ois.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return arItemList;
}
}
My custom ItemListAdapter
public class ItemListAdapter extends ArrayAdapter<Items> {
private Context mContext;
int mResource;
public ItemListAdapter(Context context, int resource, ArrayList<Items> objects) {
super(context, resource, objects);
this.mContext = context;
this.mResource = resource;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
//get the Item info
String task = getItem(position).getTask();
String date = getItem(position).getDate();
//Create the task object with the information
Items item = new Items(task, date);
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource, parent, false);
TextView tvDate = (TextView) convertView.findViewById(R.id.tvDate);
TextView tvTask = (TextView) convertView.findViewById(R.id.tvItem);
tvDate.setText(date);
tvTask.setText(task);
return convertView;
}
}
Item class
public class Items implements Serializable {
private String task;
private String date;
public Items(String task, String date) {
this.task = task;
this.date = date;
}
public String getTask() {
return task;
}
public void setTask(String task) {
this.task = task;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
In your onClick
function, you always create a new ArrayList<Items> ItemList
and add a single Items
to it, then you create a new ItemListAdapter
, that displays this new (one-item) list in the lvItemList
.
The code should be more like below.
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btnAdd:
ListView lvItemList = (ListView) findViewById(R.id.lvItem);
String itementered = edText.getText().toString();
String dateentered = tvDate.getText().toString();
Items item1 = new Items(itementered, dateentered);
//do not create a new ArrayList
//ArrayList<Items> ItemList = new ArrayList<>();
//ItemList.add(item1);
//append item1 to the existing one instead
arrItem.add(item1);
//you might have to change this line to handle addition of single item
//FileHelper.writeData(ItemList, this);
//however after a quick look at FileHelper it seems that
FileHelper.writeData(arrItem, this); //might work
//now you also don't need to/shouldn't create a new adapter
//adapter = new ItemListAdapter(this, R.layout.adapter_view_layout, ItemList);
//lvItemList.setAdapter(adapter);
//just notify that arrItem has changed and the adapter will update the ListView
adapter.notifyDataSetChanged();
//Clear TextView and EditText
edText.setText("");
tvDate.setText("");
Toast.makeText(this,"Task Added", Toast.LENGTH_SHORT).show();
break;
}
}
Notice I have also included adapter.notifyDataSetChanged()
, since that is really the reason why adapters are convenient.
You first set the adapter
to lvItemList
in onCreate
:
adapter = new ItemListAdapter(this, R.layout.adapter_view_layout, arrItem);
lvItemList.setAdapter(adapter);
This displays the contents of arrItem
in lvItemList
. If you later wish to add item, you add it to arrItem
and call adapter.notifyDataSetChanged()
to display the changes.
A note on the FileHelper
. It looks like FileHelper.writeData()
rewrites the whole file, so writing arrItem
should produce the desired result, where all items displayed in lvItemList
are also stored in the file.