BÀI 5: ACTIVITIES VÀ INTENTS – Lập trình Android

1. Chào mừng

Giới thiệu

Một Activity đại diện cho một màn hình duy nhất trong ứng dụng của bạn mà người dùng có thể thực hiện một tác vụ tập trung duy nhất, chẳng hạn như chụp ảnh, gửi email hoặc xem bản đồ. Một hoạt động thường được hiển thị cho người dùng dưới dạng cửa sổ toàn màn hình.

Một ứng dụng thường bao gồm nhiều màn hình được liên kết với nhau. Mỗi màn hình là một hoạt động. Thông thường, một hoạt động trong ứng dụng được chỉ định là hoạt động “chính” (MainActivity.java), được hiển thị cho người dùng khi ứng dụng được khởi chạy. Hoạt động chính sau đó có thể bắt đầu các hoạt động khác để thực hiện các hành động khác nhau.

Mỗi khi một hoạt động mới bắt đầu, hoạt động trước đó sẽ bị dừng lại, nhưng hệ thống bảo lưu hoạt động đó trong một ngăn xếp (“stack”). Khi một hoạt động mới bắt đầu, hoạt động mới đó sẽ được đẩy lên đỉnh của ngăn xếp. Ngăn xếp tuân theo logic ngăn xếp cơ bản “vào sau, ra trước”. Khi người dùng thực hiện xong hoạt động hiện tại và nhấn nút Back, hoạt động đó sẽ bị hủy, và hoạt động trước đó sẽ tiếp tục.

Một hoạt động được bắt đầu hoặc được kích hoạt với một ý định (intent). Một Intent là một thông báo không đồng bộ mà bạn có thể sử dụng trong hoạt động của mình để yêu cầu một hành động từ một hoạt động khác hoặc từ một số thành phần ứng dụng khác. Bạn sử dụng một ý định để bắt đầu một hoạt động từ một hoạt động khác và chuyển dữ liệu giữa các hoạt động.

Một Intent có thể rõ ràng hoặc ngầm:

  • Một ý định rõ ràng là một ý định trong đó bạn biết được mục tiêu của nó. Có nghĩa là, bạn đã biết tên lớp đủ điều kiện của hoạt động cụ thể đó.
  • Một ý định ngầm là một ý định trong đó bạn không có tên của các thành phần mục tiêu, nhưng bạn có một hành động chung để thực hiện.

Trong thực tế này, bạn tạo ra ý định rõ ràng. Bạn tìm hiểu cách sử dụng ý định ngầm trong một thực tế sau này.

Những gì bạn nên biết

  • Tạo và chạy ứng dụng trong Android Studio.
  • Sử dụng trình chỉnh sửa bố cục để tạo bố cục trong ConstraintLayout.
  • Chỉnh sửa mã bố cục XML.
  • Thêm chức năng onClick vào một Button.

Những gì bạn sẽ học

  • Cách tạo mới Activity trong Android Studio.
  • Làm thế nào để bắt đầu một Activity với một Intent rõ ràng.
  • Làm thế nào để chuyển dữ liệu giữa các Activity với một Intent rõ ràng.

Bạn sẽ làm gì

  • Tạo một ứng dụng Android mới với một Activity chính và một Activity thứ hai.
  • Chuyển một số dữ liệu (một chuỗi) từ Activity chính sang Activity thứ hai bằng cách sử dụng Intent và hiển thị dữ liệu đó trong Activity thứ hai.
  • Gửi một số dữ liệu khác từ Activity thứ hai trở lại Activity chính, cũng bằng cách sử dụng Intent.

2. Tổng quan về ứng dụng

Trong bài này, bạn tạo và xây dựng một ứng dụng có tên là Two Activities. Bạn xây dựng ứng dụng trong ba giai đoạn.

Trong giai đoạn đầu tiên, bạn tạo một ứng dụng có hoạt động chính chứa một nút là Send. Khi người dùng nhấp vào nút này, hoạt động chính của bạn sử dụng một ý định để bắt đầu hoạt động thứ hai.

Trong giai đoạn thứ hai, bạn thêm một EditText vào hoạt động chính. Người dùng nhập tin nhắn và nhấp vào Send. Hoạt động chính sử dụng một ý định để bắt đầu hoạt động thứ hai và gửi thông điệp của người dùng đến hoạt động thứ hai. Hoạt động thứ hai hiển thị thông báo mà nó nhận được.

Trong giai đoạn cuối cùng của việc tạo ra ứng dụng Two Activities, bạn thêm một EditText và nút Reply vào hoạt động thứ hai. Giờ đây, người dùng có thể nhập tin nhắn trả lời và chạm vào Reply, và câu trả lời được hiển thị trên hoạt động chính. Tại thời điểm này, bạn sử dụng một ý định để chuyển trả lời từ hoạt động thứ hai trở lại hoạt động chính.

3. Tạo dự án TwoActivities

Trong tác vụ này, bạn thiết lập dự án ban đầu với một Activity chính, xác định bố cục và xác định phương thức cho sự kiện onClick.

3.1 Tạo dự án TwoActivities

Bước 1: Khởi động Android Studio và tạo một dự án Android Studio mới.

Bước 2: Chọn cài đặt là Phone and Tablet và chọn Empty Activity cho Activity mẫu. Nhấp vào Next.

Bước 3: Nhập các thông cho bước tiếp theo như sau:

Thuộc tínhGiá trịNameTwo ActivitiesPackageandroid.example.com (hoặc miền của riêng bạn)Save locationChọn nơi lưuLanguageJavaMinimum SDKAPI 21: Android 5.0 (Lollipop)

Bước 4: Nhấp vào Finish.

3.2 Xác định bố cục cho main Activity

Bước 1: Mở res/layout/activity_main.xml trong ngăn Project/Android. Trình chỉnh sửa bố cục xuất hiện.

Bước 2: Nhấp vào tab Design nếu nó chưa được chọn và xóa TextView (TextView có nội dung “Hello World”) trong ngăn Component Tree.

Bước 3: Khi đã bật Autoconnect (cài đặt mặc định), hãy kéo một Button từ ngăn Palette đến góc dưới bên phải của bố cục. Autoconnect tạo ra các ràng buộc cho Button.

Bước 4: Trong ngăn Attributes, đặt ID thành button_mainlayout_width và layout_height thành wrap_content và nhập Send cho trường Text. Bố cục bây giờ sẽ trông như thế này:

Bước 5: Bấm vào tab Code để chỉnh sửa mã XML. Thêm thuộc tính sau vào Button:

android:onClick="launchSecondActivity"

Giá trị thuộc tính được gạch chân màu đỏ vì phương thức launchSecondActivity() chưa được tạo. Bỏ qua lỗi này, bạn sửa nó trong nhiệm vụ tiếp theo.

Bước 6: Trích xuất tài nguyên chuỗi, như được mô tả trong thực tế trước, sử dụng tên button_main cho “Send”.

Mã XML cho Button này sẽ giống như sau:

<Button
    android:id="@+id/button_main"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="16dp"
    android:layout_marginBottom="16dp"
    android:onClick="launchSecondActivity"
    android:text="@string/button_main"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent" />

3.3 Xác định hành động của Button

Trong tác vụ này, bạn triển khai phương thức launchSecondActivity() mà bạn đã đề cập đến trong bố cục cho thuộc tính android:onClick.

Bước 1: Nhấp vào “launchSecondActivity” trong mã XML activity_main.xml.

Bước 2: Nhấn Alt+Enter  và chọn Create ‘launchSecondActivity(View)’ trong MainActivity.

Tập tin MainActivity.java mở ra, và Android Studio tạo ra một phương thức cho launchSecondActivity().

Bước 3: Bên trong launchSecondActivity(), thêm một Log có nội dung “Button Clicked!”

Log.d(LOG_TAG, "Button clicked!");

LOG_TAG sẽ hiển thị màu đỏ. Bạn thêm định nghĩa cho biến đó trong bước sau.

Bước 4: Ở đầu lớp MainActivity, thêm một hằng số cho biến LOG_TAG:

private static final String LOG_TAG = MainActivity.class.getSimpleName();

Hằng số này sử dụng tên của chính lớp làm thẻ.

Bước 5: Chạy ứng dụng của bạn. Khi bạn nhấp vào nút Send, bạn sẽ thấy thông báo “Button Clicked!” trong ngăn Logcat. Nếu có quá nhiều kết quả trong màn hình, hãy nhập MainActivity vào hộp tìm kiếm và ngăn Logcat sẽ chỉ hiển thị các dòng khớp với thẻ đó.

Mã cho MainActivity sẽ trông như sau:

package com.tmtdeveloper.twoactivities;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class MainActivity extends AppCompatActivity {
    private static final String LOG_TAG = MainActivity.class.getSimpleName();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public void launchSecondActivity(View view) {
        Log.d(LOG_TAG, "Button clicked!");
    }
}

4. Tạo và khởi chạy Activity thứ hai

Mỗi hoạt động mới bạn thêm vào dự án của mình có tệp bố cục và Java riêng, tách biệt với các tệp của hoạt động chính. Nó cũng có phần tử <activity> riêng của nó trong tệp AndroidManifest.xml. Giống như hoạt động chính, các triển khai hoạt động mới mà bạn tạo trong Android Studio cũng mở rộng từ lớp AppCompatActivity.

Bạn có thể xác định một hoạt động làm hoạt động gốc của một hoạt động khác trong tệp AndroidManifest.xml. Mối quan hệ cha-con này cho phép Android thêm các gợi ý điều hướng, chẳng hạn như mũi tên hướng sang trái trên thanh tiêu đề cho mỗi hoạt động.

Một hoạt động giao tiếp với các hoạt động khác (trong cùng một ứng dụng và trên các ứng dụng khác nhau) với một ý định (intent). Một Intent có thể rõ ràng hoặc ngầm:

  • Một ý định rõ ràng là một ý định trong đó bạn biết được mục tiêu của nó, nghĩa là bạn đã biết tên lớp thoả điều kiện của hoạt động cụ thể đó.
  • Một ý định ngầm là một ý định trong đó bạn không có tên của các thành phần mục tiêu, nhưng có một hành động chung để thực hiện.

Trong tác vụ này, bạn thêm hoạt động thứ hai vào ứng dụng, với bố cục riêng của nó. Bạn sửa đổi tệp AndroidManifest.xml để xác định hoạt động làm hoạt động chính. Sau đó, bạn sửa đổi phương thức launchSecondActivity() trong MainActivity để bao gồm một ý định khởi chạy hoạt động thứ hai khi bạn nhấp vào nút.

4.1 Tạo Activity thứ hai

Bước 1: Nhấp chuột phải vào thư mục app trong dự án của bạn và chọn New/Activity/Empty Activity.

Bước 2: Đặt tên cho Activity mới là SecondActivity. Đảm bảo rằng Generate a Layout File được chọn. Tên bố cục được điền dưới dạng activity_second. Không check vào tuỳ chọn Launcher Activity.

Bước 3: Nhấp vào Finish. Android Studio thêm cả bố cục Activity mới (activity_second.xml) và tệp Java mới (SecondActivity.java) vào Activity mới của bạn. Nó cũng cập nhật tệp AndroidManifest.xml để bao gồm Activity mới.

4.2 Sửa đổi tệp AndroidManifest.xml

Bước 1: Mở mục mainfests/AndroidManifest.xml.

Bước 2: Tìm phần tử <activity> mà Android Studio đã tạo cho Activity thứ hai.

<activity
    android:name=".SecondActivity"
    android:exported="false" />

Bước 3: Thay thế toàn bộ phần tử <activity> bằng phần tử sau:

<activity
    android:name=".SecondActivity"
    android:label = " Second Activity"
    android:parentActivityName=".MainActivity"/>

Thuộc tính label bổ sung thêm tiêu đề của Activity trên thanh ứng dụng.

Với thuộc tính parentActivityName, bạn chỉ ra rằng hoạt động chính là cha của hoạt động thứ hai. Mối quan hệ này được sử dụng cho điều hướng lên (Up navigation) trong ứng dụng của bạn: thanh ứng dụng cho hoạt động thứ hai sẽ có mũi tên hướng sang trái để người dùng có thể điều hướng “lên trên” đến hoạt động chính.

Bước 4: Trích xuất tài nguyên chuỗi cho “Second Activity” trong đoạn mã trên và sử dụng activity2_name làm tên tài nguyên.

4.3 Xác định bố cục cho Activity thứ hai

Bước 1: Mở activity_second.xml và nhấp vào tab Design nếu nó chưa được chọn.

Bước 2: Kéo một TextView từ ngăn Palette đến góc trên cùng bên trái của bố cục và thêm các ràng buộc vào phía trên và bên trái của bố cục. Đặt các thuộc tính của nó trong ngăn Attributes như sau:

Thuộc tínhGiá trịidtext_headerlayout_marginTop16layout_marginStart8layout_widthwrap_contentlayout_heightwrap_contenttextMessage ReceivedtextAppearance@style/TextAppearance.AppCompat.MediumtextStyleB (Bold)

Giá trị của textAppearance là một thuộc tính chủ đề Android đặc biệt, xác định các kiểu phông chữ cơ bản. Bạn tìm hiểu thêm về các chủ đề trong một bài học sau.

Bố cục bây giờ sẽ trông như thế này:

Bước 3: Nhấp vào tab Text để chỉnh sửa mã XML và trích xuất chuỗi “Message Received” vào một tài nguyên có tên text_header.

Mã XML cho activity_second.xml phải như sau:

<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"
    tools:context=".SecondActivity">
    <TextView
        android:id="@+id/text_header"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:text="@string/text_header"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

4.4 Thêm một Intent vào Activity chính

Trong nhiệm vụ này, bạn thêm một Intent rõ ràng vào Activity chính. Intent này được sử dụng để kích hoạt Activity thứ hai khi nút Send được nhấp vào.

Bước 1: Mở MainActivity.

Bước 2: Tạo mới Intent trong phương thức launchSecondActivity().

Hàm tạo Intent nhận hai đối số cho một Intent rõ ràng: một ứng dụng Context và thành phần cụ thể sẽ nhận Intent đó. Ở đây bạn nên sử dụng this như là Context, và SecondActivity.class như các lớp cụ thể:

Intent intent = new Intent(this, SecondActivity.class);

Bước 3: Gọi phương thức startActivity() với đối số là new Intent.

startActivity(intent);

Bước 4: Chạy ứng dụng.

Khi bạn nhấp vào nút SendMainActivity gửi Intent và hệ thống Android sẽ khởi chạy SecondActivity xuất hiện trên màn hình. Để quay lại MainActivity, hãy nhấp vào nút Up (mũi tên bên trái trên thanh ứng dụng) hoặc nút Quay lại ở cuối màn hình.

5. Gửi dữ liệu từ Activity chính sang Activity thứ hai

Trong nhiệm vụ cuối cùng, bạn đã thêm một ý định rõ ràng vào MainActivity để khởi chạy SecondActivity. Bạn cũng có thể sử dụng một ý định để gửi dữ liệu từ hoạt động này sang hoạt động khác trong khi khởi chạy nó.

Đối tượng mục đích của bạn có thể chuyển dữ liệu đến hoạt động mục tiêu theo hai cách: trong trường dữ liệu hoặc trong phần bổ sung ý định. Dữ liệu ý định là một URI cho biết dữ liệu cụ thể sẽ được thực hiện. Nếu thông tin bạn muốn chuyển cho một hoạt động thông qua một mục đích không phải là URI hoặc bạn có nhiều thông tin muốn gửi, bạn có thể đưa thông tin bổ sung đó vào phần bổ sung.

Ý định bổ sung là các cặp khóa/giá trị (key/value) trong một Bundle. Một Bundle là một tập hợp dữ liệu, được lưu trữ dưới dạng các cặp khóa/giá trị. Để chuyển thông tin từ hoạt động này sang hoạt động khác, bạn đặt các khóa và giá trị Bundle vào mục đích bổ sung từ hoạt động gửi và sau đó đưa chúng trở lại hoạt động nhận.

Trong tác vụ này, bạn sửa đổi ý định rõ ràng MainActivity để bao gồm dữ liệu bổ sung (trong trường hợp này là chuỗi do người dùng nhập) trong ý định bổ sung Bundle. Sau đó, bạn sửa đổi SecondActivity để lấy lại dữ liệu đó ra khỏi mục đích bổ sung Bundle và hiển thị nó trên màn hình.

5.1 Thêm một EditText vào bố cục MainActivity

Bước 1: Mở activity_main.xml.

Bước 2: Kéo phần tử Plain Text (Text) từ ngăn Palette xuống cuối bố cục và thêm các ràng buộc vào bên trái của bố cục, cuối bố cục và bên trái của Button Send. Đặt các thuộc tính của nó trong ngăn Attributes như sau:

Thuộc tínhGiá trịideditText_mainlayout_marginEnd8layout_marginStart8layout_marginBottom16layout_widthmatch_constraintlayout_heightwrap_contentinputTypetextLongMessagehintEnter Your Message Heretext(Xóa bất kỳ văn bản nào trong trường này)

Bố cục mới trong activity_main.xml trông như thế này:

Bước 3: Nhấp vào tab Code để chỉnh sửa mã XML và trích xuất chuỗi “Enter Your Message Here” thành một tài nguyên có tên editText_main.

Mã XML cho bố cục sẽ trông giống như sau.

<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"
    tools:context=".MainActivity">
    <Button
        android:id="@+id/button_main"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginBottom="16dp"
        android:onClick="launchSecondActivity"
        android:text="@string/button_main"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
    <EditText
        android:id="@+id/editText_main"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="16dp"
        android:ems="10"
        android:hint="@string/editText_main"
        android:inputType="textLongMessage|text"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/button_main"
        app:layout_constraintStart_toStartOf="parent"
        tools:ignore="TouchTargetSizeCheck" />
</androidx.constraintlayout.widget.ConstraintLayout>

5.2 Thêm một chuỗi vào phần Intent bổ sung

Intent bổ sung là các cặp khóa/giá trị trong một Bundle. Một Bundle là một tập hợp dữ liệu, được lưu trữ dưới dạng các cặp khóa/giá trị. Để chuyển thông tin từ Activity này sang Activity khác, bạn đặt các khóa và giá trị Bundle vào Intent bổ sung từ quá trình gửi Activity, sau đó lấy lại chúng trong lần nhận Activity.

Bước 1: Mở MainActivity.

Bước 2: Thêm một hằng số public ở đầu lớp để xác định khóa cho Intent bổ sung:

public static final String EXTRA_MESSAGE =
 "com.tmtdeveloper.twoactivities.extra.MESSAGE";

Bước 3: Thêm một biến private ở đầu lớp để giữ EditText:

private EditText mMessageEditText;

Bước 4: Trong phương thức onCreate(), sử dụng findViewById() để nhận tham chiếu đến EditText và gán nó cho biến private đó:

mMessageEditText = findViewById(R.id.editText_main);

Bước 5: Trong phương thức launchSecondActivity(), ngay dưới new Intent, lấy văn bản từ EditText dưới dạng chuỗi:

String message = mMessageEditText.getText().toString();

Bước 6: Thêm chuỗi đó vào phần Intent bổ sung với hằng số EXTRA_MESSAGE làm khóa và chuỗi dưới dạng giá trị:

intent.putExtra(EXTRA_MESSAGE, message);

Phương thức onCreate() trong MainActivity bây giờ sẽ trông như sau:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mMessageEditText = findViewById(R.id.editText_main);
}

Phương thức launchSecondActivity() trong MainActivity bây giờ sẽ trông như sau:

public void launchSecondActivity(View view) {
    Log.d(LOG_TAG, "Button clicked!");
    Intent intent = new Intent(this, SecondActivity.class);
    String message = mMessageEditText.getText().toString();
    intent.putExtra(EXTRA_MESSAGE,message);
    startActivity(intent);
}

5.3 Thêm TextView vào SecondActivity cho tin nhắn

Bước 1: Mở activity_second.xml.

Bước 2: Kéo một TextView khác vào bố cục bên dưới TextView text_header và thêm các ràng buộc vào bên trái của bố cục và vào cuối text_header.

Bước 3: Đặt các thuộc tính TextView mới trong ngăn Attributes như sau:

Thuộc tínhGiá trịidtext_messagelayout_marginTop8layout_marginStart8layout_widthwrap_contentlayout_heightwrap_contenttext(Xóa bất kỳ văn bản nào trong trường này)textAppearance@style/TextAppearance.AppCompat.Medium

Bố cục mới trông giống như trong tác vụ trước đó, vì TextView mới không (chưa) chứa bất kỳ văn bản nào và do đó không xuất hiện trên màn hình.

Mã XML cho bố cục activity_second.xml sẽ trông giống như sau:

<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"
    tools:context=".SecondActivity">
    <TextView
        android:id="@+id/text_header"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:text="@string/text_header"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/text_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/text_header" />
</androidx.constraintlayout.widget.ConstraintLayout>

5.4 Sửa đổi SecondActivity để nhận các tính năng bổ sung và hiển thị tin nhắn

Bước 1: Mở SecondActivity để thêm mã vào phương thức onCreate().

Bước 2: Nhận Intent kích hoạt Activity:

Intent intent = getIntent();

Bước 3: Lấy chuỗi chứa thông báo từ Intent bổ sung bằng cách sử dụng biến tĩnh MainActivity.EXTRA_MESSAGE làm khóa:

String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);

Bước 4: Sử dụng findViewByID() để tham chiếu đến thông báo TextView từ bố cục:

TextView textView = findViewById(R.id.text_message);

Bước 5: Đặt văn bản của chuỗi TextView thành chuỗi từ Intent bổ sung:

textView.setText(message);

Bước 6: Chạy ứng dụng. Khi bạn nhập tin nhắn vào MainActivity và nhấp vào SendSecondActivity sẽ khởi chạy và hiển thị tin nhắn.

Phương thức onCreate() trong SecondActivity như sau:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);
    Intent intent = getIntent();
    String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
    TextView textView = findViewById(R.id.text_message);
    textView.setText(message);
}

6. Trả dữ liệu trở lại Activity chính

Bây giờ bạn có một ứng dụng khởi chạy một hoạt động mới và gửi dữ liệu cho nó, bước cuối cùng là đưa dữ liệu từ hoạt động thứ hai trở lại hoạt động chính. Bạn cũng sử dụng một ý định và ý định bổ sung cho nhiệm vụ này.

6.1 Thêm một EditText và một Button vào bố cục SecondActivity

Bước 1: Mở string.xml và thêm tài nguyên chuỗi cho văn bản của Button và văn bản gợi ý cho EditText bạn sẽ thêm vào SecondActivity:

<string name="button_second">Reply</string>
<string name="editText_second">Enter Your Reply Here</string>

Bước 2: Mở activity_main.xml và activity_second.xml.

Bước 3: Sao chép EditText và Button từ tệp tin bố cục activity_main.xml và Paste chúng vào bố cục activity_second.xml.

Bước 4: Trong activity_second.xml, sửa đổi các giá trị thuộc tính cho Button như sau:

Giá trị thuộc tính cũGiá trị thuộc tính mớiandroid:id=”@+id/button_main”android:id=”@+id/button_second”android:onClick=”launchSecondActivity”android:onClick=”returnReply”android:text=”@string/button_main”android:text=”@string/button_second”

Bước 5: Trong activity_second.xml, sửa đổi các giá trị thuộc tính cho EditText như sau:

Giá trị thuộc tính cũGiá trị thuộc tính mớiandroid:id=”@+id/editText_main”android:id=”@+id/editText_second”app:layout_constraintEnd_toStartOf=”@+id/button”app:layout_constraintEnd_toStartOf=”@+id/button_second”android:hint=”@string/editText_main”android:hint=”@string/editText_second”

Bước 6: Trong trình chỉnh sửa bố cục XML, nhấp vào returnReply, nhấn Alt+Enter và chọn Create ‘returnReply (View)’ in ‘SecondActivity’.

Android Studio tạo một phương thức khung cho trình xử lý returnReply(). Bạn thực hiện phương thức này trong nhiệm vụ tiếp theo.

Bố cục mới cho activity_second.xml trông như thế này:

Mã XML cho tệp bố cục activity_second.xml như sau:

<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"
    tools:context=".SecondActivity">
    <TextView
        android:id="@+id/text_header"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:text="@string/text_header"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/text_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/text_header" />
    <Button
        android:id="@+id/button_second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginBottom="16dp"
        android:onClick="returnReply"
        android:text="@string/button_second"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
    <EditText
        android:id="@+id/editText_second"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="16dp"
        android:ems="10"
        android:hint="@string/editText_second"
        android:inputType="textLongMessage|text"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/button_second"
        app:layout_constraintStart_toStartOf="parent"
        tools:ignore="TouchTargetSizeCheck" />
</androidx.constraintlayout.widget.ConstraintLayout>

6.2 Tạo ý định phản hồi trong Activity thứ hai

Dữ liệu phản hồi từ Activity thứ hai trở lại Activity chính được gửi qua Intent bổ sung. Bạn xây dựng trả về Intent này và đưa dữ liệu vào đó giống như cách bạn làm đối với việc gửi Intent.

Bước 1: Mở SecondActivity.

Bước 2: Ở đầu lớp, thêm một hằng số công khai để xác định khóa cho Intent bổ sung:

public static final String EXTRA_REPLY =
 "com.example.android.twoactivities.extra.REPLY";

Bước 3: Thêm một biến private ở đầu lớp để giữ EditText.

private EditText mReply;

Bước 4: Trong phương thức onCreate(), trước mã Intent, hãy sử dụng findViewByID() để nhận tham chiếu đến EditText và gán nó cho biến private đó:

mReply = findViewById(R.id.editText_second);

Bước 5: Trong phương thức returnReply(), lấy văn bản của chuỗi EditText dưới dạng:

String reply = mReply.getText().toString();

Bước 6: Trong phương thức returnReply(), hãy tạo một ý định mới cho phản hồi – không sử dụng lại đối tượng Intent mà bạn đã nhận được từ yêu cầu ban đầu.

Intent replyIntent = new Intent();

Bước 7: Thêm reply chuỗi từ EditText đến ý định mới như một Intent bổ sung. Vì phần bổ sung là các cặp khóa/giá trị, đây là khóa EXTRA_REPLY và giá trị là reply:

replyIntent.putExtra(EXTRA_REPLY, reply);

Bước 8: Đặt kết quả để RESULT_OK chỉ ra rằng phản hồi đã thành công. Các lớp Activity xác định mã số kết quả, bao gồm RESULT_OK và RESULT_CANCELLED.

setResult(RESULT_OK,replyIntent);

Bước 9: Gọi finish() để đóng Activity và quay lại MainActivity.

finish();

Mã cho SecondActivity bây giờ sẽ như sau:

public class SecondActivity extends AppCompatActivity {
public static final String EXTRA_REPLY = "com.tmtdeveloper.twoactivities.extra.REPLY";
private EditText mReply;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        mReply = findViewById(R.id.editText_second);
        Intent intent = getIntent();
        String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
        TextView textView = findViewById(R.id.text_message);
        textView.setText(message);
    }
    public void returnReply(View view) {
        String reply = mReply.getText().toString();
        Intent replyIntent = new Intent(
        );
        replyIntent.putExtra(EXTRA_REPLY,reply);
        setResult(RESULT_OK, replyIntent);
        finish();
    }
}

6.3 Thêm các phần tử TextView để hiển thị câu trả lời

MainActivity cần một cách để hiển thị câu trả lời được SecondActivity gửi. Trong tác vụ này, bạn thêm các phần tử TextView vào bố cục activity_main.xml để hiển thị câu trả lời MainActivity.

Để thực hiện tác vụ này dễ dàng hơn, bạn sao chép các phần tử TextView bạn đã sử dụng trong SecondActivity.

Bước 1: Mở string.xml và thêm tài nguyên chuỗi cho tiêu đề trả lời:

<string name="text_header_reply">Reply Received</string>

Bước 2: Mở activity_main.xml và activity_second.xml.

Bước 3: Sao chép hai phần tử TextView từ tệp bố cục activity_second.xml và dán chúng vào bố cục activity_main.xml (phía trên Button).

Bước 4: Trong activity_main.xml, sửa đổi các giá trị thuộc tính cho TextView đầu tiên như sau:

Giá trị thuộc tính cũGiá trị thuộc tính mớiandroid:id=”@+id/text_header”android:id=”@+id/text_header_reply”android:text=”@string/text_header”android:text=”@string/text_header_reply”

Bước 5: Trong activity_main.xml, sửa đổi các giá trị thuộc tính cho TextView thứ hai như sau:

Giá trị thuộc tính cũGiá trị thuộc tính mớiandroid:id=”@+id/text_message”android:id= “@+id/text_message_reply”app:layout_constraintTop_toBottomOf=”@+id/text_header”app:layout_constraintTop_toBottomOf=”@+id/text_header_reply”

Bước 6: Thêm thuộc tính android:visibility vào từng thuộc tính TextView để làm cho chúng ẩn ban đầu. (Việc hiển thị chúng trên màn hình nhưng không có bất kỳ nội dung nào, có thể gây nhầm lẫn cho người dùng.)

android:visibility="invisible"

Bạn sẽ hiển thị các phần tử TextView này sau khi dữ liệu phản hồi được chuyển lại từ Activity thứ hai.

Các activity_main.xml bố trí trông giống như nó đã làm trong tác vụ trước, mặc dù bạn đã bổ sung thêm hai TextView mới. Vì bạn đặt các phần tử này ở chế độ ẩn nên chúng sẽ không xuất hiện trên màn hình.

Sau đây là mã XML cho tệp activity_main.xml:

<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"
    tools:context=".MainActivity">
    <TextView
        android:id="@+id/text_header_reply"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:text="@string/text_header_reply"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:visibility="invisible"/>
    <TextView
        android:id="@+id/text_message_reply"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/text_header_reply"
        android:visibility="invisible"/>
    <Button
        android:id="@+id/button_main"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginBottom="16dp"
        android:onClick="launchSecondActivity"
        android:text="@string/button_main"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
    <EditText
        android:id="@+id/editText_main"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="16dp"
        android:ems="10"
        android:hint="@string/editText_main"
        android:inputType="textLongMessage|text"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/button_main"
        app:layout_constraintStart_toStartOf="parent"
        tools:ignore="TouchTargetSizeCheck" />
</androidx.constraintlayout.widget.ConstraintLayout>

6.4 Nhận câu trả lời từ Intent bổ sung và hiển thị nó

Khi bạn sử dụng Intent một cách rõ ràng để bắt đầu một Activity khác, bạn có thể không mong đợi lấy lại bất kỳ dữ liệu nào – bạn chỉ đang kích hoạt dữ liệu Activity đó. Trong trường hợp đó, bạn sử dụng startActivity() để bắt đầu Activity mới, như bạn đã làm trước đó trong thực tế này. Tuy nhiên, nếu bạn muốn lấy dữ liệu từ Activity, bạn cần bắt đầu với startActivityForResult().

Trong tác vụ này, bạn sửa đổi ứng dụng để bắt đầu SecondActivity có dữ liệu trả về từ Intent và hiển thị dữ liệu đó trong các phần tử TextView bạn đã tạo trong tác vụ cuối cùng.

Bước 1: Mở MainActivity.

Bước 2: Thêm một hằng số công khai ở đầu lớp để xác định khóa cho một loại phản hồi cụ thể mà bạn quan tâm:

public static final int TEXT_REQUEST = 1;

Bước 3: Thêm hai biến riêng để giữ tiêu đề trả lời và các phần tử TextView trả lời:

private TextView mReplyHeadTextView;
private TextView mReplyTextView;

Bước 4: Trong phương thức onCreate(), sử dụng findViewByID() để lấy tham chiếu từ bố cục đến tiêu đề trả lời và các phần tử TextView trả lời:

mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);

Phương thức onCreate() đầy đủ bây giờ sẽ giống như sau:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mMessageEditText = findViewById(R.id.editText_main);
    mReplyHeadTextView = findViewById(R.id.text_header_reply);
    mReplyTextView = findViewById(R.id.text_message_reply);
}

Bước 5: Trong phương thức launchSecondActivity(), hãy thay đổi lời gọi startActivity() thành startActivityForResult() và bao gồm khóa TEXT_REQUEST làm đối số:

startActivityForResult(intent, TEXT_REQUEST);

Bước 6: Thêm phương thức onActivityResult() như sau:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
}

Ba đối số để onActivityResult() chứa tất cả thông tin bạn cần để xử lý dữ liệu trả về: đối số requestCode bạn đặt khi khởi chạy Activity với startActivityForResult(), đối số resultCode được khởi chạy Activity (thường là một trong số RESULT_OK hoặc RESULT_CANCELED) và đối số Intent data chứa dữ liệu được trả về từ quá trình khởi chạy Activity.

Bước 7: Bên trong onActivityResult(), hãy gọi super.onActivityResult():

super.onActivityResult(requestCode, resultCode, data);

Bước 8: Thêm mã để kiểm tra TEXT_REQUEST để đảm bảo bạn xử lý Intent kết quả phù hợp, trong trường hợp có nhiều mã. Cũng kiểm tra RESULT_OK để đảm bảo rằng yêu cầu đã thành công:

if (requestCode == TEXT_REQUEST) {
    if (resultCode == RESULT_OK) { 
    }
}

Các Activity lớp xác định mã số kết quả. Mã có thể là RESULT_OK (yêu cầu đã thành công), RESULT_CANCELED (người dùng đã hủy thao tác) hoặc RESULT_FIRST_USER (để xác định mã kết quả của riêng bạn).

Bước 9: Bên trong khối if bên trong, lấy Intent thêm từ response Intent(data). Đây là chìa khóa cho phần bổ sung là hằng số EXTRA_REPLY từ SecondActivity:

String reply = data.getStringExtra(SecondActivity.EXTRA_REPLY);

Bước 10: Đặt khả năng hiển thị của tiêu đề trả lời thành true:

mReplyHeadTextView.setVisibility(View.VISIBLE);

Bước 11: Đặt văn bản TextView trả lời thành reply và đặt khả năng hiển thị của nó thành true:

mReplyTextView.setText(reply);
mReplyTextView.setVisibility(View.VISIBLE);

Phương thức onActivityResult() đầy đủ bây giờ sẽ giống như sau:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == TEXT_REQUEST) {
        if (resultCode == RESULT_OK) {
            String reply = data.getStringExtra(SecondActivity.EXTRA_REPLY);
            mReplyHeadTextView.setVisibility(View.VISIBLE);
            mReplyTextView.setText(reply);
            mReplyTextView.setVisibility(View.VISIBLE);
        }
    }
}

Bước 12: Chạy ứng dụng.

Bây giờ, khi bạn gửi tin nhắn đến Activity thứ hai và nhận được trả lời, Activity chính cập nhật để hiển thị tin nhắn trả lời.

7. Thử thách mã hóa

Tạo một ứng dụng có ba phần tử Button được gắn nhãn Text OneText Two, và Text Three. Khi bất kỳ phần tử Button nào trong số này được nhấp, hãy khởi chạy Activity thứ hai. Activity thứ hai đó phải chứa một ScrollView hiển thị một trong ba đoạn văn bản (bạn có thể bao gồm lựa chọn đoạn văn của mình). Sử dụng Intent để khởi chạy Activity thứ hai với các tính năng bổ sung để cho biết đoạn nào trong số ba đoạn sẽ hiển thị.

8. Tóm tắt

Tổng quát:

  • Một Activity là một thành phần ứng dụng cung cấp một màn hình duy nhất tập trung vào một tác vụ của người dùng.
  • Mỗi Activity có tệp bố cục giao diện người dùng riêng.
  • Bạn có thể chỉ định các Activity triển khai của mình là mối quan hệ cha/con để bật điều hướng Up trong ứng dụng của bạn.
  • Một View có thể được hiển thị hoặc vô hình với thuộc tính android:visibility.

Để triển khai một Activity:

  • Chọn New/Activity để bắt đầu từ một mẫu và tự động thực hiện các bước sau.
  • Nếu không bắt đầu từ mẫu, hãy tạo một Activity lớp Java, triển khai giao diện người dùng cơ bản cho Activity trong tệp bố cục XML được liên kết và khai báo mới Activity trong AndroidManifest.xml.

Intent:

  • Ví dụ IntentIntent cho phép bạn yêu cầu một hành động từ một thành phần khác trong ứng dụng của bạn để bắt đầu một hành động từ một thành phần Activity khác. Một Intent có thể rõ ràng hoặc ngầm.
  • Với một cách rõ ràng, Intent chỉ ra thành phần mục tiêu cụ thể để nhận dữ liệu.
  • Với một cách ngầm định, Intent chỉ định chức năng bạn muốn nhưng không chỉ định thành phần đích.
  • Một Intent có thể bao gồm dữ liệu để thực hiện một hành động (dưới dạng URI) hoặc thông tin dưới dạng Intent bổ sung.
  • Intent bổ sung là các cặp khóa/giá trị trong một Bundle được gửi cùng với Intent.

9. Bài tập về nhà

Mở ứng dụng HelloToast mà bạn đã tạo trong bảng mã thực tế trước đó.

  1. Sửa đổi nút Toast để nó khởi chạy Activity mới hiển thị từ “Hello!” và số lượng hiện tại, như được hiển thị bên dưới.
  2. Thay đổi văn bản trên nút Toast thành Say Hello.

Câu hỏi

Câu 1: Những thay đổi nào được thực hiện khi bạn thêm Activity thứ hai vào ứng dụng của mình bằng cách chọn New/Activity và chọn Activity mẫu? Chọn một:

A. Activity thứ hai được thêm vào dưới dạng một lớp Java. Bạn cần thêm tệp bố cục XML.
B. Tệp bố cục XML Activity thứ hai được tạo và một lớp Java được thêm vào.
C. Activity thứ hai được thêm vào dưới dạng một lớp Java, tệp bố cục XML được tạo và tệp AndroidManifest.xml được thay đổi để khai báo Activity thứ hai.
D. Tệp bố cục XML Activity thứ hai được tạo và tệp AndroidManifest.xml được thay đổi để khai báo tệp Activity thứ hai.

Câu 2: Điều gì xảy ra nếu bạn xóa android:parentActivityName và các phần tử <meta-data> khỏi khai báo Activity thứ hai trong tệp AndroidManifest.xml? Chọn một:

A. Activity thứ hai không còn xuất hiện nữa khi bạn cố gắng bắt đầu nó bằng một câu lệnh Intent rõ ràng.
B. Tệp bố cục XML Activity thứ hai bị xóa.
C. Nút Back không còn hoạt động trong Activity thứ hai để đưa người dùng trở lại Activity chính.
D. Nút Up trên thanh ứng dụng không còn xuất hiện trong Activity thứ hai để đưa người dùng trở lại Activity chính.

Câu 3: Bạn sử dụng phương thức khởi tạo nào để tạo mới một Intent rõ ràng? Chọn một:

A. new Intent()
B. new Intent(Context context, Class<?> class)
C. new Intent(String action, Uri uri)
D. new Intent(String action)

Câu 4: Trong bài tập về ứng dụng HelloToast, làm cách nào để bạn thêm giá trị hiện tại của số đếm vào Intent? Chọn một:

A. Như Intent dữ liệu
B. Như Intent TEXT_REQUEST
C. Như Intent hành động
D. Như Intent bổ sung

Câu 5: Trong bài tập về ứng dụng HelloToast, làm cách nào để bạn hiển thị số đếm hiện tại trong câu “Hello” Activity thứ hai? Chọn một:

A. Nhận được những gì Intent đã được khởi chạy với Activity.
B. Lấy giá trị đếm hiện tại ra khỏi Intent.
C. Cập nhật số đếm TextView.
D. Tất cả những điều trên.

Gửi ứng dụng của bạn để chấm điểm

Kiểm tra để đảm bảo rằng ứng dụng có các tính năng sau:

  • Nó hiển thị nút Say Hello thay vì nút Toast.
  • Activity thứ hai bắt đầu khi nút Say Hello được nhấn và nó sẽ hiển thị thông báo “Hello!” và số lượng hiện tại từ MainActivity.
  • Tệp Java và bố cục XML cho Activity thứ hai đã được thêm vào dự án.
  • Tệp bố cục XML cho Activity thứ hai chứa hai phần tử TextView, một phần tử có chuỗi “Hello!” và phần tử thứ hai là count.
  • Bao gồm việc triển khai phương thức xử lý nhấp chuột cho nút Say Hello (trong MainActivity).
  • Bao gồm việc triển khai phương thức onCreate() cho Activity thứ hai và cập nhật số lượng TextView với count từ MainActivity.