Monday, December 21, 2015

Passing data between Android activities

Passing data between activities in Android is extremely common, and therefore a very basic thing to learn.
In this entry I will explain how to pass data forward (so from a first activity to a second activity), and backwards (from the second activity back to the first activity).

The Final Product

So this is what the app is going to do, and how it will behave.


Super simple!

The workflow

Before we start coding let me explain to you and how this is going to work.

  • In the Initial activity we will get the element we're going to pass around. In this example this will be a regular String
  • We will be passing this as an Intent extra, therefore we will need a key to use in both activities (this is a key-value pair)
  • When the initial activity gets ready to start the second activity, the initial activity will know that it will be getting something back (a "result"), so the Initial activity will start the Second activity expecting a result, and passing a result code (a "request code")
  • When the Second activity ends, it will end with a result code and an Intent. The Intent will have an extra again, once again using a key (this is usually called a "bundle code")
  • Finally, when the Initial activity comes back from the Second activity, we will be checking the result for a request code, and we will get the data from the Intent that comes from this result.
If this doesn't make sense, the rest of the tutorial should clear it up for you.

Passing data forward (from First to Second activities)

In the first activity we will ask the user for some data (in this case a String of text), which will be passed to the second activity once the user pushes a button in the first activity.

The key here is that instead of starting the Second activity with the regular startActivity(Intent intent) method, we will instead use startActivityForResult(Intent intent, int requestCode).

The code for the entire FirstActivity class will look like this:
public class FirstActivity extends AppCompatActivity
{
    private TextView tvName;
    private TextView tvNumber;
    private EditText etName;
    private Button button;

    public static final String KEY_SENDING_DATA = "sending_data";
    private int REQUEST_CODE = 9;

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

        tvName = (TextView)findViewById(R.id.tv_name);
        tvNumber = (TextView)findViewById(R.id.tv_number);
        etName = (EditText)findViewById(R.id.et_name);
        button = (Button)findViewById(R.id.button_first_activity);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                intent.putExtra(KEY_SENDING_DATA, etName.getText().toString());
                startActivityForResult(intent, REQUEST_CODE);
            }
        });

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == REQUEST_CODE && resultCode == RESULT_OK)
        {
            // get data from second activity
            String numberReceived = data.getStringExtra(SecondActivity.BUNDLE_NUMBER);

            tvNumber.setText("The number from second activity is: " + numberReceived);
            tvNumber.setVisibility(View.VISIBLE);
        }
    }
}

Things to notice in here:
  1. The variable KEY_SENDING_DATA is a public static variable. The reason for this is because we want to use this same variable in the Second class so we only have to worry about 1 key variable.
  2. When the button is pushed we will be calling startActivityForResult()
  3. We will be overriding the method onActivityResult(int requestCode, int resultCode, Intent data)
  4. In onActivityResult() we will be checking if the requestCode matches what will be coming from the Second activity, and if the resultCode is RESULT_OK
  5. And finally, in the onActivityResult(), if we're in the correct requestCode and resultCode, then we will get the data coming from the Second activity, using another static variable which has been declared in the Second activity.
With all of this done, the FirstActivity is now passing data to the SecondActivity class, and it is ready to receive data coming from any class (in this case the SecondActivity but it could be anyone that has a valid requestCode)

Passing data backwards (from Second to First activities)

So now that we got data sent from the FirstActivity to the SecondActivity, we need to finish the job by passing data back from the SecondActivity to the FirstActivity. Since we used a String in the FirstActivity, we will pass an int now from the SecondActivity back to the FirstActivity.

And since the code in the SecondActivity is even shorter than in the FirstActivity, I will again copy the entire code of this class:
public class SecondActivity extends AppCompatActivity
{
    private TextView tvName;
    private TextView tvNumber;
    private EditText etNumber;
    private Button button;

    public static final String BUNDLE_NUMBER = "number";

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

        tvName = (TextView)findViewById(R.id.tv_name_second);
        tvNumber = (TextView)findViewById(R.id.tv_number_second);
        etNumber = (EditText)findViewById(R.id.et_number_second);
        button = (Button)findViewById(R.id.button_second_activity);

        // get data from first activity
        Intent intent = getIntent();
        String nameReceived = intent.getStringExtra(FirstActivity.KEY_SENDING_DATA);

        // display the name received
        tvName.setText("Your name is: " + nameReceived);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent result = new Intent();
                result.putExtra(BUNDLE_NUMBER, etNumber.getText().toString());
                setResult(RESULT_OK, result);
                finish();
            }
        });
    }
}

Again, things to notice in here:
  1. We will be getting the data from the FirstActivity using the getIntent().getStringExtra(key), using as key the static String we created in the FirstActivity
  2. When the button gets pushed in this Second activity, we will be creating a new Intent (without any parameters), and put an extra in the Intent, using a new static variable.
  3. And finally, before we finish the activity we invoke the method setResult(int resultCode, Intent data) to pass the result code of RESULT_OK and the newly created Intent we arbitrarily called result

And there you have it. Now you can be passing data back and forth all day long!

Note: this tutorial uses simple data types like String and int to be passed around. If you want to pass custom objects around you may need to make sure first your object implements Serializable or Parcelable.

As usual, here's the link to the code used in this tutorial.
Eduardo

No comments:

Post a Comment