Tìm hiểu về Native Modules trong React Native (Android)

Có lẽ hiện tại React Native không còn lạ lẫm so với anh em làm IT nói chung và Mobile nói riêng, với mục tiêu không cần học thêm ngôn ngữ mà vẫn làm đa nền tảng nhưng vẫn đem lại hiệu suất tương đương với ứng dụng native. Tuyệt vời!

Tuy nhiên chủ đề lần này mình sẽ xin nói tới việc kết nối React (JS) từ phía trên với phần native bên dưới, chính là thứ cốt lõi đem lại hiệu suất mượt mà cho ứng dụng của bạn.

I. Giới thiệu chung

Native Modules là cách gọi của React Native (RN) khi chúng ta truy xuất đến một chức năng native, vì truy xuất đến native nên nó sẽ mang lại hiệu suất native như quảng cáo của FB là điều khả dĩ. Tất nhiên không hẳn là 100% nhưng cũng được 99% ^^!

Về bản chất, RN cung cấp một số thư viện làm cầu nối (bridge) để JS có thể call được tới các thành phần native. Giờ chúng ta cùng tìm hiểu chi tiết hơn nhé!

II. Thử nghiệm xây dựng Toast Module

1. Mục tiêu

Giả sử chúng ta cần hiện một popup thông báo nho nhỏ trong vài giây để thông báo cho người dùng, ví dụ như đăng nhập thành công chẳng hạn. Lúc này chúng ta có thể dùng sẵn chức năng Toast trong Android gốc dễ dàng.

2. Các bước thực hiện

Đầu tiên, chúng ta mở Android Studio, tạo một package mới tên là modules chẳng hạn, và tạo một file ToastModule.java.

package com.facebook.react.modules.toast;

import android.widget.Toast;

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

import java.util.Map;
import java.util.HashMap;

public class ToastModule extends ReactContextBaseJavaModule {

  private static final String DURATION_SHORT_KEY = "SHORT";
  private static final String DURATION_LONG_KEY = "LONG";

  public ToastModule(ReactApplicationContext reactContext) {
    super(reactContext);
  }
}

Bước này chúng ta sử dụng các thư viện bridge có sẵn để thiết lập kết nói với phía JS bên ngoài, tất nhiên để bên ngoài biết cần phải gọi module này thế nào. Chúng ta cần khai báo tiếp vào file này như sau.

  @Override
  public String getName() {
    return "ToastExample";
  }

Sau bước này chúng ta đã có tên ToastExample để giao tiếp với JS. Để xử lý thời gian hiện ngắn hay dài, ta sẽ thêm một đoạn xử lý sau (phần này tuỳ với native bạn có thể custom thoải mái), với mục đích khai báo const (hằng số) cho phần JS xài (quá bá đạo).

  @Override
  public Map<String, Object> getConstants() {
    final Map<String, Object> constants = new HashMap<>();
    constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT);
    constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG);
    return constants;
  }

Cuối cùng viết một function nữa để sau này ra JS call cho nó hiện lên thông báo.

  @ReactMethod
  public void show(String message, int duration) {
    Toast.makeText(getReactApplicationContext(), message, duration).show();
  }

Vậy là xong, chúng ta có một hàm tên show nhận vào 2 đối số là message là nội dung và duration là thời gian hiển thị. Tiếp theo chúng ta cần implement nó bằng interface Package chung của RN (tương tự như các native modules khác mà RN đã viết sẵn).

Chúng ta tiếp tục tạo một file mới tên là CustomReactPackages.java chẳng hạn, import file ToastModule vừa xong và khai báo như sau để đăng ký.

package com.facebook.react.modules.toast;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CustomReactPackages implements ReactPackage {

  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Collections.emptyList();
  }

  @Override
  public List<NativeModule> createNativeModules(
                              ReactApplicationContext reactContext) {
    List<NativeModule> modules = new ArrayList<>();

    modules.add(new ToastModule(reactContext));

    return modules;
  }

}

Cuối cùng chúng ta đăng ký thêm Package đó với ứng dụng chính là xong. Ta sửa file MainApplication.java

protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
            new MainReactPackage(),
            new CustomReactPackages()); // <-- Add this line with your package name.
}

3. Sử dụng

Sau khi đăng ký xong, ta vào ứng dụng RN bình thường và chỉ cần khai báo như sau là xài được ngay.

import { NativeModules } from 'react-native';
NativeModules.ToastExample.show('Awesome', ToastExample.SHORT);

Thật sự đơn giản và có kết quả ngay...

Kết luận

Chỉ với một chút kiến thức về native, chúng ta hoàn toàn có thể xây dựng một module dễ dàng mà còn đem lại hiệu suất tuyệt vời cho ứng dụng thay vì phải làm hoàn toàn bằng native. Hơn nữa cùng với chung một lời gọi trên JS, chúng ta hoàn toàn có thể viết tiếp native module cho iOS để build đa nền tảng.

Đương nhiên, các native module này bạn hoàn toàn có thể export ra thành lib cho từng platform, tái sử dụng trong những dự án sau này, quả thực rất tiện lợi ^^. Để tìm hiểu thêm về những chức năng RN hỗ trợ khi làm việc với Native Modules, bạn tham khảo thêm tại đây. Bài viết tiếp theo mình sẽ chia sẻ sâu hơn về phần này.