Chả là thời gian vừa rồi tôi có cơ hội tiếp cận dự án porting ứng dụng trên macOS sang ứng dụng Android nên có tổng hợp lại để sau này dùng nếu cần hoặc hữu ích với ai đó đang tìm kiếm (thời điểm tôi viết tìm tiếng Anh & Việt rất hiếm, có lẽ đây là bài viết đầu tiên bằng tiếng Việt có cái nhìn tổng quan đến như vậy).
Có thể nó sẽ rất hữu ích khi chúng ta nghĩ, thiết kế hệ thống mới.
Porting có thể hiểu là việc convert phần mềm chạy nền tảng này sang nền tảng khác.
Ví dụ: convert app xử lý âm thanh chạy trên windows được viết bằng C/C++/Objective-C sang Android app được viết bằng Java.
Phần mềm Portable cũng bắt nguồn từ từ này, Portable nghĩa là linh động, di động, linh hoạt không cần cài cắm, có hẳn 1 trang cho các phần mềm dạng đó: portableapps.com
Xem qua các nội dung cần chú ý khi porting:
- Kiểu dữ liệu (data type)
- Pointer vs Reference vs Array vs Object
- Struct vs Class
- Cast (ép kiểu)
- So sánh UInt8 and uint8_t
Bắt đầu đi chi tiết:
Kiểu dữ liệu (data type)
Các ngôn ngữ như C, C++, Objective-C, Java rất quan trọng kiểu dữ liệu. Do đó việc đầu tiên phải chú ý đó là kiểu dữ liệu tương ứng.
Nếu không lưu đúng kiểu data thì sẽ gây ra chương trình bị lỗi.
vd: đáng lẽ phải lưu số 128 mà ta chỉ lưu số -1 thì sẽ gây ra lỗi nghiêm trọng trong các phép tính: cộng, trừ, nhân, chia.
(ở đây chúng ta ví dụ số 128 là vì trong Java: số nguyên lớn nhất 1 byte có thể chứa được là số nguyên 127, bạn phải chú ý điều này)
1. Các kiểu dữ liệu nguyên thuỷ có trong Java
Đầu tiên chúng ta xem thử trong Java có những kiểu gì.
Trong tiếng Anh họ dùng từ primitive, khi đọc các tài liệu tiếng Việt bạn có thể hiểu nó là kiểu dữ liệu nguyên thuỷ hoặc kiểu dữ liệu gốc. Vì ngoài kiểu primitive này ra Java còn có các kiểu dữ liệu reference hay đôi khi họ gọi là non-primitive. Nói qua loại reference này là 1 kiểu wrapper class bọc lấy kiểu primitive và thêm các phương thức tiện ích cho tiện thao tác.
Loại primitive | Kích thước | Giải thích | Loại reference tương ứng |
byte | 1 byte | dùng để chứa số: từ -128 đến 127 | Byte |
short | 2 bytes | dùng để chứa số: từ -32,768 đến 32,767 | Short |
int | 4 bytes | dùng để chứa số: từ -2,147,483,648 đến 2,147,483,647 | Integer |
long | 8 bytes | dùng để chứa số: từ -9,223,372,036,854,775,808 đến 9,223,372,036,854,775,807 | Long |
float | 4 bytes | lưu số thập phân từ: 1.4e-45f đến 3.4028235e+38f (340,282,346,638,528,860,000,000,000,000,000,000,000.000000) | Float |
double | 8 bytes | lưu số thập phân | Double |
boolean | 1 bit | chỉ lưu giá trị đúng sai – true false | Boolean |
char | 2 bytes | 1 ký tự hoặc số từ 0 đến 65535 (có thể gán trực tiếp bằng kí tự hoặc số nguyên) | Character |
2. So sánh các kiểu dữ liệu tương ứng Java vs C/C++
Java | C/C++ |
byte (max: 127) | char, int8 (max: 127) |
short (max: 32767) | uint8, Uint8 (max: 255) |
int (max: 2147483647) | uint16 (max: 65535) |
int (max: 2147483647) | int 4 bytes (max: 2147483647) (tuỳ platform mà kiểu “int” này có “độ nặng” 2 bytes) |
long (max: 9,223,372,036,854,775,807) | uint32 (max: 4294967295) |
float | float |
double | double |
boolean | boolean |
char | char |
Chúng ta có thể lưu số nguyên trong nhiều kiểu dữ liệu khác nhau. (Số nguyên có 2 kiểu âm & dương)
Ví dụ có thể lưu số nguyên 1, 2, 3… bằng:
– kiểu int (rất hay dùng)
– hoặc kiểu byte
– hoặc kiểu short
– hoặc kiểu long
– và kể cả bằng kiểu float.
Nhưng có vấn đề đấy là:
Với những số nhỏ 1, 2, 3 thì không có sự khác biệt gì và chỉ khi muốn lưu những số lớn như tầm hàng tỷ thì có sự khác biệt cực lớn.
Ví dụ: bạn đang làm ứng dụng ngân hàng muốn lưu số tiền 5 tỷ vậy bạn chọn kiểu dữ liệu nào để lưu số nguyên 5,000,000,000?
Cụ thể ứng dụng đó được viết bằng Java thì bạn không thể lưu bằng byte, short, int được mà bạn phải lưu bằng kiểu long. Vì theo range này bạn lưu số 5 tỷ thì vượt quá sức của các kiểu byte, short, int và trong Java lại không có kiểu unsigned int. Kể cả có kiểu unsigned int như C/C++/Objective – C đi chăng nữa cũng không thể chứa hết vì unsigned int có range là: 0 ~ 4 294 967 295 (max gần 4 tỷ 3)
byte -128 ~ 127
short -32,768 ~ 32,767
int -2,147,483,648 ~ 2,147,483,647
Do đó kiểu long là kiểu đúng nhất. Bạn có thể lưu được số tiền của người giàu nhất thế giới lên đến 9 tỷ tỷ.
Trường hợp lưu số lẻ thập phân trong tài khoản thì cần phải dùng kiểu float hoặc kiểu double.
3. Dùng số hệ Dec hay số hệ Hex?
1 số nguyên có thể viết ở các hệ khác nhau:
Ví dụ: số 255 hệ Dec có thể viết ở hệ Hex là 0xFF
Chúng ta có thể lưu số nguyên 255 theo kiểu này:
int my_var = 0xFF giống với int my_var = 255
Do đó 2 cách viết này là hoàn toàn giống nhau, dùng cách nào đó là tuỳ bạn.
Pointer vs Reference vs Array vs Object
Trong Java không có con trỏ nên muốn dùng theo phong cách con trỏ C/C++/Objective-C thì chúng ta phải dùng đối tượng hoặc mảng thay thế. Nếu dùng đối tượng hoặc mảng thì ta có thể hiểu là đang dùng tham chiếu. Tương tự cách dùng &abc hay *xyz.
Trong C, C++:
- &abc là lấy địa chỉ 1 biến abc
- *xyz là lấy ra giá trị của vùng nhớ mà con trỏ xyz trỏ đến.
- C/C++ array chính là 1 con trỏ, mặc định con trỏ này trỏ vào array[0]
Struct vs Class
Trong Java không có struct nên muốn dùng theo phong cách C/C++ thì chúng ta có thể dùng static inner class
Cast (ép kiểu)
Khi chuyển các kiểu dữ liệu với nhau ta mới cần cast.
Nếu chuyển byte sang int thì làm như sau: int so_nguyen = abc & 0xFF
Nếu chỉ thao tác trên cùng kiểu dữ liệu thì không cần cast, byte thì dữ nguyên byte, int thì giữ nguyên int (điều này rất quan trọng)
So sánh UInt8 and uint8_t
kiểu nào có “_t” đằng sau là portable tức là có thể chạy multi-platform mà không gặp vấn đề gì về kiểu dữ liệu.
uint8_t đảm bảo rằng biến đang được khai báo luôn là số nguyên 8 bits.
Tương tự cho kiểu uint16_t, uint32_t…
Lời kết
Porting ứng dụng từ macOS sang Android là một quá trình phức tạp và đòi hỏi sự chú ý đến nhiều yếu tố khác nhau. Tuy nhiên, nếu được thực hiện một cách đúng đắn, việc porting ứng dụng có thể mang lại nhiều lợi ích và giúp tăng cường trải nghiệm người dùng, giúp mở rộng thị trường tiềm năng cho ứng dụng.
Để đạt được mục tiêu porting ứng dụng thành công, cần phải có kế hoạch rõ ràng và cẩn thận với quá trình chuyển đổi mã nguồn và thiết kế giao diện. Việc sử dụng các công cụ và framework hỗ trợ cũng rất quan trọng trong quá trình này. Nếu không có kinh nghiệm về porting, bạn nên tìm kiếm sự giúp đỡ từ những chuyên gia hoặc công ty phát triển phần mềm. Liên hệ với dotrinh cũng là một ý tưởng tốt!
Tham khảo thêm
https://dotrinh.com/little-endian-unsinged-trong-java/
https://docs.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=msvc-170
https://stackoverflow.com/questions/16937459/whats-the-difference-between-uint8-and-uint8-t
https://www.cs.cornell.edu/courses/cs202/2002sp/JavaCcomparison.html
https://introcs.cs.princeton.edu/java/faq/c2java.html
https://stackoverflow.com/questions/2386772/what-is-the-difference-between-float-and-double
*Bài viết này sẽ được bổ sung thêm khi cần thiết.
Các bài viết không xem thì tiếc:
- Little Endian Unsinged trong Java
- Copy mảng byte trong Java bằng Arrays.copyOfRange()
- Thiết kế website số 1 Việt Nam và thiết kế web top 1 Google
- Thuật toán tìm kiếm nhị phân (Binary Search)
- Tổng quan nhất về ứng dụng Android
- Thuê quản trị website bao nhiêu tiền?
- 30 tuổi học lập trình có muộn không?
- 7 lời khuyên của Sam Altman để thành công
- Làm việc và học tập 1 cách thông minh hơn – năng suất hơn – chill hơn với ChatGPT
- CÔNG CỤ HAY DÙNG CHO LẬP TRÌNH NHÚNG
- Siêu tổng hợp iOS code snippets – Objective C
- CHECKLIST KHI UPDATE APP ĐÃ CÓ TRÊN APP STORE | dotrinh.com
- Tạo icon cho app trong android
- Test app chuyển ảnh thường thành ảnh hoạt hình sử dụng trí tuệ nhân tạo
- Tại sao đã thêm vào file gitignore rồi mà không có tác dụng?
1 Comment