Search code examples
androidlistviewarraylistcustom-adapter

Listview only display one item after add the second item


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;
}
}

Solution

  • 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.