Somil Rastogi
Somil Rastogi

Reputation: 61

Adding multiple items to a listview with each item received from another intent on a button click

I'm creating a birthday reminder application, where the app starts on the main activity, goes to a new activity using intent and there the person selects the birthday, and the selected birth day, month and year is returned back to the main activity. Then in the main activity I've created a new button which retrieves all the information sent by the bday picker activity and tries to display it in a list activity every time I press a button.

The problem I'm facing is if once I run the app, the birthday gets recorded and is shown in the listview, but if I add another Birthday and try to display it in the listview,the previous record is removed and I'm left with only the present record.

What I exactly want to know is how can I add items in my listView so that all my previous birthdays are shown as well.

The code File Provided is as Follows: activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:weightSum="10"
    tools:context=".MainActivity">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_weight="1"
        android:background="#97B252D5">

        <TextView
            android:id="@+id/editText"
            android:layout_width="213dp"
            android:layout_height="52dp"
            android:ems="10"
            android:fontFamily="sans-serif-black"
            android:text="Remindro"
            android:textAllCaps="true"
            android:textAppearance="@style/TextAppearance.AppCompat.Large"
            android:textSize="36sp"
            android:textStyle="bold|italic"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.067"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/newEntry"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#C1E6E60F"
            android:fontFamily="sans-serif-black"
            android:onClick="addNewEntry"
            android:text="+ADD"
            android:textAppearance="@style/TextAppearance.AppCompat.Large"
            android:textSize="30sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.88"
            app:layout_constraintStart_toEndOf="@+id/editText"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.48" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_weight="9"
        android:background="#A071D4ED">


        <ListView
            android:id="@+id/list"
            android:layout_width="410dp"
            android:layout_height="596dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/viewRecord"
            app:layout_constraintVertical_bias="0.0" />

        <Button
            android:id="@+id/viewRecord"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:background="#9650EC31"
            android:onClick="viewRecord"
            android:text="View Record"
            android:textAppearance="@style/TextAppearance.AppCompat.Large"
            android:textStyle="bold"
            app:layout_constraintBottom_toTopOf="@+id/_dynamic"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.0" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

Code file for : MainActivity.java

package com.example.remindro;

import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import androidx.appcompat.app.AppCompatActivity;

import java.util.ArrayList;
import java.util.Calendar;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "";

    ArrayList<String> listItems = new ArrayList<String>();

    ArrayAdapter<String> adapter;

    Calendar calendar = Calendar.getInstance();
    int thisYear = calendar.get(Calendar.YEAR);
    int thisMonth = calendar.get(Calendar.MONTH) + 1;
    int thisDay = calendar.get(Calendar.DAY_OF_MONTH);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        adapter=new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1,
                listItems);
        ListView records = (ListView) findViewById(R.id.list);
        records.setAdapter(adapter);
    }

    public void addNewEntry(View v)
    {
        Intent adding = new Intent();
        adding.setClass(this,addinglist.class);
        startActivity(adding);
        finish();

    }
    public void viewRecord(View v)
    {
        Intent receiver = getIntent();
        int day = receiver.getIntExtra("day",0);
        int month = receiver.getIntExtra("month",0);
        int year = receiver.getIntExtra("year",0);
        String name = receiver.getStringExtra("nameofperson");
        String choice = receiver.getStringExtra("radio");
        String mss = name + " has his " + choice + " on " + day + "/" + month + "/" + year;
        //Toast.makeText(getApplicationContext(),mss,Toast.LENGTH_LONG).show();

        int age = thisYear - year;
        calendar.set(thisYear,thisMonth,thisDay);
        Calendar calendar1 = Calendar.getInstance();
        calendar1.set(thisYear,month,day);

        long milliseconds1 = calendar.getTimeInMillis();
        long milliseconds2 = calendar1.getTimeInMillis();
        long diff = milliseconds2 - milliseconds1;
        int noOfDays = (int) (diff / (24 * 60 * 60 * 1000));
        String msg2 = "Turning " + age + " in " + noOfDays + "days!!";
//        Toast.makeText(getApplicationContext(),msg2,Toast.LENGTH_LONG).show();


        String finalMsg = mss + " " + msg2;
        listItems.add(finalMsg);
        adapter.notifyDataSetChanged();
    }
}

activity_addinglist.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#8AEC9F18"
    tools:context=".addinglist">

    <NumberPicker
        android:id="@+id/day"
        android:layout_width="97dp"
        android:layout_height="131dp"
        android:background="#B5EA1241"
        android:scaleX="1.3"
        android:scaleY="1.3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.298">

    </NumberPicker>

    <NumberPicker
        android:id="@+id/month"
        android:layout_width="97dp"
        android:layout_height="131dp"
        android:layout_marginStart="60dp"
        android:layout_marginLeft="60dp"
        android:background="#B5EA1241"
        android:scaleX="1.3"
        android:scaleY="1.3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/day"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.298">

    </NumberPicker>

    <NumberPicker
        android:id="@+id/year"
        android:layout_width="97dp"
        android:layout_height="131dp"
        android:layout_marginStart="56dp"
        android:layout_marginLeft="56dp"
        android:background="#B5EA1241"
        android:scaleX="1.3"
        android:scaleY="1.3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/month"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.298">

    </NumberPicker>

    <Button
        android:id="@+id/submit"
        android:layout_width="121dp"
        android:layout_height="59dp"
        android:layout_marginBottom="156dp"
        android:background="#9A7CEF46"
        android:onClick="addingEvent"
        android:text="ADD Event"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <RadioGroup
        android:id="@+id/typer"
        android:layout_width="384dp"
        android:layout_height="88dp"
        app:layout_constraintBottom_toTopOf="@+id/submit"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.407"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/month"
        app:layout_constraintVertical_bias="0.666">

        <RadioButton
            android:id="@+id/birthday"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Birthday"
            android:textAppearance="@style/TextAppearance.AppCompat.Large" />

        <RadioButton
            android:id="@+id/anniversary"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Anniversary"
            android:textAppearance="@style/TextAppearance.AppCompat.Large" />
    </RadioGroup>

    <EditText
        android:id="@+id/name"
        android:layout_width="413dp"
        android:layout_height="53dp"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        android:hint="Enter the Name of the Person"
        app:layout_constraintBottom_toTopOf="@+id/month"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.045"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.475" />

    <EditText
        android:id="@+id/resultshower"
        android:layout_width="412dp"
        android:layout_height="95dp"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.045"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/submit"
        app:layout_constraintVertical_bias="0.518" />

</androidx.constraintlayout.widget.ConstraintLayout>

and addinglist.java


import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.NumberPicker;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Switch;

public class addinglist extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_addinglist);
        NumberPicker day = (NumberPicker) findViewById(R.id.day);
        NumberPicker month = (NumberPicker) findViewById((R.id.month));
        NumberPicker year = (NumberPicker) findViewById(R.id.year);
        day.setMinValue(1);
        day.setMaxValue(31);
        month.setMinValue(1);
        month.setMaxValue(12);
        year.setMinValue(1950);
        year.setMaxValue(2020);
    }

    public void addingEvent(View v)
    {
        String name;
        EditText nameEntered = (EditText) findViewById(R.id.name);
        name = nameEntered.getText().toString();
        NumberPicker day = (NumberPicker) findViewById(R.id.day);
        NumberPicker month = (NumberPicker) findViewById((R.id.month));
        NumberPicker year = (NumberPicker) findViewById(R.id.year);
        int day1 = day.getValue();
        int month1 = month.getValue();
        int year1 = year.getValue();
        RadioGroup typer = (RadioGroup) findViewById(R.id.typer);
        int selectedId = typer.getCheckedRadioButtonId();
        RadioButton checked = (RadioButton) findViewById(selectedId);
        String typee = checked.getText().toString();
        EditText resultbox = (EditText) findViewById(R.id.resultshower);
        String Finalmsg = name + " has his " + typee + " on " + day1 + "/" + month1 + "/" + year1;
        resultbox.setText(Finalmsg);
        Intent newintent = new Intent();
        newintent.putExtra("nameofperson",name);
        newintent.putExtra("day",day1);
        newintent.putExtra("month",month1);
        newintent.putExtra("year",year1);
        newintent.putExtra("radio",typee);
        newintent.setClass(this,MainActivity.class);
        startActivity(newintent);
    }
}

Thanks in advance for taking out time to solve this query.

Upvotes: 1

Views: 385

Answers (1)

Lakindu
Lakindu

Reputation: 950

To get a result from an activity you should use startActivityForResult() and onActivityResult() APIs instead of startActivity().

You can learn it from this simple example given by tutorialspoint : https://www.tutorialspoint.com/how-to-manage-startactivityforresult-on-android

But latest Android developer documentation recommends us to use new Activity Result APIs for this.

To learn, you can refer to the Google's documentation : https://developer.android.com/training/basics/intents/result

And this write up by Wajahat Karim : https://wajahatkarim.com/2020/05/activity-results-api-onactivityresult/

I'm trying to give you an answer using this new Activity Result API.

First, you must add AndroidX Activity and Fragment libraries as dependencies.

app/build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"

    defaultConfig {
        applicationId "com.lakindu.birthdayreminder"
        minSdkVersion 14
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    // Reference 1 : https://developer.android.com/training/basics/intents/result
    // Reference 2 : https://wajahatkarim.com/2020/05/activity-results-api-onactivityresult/
    implementation 'androidx.activity:activity:1.2.0-alpha04'
    implementation 'androidx.fragment:fragment:1.3.0-alpha04'
}

I'm going to send a Parcelable object from the addinglist activity to the MainActivity as the result.

This is the implementation of that Parcelable Event class.

Event.java

import android.os.Parcel;
import android.os.Parcelable;

public class Event implements Parcelable {

    // Name of the person
    private String nameOfPerson;

    // Day of month
    // byte (8 bit) as the type, because day can only have a value from 1 to 31
    private byte day;

    // Month of year
    // byte (8 bit) as the type, because month can only have a value from 1 to 12
    private byte month;

    // Year
    // Short (16 bit) as the type, because year can only have a realistic A.D. year
    private short year;

    // Type of event
    private String eventType;

    // Constructor (auto-generated using Android Studio)
    public Event(String nameOfPerson, byte day, byte month, short year, String eventType) {
        this.nameOfPerson = nameOfPerson;
        this.day = day;
        this.month = month;
        this.year = year;
        this.eventType = eventType;
    }

    // Getters for each private member field (auto-generated using Android Studio)

    public String getNameOfPerson() {
        return nameOfPerson;
    }

    public byte getDay() {
        return day;
    }

    public byte getMonth() {
        return month;
    }

    public short getYear() {
        return year;
    }

    public String getEventType() {
        return eventType;
    }

    // Parcelable implementation (auto-generated using Android Studio)

    protected Event(Parcel in) {
        nameOfPerson = in.readString();
        day = in.readByte();
        month = in.readByte();
        year = (short) in.readInt();
        eventType = in.readString();
    }

    public static final Creator<Event> CREATOR = new Creator<Event>() {
        @Override
        public Event createFromParcel(Parcel in) {
            return new Event(in);
        }

        @Override
        public Event[] newArray(int size) {
            return new Event[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(nameOfPerson);
        dest.writeByte(day);
        dest.writeByte(month);
        dest.writeInt((int) year);
        dest.writeString(eventType);
    }
}

Then we have to create a class to encapsulate inputs given to addinglist activity from MainActivity (in this example there's none), and outputs returned from addinglist activity to MainActivity (Event Parcelable object).

This class is an ActivityResultContract, which is like a contract we give to the Android system to open a specific Activity, and get a result from it for us.

import android.app.Activity;
import android.content.Context;
import android.content.Intent;

import androidx.activity.result.contract.ActivityResultContract;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class GetEvent extends ActivityResultContract<Void, Event> {

    @NonNull
    @Override
    public Intent createIntent(@NonNull Context context, Void input) {

        // Create Intent that should be used to start addinglist activity for result
        Intent intent = new Intent(context, addinglist.class);

        // If you need to send any inputs to addinglist activity,
        // you can put them in intent as extras.
        // Eg: intent.putExtra("input", input)
        // But for now we don't have to send any inputs to addinglist activity.

        return intent;
    }

    @Override
    public Event parseResult(int resultCode, @Nullable Intent intent) {

        // Action is cancelled? Return null
        if(Activity.RESULT_OK != resultCode) return null;

        // No intent to get output? Return null
        if(null == intent) return null;

        // Successfully got result from addinglist activity
        return intent.getExtras().getParcelable("output");
    }
}

Here is how we launch the addinglist activity from MainActivity and get the result.

MainActivity.java

import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import androidx.activity.ComponentActivity;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;

import java.util.ArrayList;
import java.util.Calendar;

public class MainActivity extends ComponentActivity {

    private static final String TAG = "";

    ArrayList<String> listItems = new ArrayList<String>();

    ArrayAdapter<String> adapter;

    Calendar calendar = Calendar.getInstance();
    int thisYear = calendar.get(Calendar.YEAR);
    int thisMonth = calendar.get(Calendar.MONTH) + 1;
    int thisDay = calendar.get(Calendar.DAY_OF_MONTH);

    // Holds the latest event received from addinglist activity
    private Event mLatestEvent = null;

    // Register a callback to be called on an event received from addinglist activity
    private ActivityResultLauncher<Void> mGetEvent = registerForActivityResult(
            // Instance that encapsulates input and output when starting addinglist activity for result
            new GetEvent(),

            // Callback to be called when event is received
            new ActivityResultCallback<Event>() {
                @Override
                public void onActivityResult(Event result) {
                    // Save as latest event received
                    mLatestEvent = result;
                }
            }
    );

    private static final Void NO_INPUT = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        adapter=new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1,
                listItems);
        ListView records = (ListView) findViewById(R.id.list);
        records.setAdapter(adapter);
    }

    public void addNewEntry(View v)
    {
        // Launch addinglist activity to get an event
        mGetEvent.launch(NO_INPUT);
    }
    public void viewRecord(View v)
    {
        // No latest event? Then nothing to add to list, just return.
        if(null == mLatestEvent) return;

        // Prepare string that is being added to the list.
        // Using a StringBuilder as there are multiple number of immutable strings to be appended.
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(mLatestEvent.getNameOfPerson())
                .append(" has his ")
                .append(mLatestEvent.getEventType())
                .append(" on ")
                .append(mLatestEvent.getDay())
                .append("/")
                .append(mLatestEvent.getMonth())
                .append("/")
                .append(mLatestEvent.getYear());

        String mss = stringBuilder.toString();
        //Toast.makeText(getApplicationContext(),mss,Toast.LENGTH_LONG).show();

        int age = thisYear - mLatestEvent.getYear();
        calendar.set(thisYear,thisMonth,thisDay);
        Calendar calendar1 = Calendar.getInstance();
        calendar1.set(thisYear, mLatestEvent.getMonth(), mLatestEvent.getDay());

        long milliseconds1 = calendar.getTimeInMillis();
        long milliseconds2 = calendar1.getTimeInMillis();
        long diff = milliseconds2 - milliseconds1;
        int noOfDays = (int) (diff / (24 * 60 * 60 * 1000));
        String msg2 = "Turning " + age + " in " + noOfDays + "days!!";
//        Toast.makeText(getApplicationContext(),msg2,Toast.LENGTH_LONG).show();


        String finalMsg = mss + " " + msg2;
        listItems.add(finalMsg);
        adapter.notifyDataSetChanged();
    }
}

Note that MainActivity is a ComponentActivity now. Not a AppCompatActivity.

Here is how to send the result from addinglist activity to MainActivity.

addinglist.java

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.NumberPicker;
import android.widget.RadioButton;
import android.widget.RadioGroup;

import androidx.appcompat.app.AppCompatActivity;

public class addinglist extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_addinglist);
        NumberPicker day = (NumberPicker) findViewById(R.id.day);
        NumberPicker month = (NumberPicker) findViewById((R.id.month));
        NumberPicker year = (NumberPicker) findViewById(R.id.year);
        day.setMinValue(1);
        day.setMaxValue(31);
        month.setMinValue(1);
        month.setMaxValue(12);
        year.setMinValue(1950);
        year.setMaxValue(2020);
    }

    public void addingEvent(View v)
    {
        String name;
        EditText nameEntered = (EditText) findViewById(R.id.name);
        name = nameEntered.getText().toString();
        NumberPicker day = (NumberPicker) findViewById(R.id.day);
        NumberPicker month = (NumberPicker) findViewById((R.id.month));
        NumberPicker year = (NumberPicker) findViewById(R.id.year);
        byte day1 = (byte) day.getValue();
        byte month1 = (byte) month.getValue();
        short year1 = (short) year.getValue();
        RadioGroup typer = (RadioGroup) findViewById(R.id.typer);
        int selectedId = typer.getCheckedRadioButtonId();
        RadioButton checked = (RadioButton) findViewById(selectedId);
        String typee = checked.getText().toString();
        EditText resultbox = (EditText) findViewById(R.id.resultshower);
        String Finalmsg = name + " has his " + typee + " on " + day1 + "/" + month1 + "/" + year1;
        resultbox.setText(Finalmsg);

        // Prepare the result to output
        Intent newintent = new Intent();
        newintent.putExtra(
                "output",
                new Event(name, day1, month1, year1, typee)
        );

        // Set the result
        setResult(Activity.RESULT_OK, newintent);

        // Finish the addinglist activity.
        // Then result will be sent to the MainActivity.
        finish();
    }
}

Here is the working app.

enter image description here enter image description here

Upvotes: 1

Related Questions