Lesson Weekend

At the moment we are gathering the user's input and printing it to the log in our MainActivity. However, our goal is to eventually use this information to complete an API request in our RestaurantsActivity. But how do we send data to another activity?

Passing Data with Intent Extras

Data can be passed to our RestaurantsActivity along with our Intent in the form of ‘extras’. We attach data to an Intent as a key value pair, using a method called putExtra(), like so:

intent.putExtra("String key", "value");

Let's do this for the location string value we created in our onClick() method in the previous lesson. (We can also remove the line to print our location to the logcat at this time). Our code should look as follows:

MainActivity.java
package com.epicodus.myrestaurants;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {
    private Button mFindRestaurantsButton;
    private EditText mLocationEditText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mLocationEditText = (EditText) findViewById(R.id.locationEditText);
        mFindRestaurantsButton = (Button) findViewById(R.id.findRestaurantsButton);

        mFindRestaurantsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String location = mLocationEditText.getText().toString();
                Intent intent = new Intent(MainActivity.this, RestaurantsActivity.class);
                intent.putExtra("location", location);
                startActivity(intent);
            }
        });
    }
}

Gathering Data from Intent Extras

Now, when we click our mFindRestaurantsButton, an Intent to take us from our MainActivity to our RestaurantsActivity should be initiated. This Intent will now include an extra key-value pair of data containing the value the user placed in our EditText form field.

Now, let’s pull the data out of the intent extra in our RestaurantsActivity. To do this, we will use the getIntent() method to recreate the Intent and the getStringExtra() method to pull out the location value based using the string key we provided:

RestaurantsActivity.java
package com.epicodus.myrestaurants;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class RestaurantsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_restaurants);
        Intent intent = getIntent();
        String location = intent.getStringExtra("location");
    }
}

However, we aren't displaying the location data anywhere, so we can't see if this is working! Let's change this: To test that we can successfully retrieve data from the intent extra, we'll first add a TextView to our activity_restaurants.xml layout that will be responsible for displaying this information:

res/layout/activity_restaurants.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.epicodus.myrestaurants.RestaurantsActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Restaurants near "
        android:id="@+id/locationTextView"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

Here, we've added a TextView, set its height and width to wrap_content, which will allow the TextView to simply expand to whatever size its inner content requires, added the filler text "Restaurants near", assigned it the ID locationTextView to reference later in our Java logic, and centered it within the layout. We've also removed the layout's default 16dp padding.

Then, back in our RestaurantsActivity, we'll declare mLocationTextView at the top of the file, define it in the onCreate() method, then update its content to display the location:

RestaurantsActivity.java
package com.epicodus.myrestaurants;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class RestaurantsActivity extends AppCompatActivity {
    private TextView mLocationTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_restaurants);
        mLocationTextView = (TextView) findViewById(R.id.locationTextView);
        Intent intent = getIntent();
        String location = intent.getStringExtra("location");
        mLocationTextView.setText("Here are all the restaurants near: " + location);
    }
}

Here, we call the setText() method on mLocationTextView to update its text to contain the sentence we include, and the location string we previously defined.

Let’s run our app and make sure that our message displays as expected. Great work!


Example GitHub Repo for MyRestaurants

Terminology


  • Intent Extra: Additional data attached to an Intent, in the form of a key-value pair. This data is assigned to the Intent and retrieved using the methods described below.

Methods


  • putExtra(): Is called upon an Intent, adds additional information to the intent in the form of a key-value pair. Takes two arguments: One representing the key, and the other representing the value corresponding to that key.

  • getStringExtra(): Called upon an Intent that has additional data attached to it. If provided an argument representing the string key in the key-value pair described above, it will return the value.

  • setText(): Similar to getText(), can be called upon any TextView object to set the text within it equal to the argument provided to the method.

Examples


MainActivity.java
mFindRestaurantsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String location = mLocationEditText.getText().toString();
                Intent intent = new Intent(MainActivity.this, RestaurantsActivity.class);
                intent.putExtra("location", location);
                startActivity(intent);
            }
        });

In the code above...

  • A string location is defined by getting the text a user has input into an EditText field, and transforming it into a string.

  • An Intent to travel from the MainActivity to the RestaurantsActivity is created.

  • Then, intent.putExtra("location", location); attacheslocationto the newly-createdIntentin the form of an intent extra."location"is the key of the key-value pair, and thelocation` variable is the value.

res/layout/activity_restaurants.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.epicodus.myrestaurants.RestaurantsActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Restaurants near "
        android:id="@+id/locationTextView"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

</RelativeLayout>
RestaurantsActivity.java
public class RestaurantsActivity extends AppCompatActivity {
    public static final String TAG = RestaurantsActivity.class.getSimpleName();
    private TextView mLocationTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_restaurants);

        mLocationTextView = (TextView) findViewById(R.id.locationTextView);

        Intent intent = getIntent();
        String location = intent.getStringExtra("location");
        mLocationTextView.setText("Here are all the restaurants near: " + location);
    }
}

When the Intent defined in the MainActivity takes the user from the MainActivity to the RestaurantsActivity, the code above is executed.

  • The line Intent intent = getIntent(); recreates the Intent that has just taken us to this new activity.

  • mLocationTextView = (TextView) findViewById(R.id.locationTextView); Locates a TextView in the RestaurantActivity's corresponding XML layout.

  • The line String location = intent.getStringExtra("location"); uses the key "location" to retrieve the variable location attached to this intent in the form of an intent extra.

  • This location is then displayed in the mLocationTextView previously located on the current layout, when mLocationTextView.setText("Here are all the restaurants near: " + location); is called.

Example GitHub Repo for MyRestaurants