Cẩm Nang Android
Nguyễn Công Tuệ Page 1 of 216
Bài 1: WHAT IS ANDROID 6
I. Features 6
II. Android Architecture 7
III. Applications 7
IV. Application Framework 7
V. Libraries 8
VI. Android Runtime 8
VII. Linux Kernel 9
Bài 2: Application Fundamentals 10
I. Application Components 10
1. Activities 10
2. Services 11
3. Broadcast Receivers 11
4. Content Providers 12
5. Activating components: intents 12
6. Shutting down components 13
7. The manifest file 13
8. Intent filters 14
II. Processes And Threads 15
1. Processes 15
2. Threads 15
3. Remote procedure calls 16
III. Component Lifecycles 17
1. Activity lifecycle 17
2. Service lifecycle 22
3. Broadcast receiver lifecylce 23
4. Processes and lifecycles 24
Bài 3: Activities 26
I. Creating An Activity 26
1. Implementing a user interface 27
2. Declairing the activity in the manifest 27
II. Starting an Activity 28
1. Starting an activity for a result 29
III. Shutting Down an Activity 30
IV. Managing the Activity Lifecycle 30
1. Implementing the lifecycle callbacks 31
2. Saving activity state 35
3. Handing configuration changes 37
4. Coordinating activities 37
Bài 4: Task And Back Stack 39
I. Saving activity state 42
II. Managing Tasks 42
1. Defining launch modes 43
2. Handling affinities 46
3. Clearing the back stack 48
4. Starting a task 48
Cẩm Nang Android
Nguyễn Công Tuệ Page 2 of 216
Bài 5: Processes And Threads 50
I. Processes 50
1. Process lifecycle 51
II. Threads 53
1. Worker threads 54
2. Thread-safe modes 63
III. Interprocess Communication 64
Bài 6: User Interface 65
1. View hierarchy 65
2. Layout 66
3. Widgets 66
4. UI events 66
5. Menus 67
6. Advanced topics 67
Bài 7: Declaring Layout 69
I. Write the XML 69
II. Load the XML resource 70
III. Attributes 70
1. ID 70
2. Layout Parameters 71
IV. Layout Position 72
V. Size, Padding and Margin 72
1. Size 72
2. Padding 72
3. Margin 72
Bài 8: Creating Menus 73
I. Defining Menus 73
II. Inflating a Menu Resource 74
III. Creating an Options Menu 74
1. Changing the menu when it opens 75
IV. Creating a Context Menu 75
V. Creating Submenus 76
VI. Other Menu Features 77
1. Menu groups 77
2. Checkable menu items 77
3. Shortcut keys 79
4. Intents for menu items 79
Bài 9: Creating Dialogs 82
I. Showing a Dialog 82
II. Dismissing a Dialog 83
1. Using dismiss listeners 83
III. Creating an AlertDialog 84
1. Adding buttons 84
2. Adding a list 85
3. Adding checkboxes and radio buttons 85
IV. Creating a ProcessDialog 86
Cẩm Nang Android
Nguyễn Công Tuệ Page 3 of 216
1. Showing a process bar 87
V. Creating a Custom Dialog 89
Bài 10: Handling UI Events 92
I. Event Listeners 92
II. Event Handlers 94
III. Handling Focus 95
Bài 11: Notifying The User 96
I. Creating Toast Notification 96
1. The Basics 97
2. Positioning your Toast 97
3. Creating a Custom Toast View 97
II. Creating Status Bar Notification 98
1. The basics 99
2. Managing your Notifications 100
3. Creating a Notification 100
4. Creating a Custom Expanded View 103
III. Creating Dialog Notification 105
Bài 12: Applying Styles And Themes 106
I. Defining Styles 106
1. Inheritance 107
2. Style Properties 108
3. Applying Styles and Themes to the UI 108
II. Using Platform Styles and Themes 110
Bài 13: Building Custom Components 111
I. The Basic Approach 111
II. Fully Customized Components 111
1. Extend onDraw() and onMeasure() 111
2. Bạn có thể tìm hiểu các ví dụ: 113
Bài 14: Binding To Data With AdapterView 114
I. Filling The Layout With Data 114
II. Handling User Selections 115
Bài 15: Common Layout Objects 116
I. FrameLayout 116
II. LinearLayout 116
III. TableLayout 117
IV. RelativeLayout 118
V. Summary of Important View Groups 119
VI. How Android Draws Views 121
Bài 16: Application Resources 123
I. Providing Resources 124
1. Grouping Resource Types 124
2. Providing Alternative Resources 126
3. Providing the Best Device Compatibility with Resources 133
4. How Android finds the Best-matching Resource 135
II. Accessing Resources 137
1. Accessing Resources in Code 138
Cẩm Nang Android
Nguyễn Công Tuệ Page 4 of 216
2. Accessing Resources from XML 139
3. Accessing Platform Resources 141
III. Handling Runtime Changes 142
1. Retaining an Object During a Configuration Change 142
2. Handling the Configuration Change Yourself 143
IV. Localization 145
1. Overview: Resource-Switching in Android 145
2. Using Resources for Localization 146
3. Localization Strateies 149
4. Testing Localized Applications 150
5. Publishing Localized Applications 151
6. Localization Checklists 151
V. Resource Types 153
Bài 17: Intents And Intent Filters 154
I. Intent Objects 154
1. Component name 154
2. Action 155
3. Data 155
4. Category 156
5. Extras 156
6. Flags 157
II. Intent Resolution 157
1. Intent Filters 157
2. Common cases 160
3. Using intent matching 161
4. Note Pad Example 161
Bài 18: Data Storage 162
I. Using Shared Preferences 162
II. Using the Internal Storage 163
1. Saving cache files 164
2. Other useful methods 164
III. Using the External Storage 164
1. Checking media availability 165
2. Accessing files on external storage 165
3. Saving files that should be shared 166
4. Saving cache files 166
IV. Using Databases 167
1. Database debugging 167
V. Using a Network Connection 168
Bài 19: Data Backup 169
I. The Basics 170
II. Declaring the Backup Agent in Your Manifest 170
III. Registering for Android Backup Service 171
IV. Extending BackupAgent 172
1. Required Methods 172
2. Performing backup 173
Cẩm Nang Android
Nguyễn Công Tuệ Page 5 of 216
3. Performing restore 175
V. Extending BackupAgentHelper 177
1. Backing up SharedPreferences 177
2. Backing up other files 178
VI. Cheking the Restore Data Version 179
VII. Requesting Backup 180
VIII. Requesting Restore 181
IX. Testing Your Backup Agent 181
1. Cài đặt ứng dụng trên Android system image phù hợp 181
2. Đảm bảo backup là enable 181
3. Mở ứng dụng và khởi tạo dữ liệu 181
4. Khởi tạo một hoạt động backup 181
5. Uninstall ứng dụng 182
6. Re-install ứng dụng 182
Bài 20: Content Providers 183
I. Content Provider Basics 183
1. The data model 183
2. URIs 184
II. Querying a Content Provider 184
1. Making the query 185
2. What a query return 186
3. Reading retrieved data 187
III. Modifying data 188
1. Adding records 188
2. Adding new values 189
3. Batch updating records 190
4. Deleting a record 190
IV. Creating a Content Provider 191
1. Extending the ContentProvider class 191
2. Delairing the content provider 193
V. Content URI Summary 194
Bài 21: Security And Permission 195
I. Security Architecture 195
II. Application Signing 195
III. User IDs and File Access 196
IV. Using Permissions 196
V. Declaring and Enforcing Permissions 197
1. Enforcing Permissions in AndroidManifest.xml 198
2. Enforcing Permission when Sending Broadcasts 199
3. Other Permission Enforcement 199
VI. URI Permissions 200
Bài 22: Graphics 201
I. Consider your Options 201
II. Simple Graphics Inside a View 201
III. Draw with a Canvas 202
1. On a View 202
Cẩm Nang Android
Nguyễn Công Tuệ Page 6 of 216
2. On a Surface 203
Bài 23: 2D Graphics 205
I. Drawables 205
1. Creating from resource images 205
2. Creating from resource XML 207
II. Shape Drawable 208
III. Nine-patch 209
1. Example XML 210
Bài 24: 3D With OpenGL 212
I. Using The API 212
II. Links To Additional Information 212
Bài 25: View Animation 213
I. Tween Animation 213
II. Frame Animation 215
Bài 1: WHAT IS ANDROID
Android là một sofware stack cho các thiết bị di động bao gồm: một hệ điều hành,
midleware và key application. Android SDK cung cấp các công cụ (tool) và APIs cần
thiết để phát triển ứng dụng trên Android platform. Android platform sử dụng ngôn ngữ
lập trình Java.
I.Features
Application framework cho phép tái sử dụng và thay thế (replacement) các
component.
Dalvik virtual machine optimize các thiết bị di động.
Integrated browser dựa trên mã nguồn mở WebKit engine.
Optimized graphics xử lý đồ họa mạnh mẽ với thư viện 2D graphics, 3D dựa
trên đặc tả OpenGL ES 1.0 (hardware acceleration optional).
SQLite lưu trữ cơ sở dữ liệu.
Media support hỗ trợ các media như: audio, video, và các định dạng hình ảnh
như: MPEG4, H.264, MP3, AAC, AMR, JPG, PNG, GIF.
GSM Telephony phụ thuộc vào phần cứng của thiết bị.
Bluetooth, EDGE, 3G, and WiFi phụ thuộc vào phần cứng của thiết bị.
Cẩm Nang Android
Nguyễn Công Tuệ Page 7 of 216
Camera, GPS, compass, and accelerometer phụ thuộc vào phần cứng của thiết
bị.
Rich development environment bao gồm một emulator thiết bị , các tool phục
vụ cho debug, memory và performance profiling, và plugin cho Eclipse IDE.
II.Android Architecture
Sơ đồ dưới đây mô tả cấu trúc của hệ điều hành Android.
III.Applications
Các ứng dụng core của Android bao gồm: mail client, SMS program, calendar,
maps, browser, contacts… Tất cả các ứng dụng được viết bằng ngôn ngữ Java.
IV.Application Framework
Bằng cách cung cấp một nền tảng phát triển mở, Android cung cấp cho
developers khả năng xây dựng các ứng dụng vô cùng phong phú và sáng tạo.
Developers có thể tự do tận dụng các thiết bị phần cứng, thông tin vị trí GPS,
chạy các dịch vụ background, thiết lập hẹn giờ alarm, thêm các thông báo vào
status bar
Cẩm Nang Android
Nguyễn Công Tuệ Page 8 of 216
Các nhà phát triển có thể truy cập vào cùng framework API được sử dụng bởi các
ứng dụng core. Kiến trúc ứng dụng được thiết kế đơn giản nhằm tái sử dụng các
thành phần; bất kỳ ứng dụng nào cũng có thể công bố capability của mình để các
ứng dụng khác có thể sử dụng những capability đó tùy thuộc vào sự giới hạn về
bảo mật được thực thi bởi framework.
Các thành phần chạy bên dưới của ứng dụng là một tập hợp các service và hệ
thống bao gồm:
o Views sử dụng để xây dựng các thành phần của ứng dụng, gồm có: list,
grid, text box, button và web browser.
o Content Providers cho phép truy cập vào dữ liệu của các ứng dụng khác
(như Contacts) và chia sẽ dữ liệu giữa chúng.
o Resource Manager cho phép truy cập vào các tài nguyên non-code như
localized strings, graphics và các file layout.
o Notification Manager cho phép tất cả các ứng dụng hiển thị các cảnh
báo(alert) được custom trong status bar.
o Activity Manager quản lý tất cả các vòng đời của ứng dụng và cung cấp
một backstack chung.
V.Libraries
Android bao gồm một tập các thư viện C/C++ sử dụng bởi nhiều thành phần khác nhau
của hệ điều hành Android. Những khả năng này được liên lạc(expose) với developers
thông qua các framework của Android. Một số thư viện core như sau:
System C library - a BSD-derived implementation of the standard C system
library (libc), tuned for embedded Linux-based devices.
Media Libraries - based on PacketVideo's OpenCORE; the libraries support
playback and recording of many popular audio and video formats, as well as static
image files, including MPEG4, H.264, MP3, AAC, AMR, JPG, and PNG
Surface Manager - manages access to the display subsystem and seamlessly
composites 2D and 3D graphic layers from multiple applications.
LibWebCore - a modern web browser engine which powers both the Android
browser and an embeddable web view.
SGL - the underlying 2D graphics engine.
3D libraries - an implementation based on OpenGL ES 1.0 APIs; the libraries use
either hardware 3D acceleration (where available) or the included, highly
optimized 3D software rasterizer.
FreeType - bitmap and vector font rendering.
SQLite - a powerful and lightweight relational database engine available to all
applications.
VI.Android Runtime
Android bao gồm một tập các thư viện cơ bản để cung cấp hầu hết các chức năng
sẵn có trong các thư viện core của ngôn ngữ lập trình JAVA.
Cẩm Nang Android
Nguyễn Công Tuệ Page 9 of 216
Tất cả các ứng dụng Android đều chạy trong tiến trình(process) riêng của nó, với
thể hiện (instance) riêng của nó của máy ảo Dalvik. Dalvik đã được viết để một
thiết bị có thể chạy nhiều máy ảo một cách hiệu quả. Máy ảo Dalvik thực thi các
file định dạng Dalvik Executable (.dex) được tối ưu hóa cho bộ nhớ tối thiểu. Máy
ảo VM được đăng ký, và chạy các class được biên dịch bởi trình biên dịch ngôn
ngữ Java đã được chuyển đổi thành các định dạng .dex bởi tool "dx".
Máy ảo Dalvik dựa trên Linux Kernel cho các chức năng cơ bản như thread và
quản lý bộ nhớ ở mức độ thấp.
VII.Linux Kernel
Android dựa trên Linux phiên bản 2.6 cho các dịch vụ hệ thống như: bảo mật, quản lý bộ
nhớ, quản lý process, network stack và driver model. Kernel cũng hoạt động như là một
tầng trừu tượng hóa(abstraction layer) giữa phần cứng và rest của software stack.
Cẩm Nang Android
Nguyễn Công Tuệ Page 10 of 216
Bài 2: Application Fundamentals
Các ứng dụng Android được viết bởi ngôn ngữ JAVA. Mã Java đã được biên dịch
cùng với các dữ liệu và các file tài nguyên được yêu cầu bởi ứng dụng được đóng
gói bởi tool aapt trong Android package, một file archive .apk. File này được sử
dụng để phân phối các ứng dụng và cài đặt nó lên thiết bị, nó là file mà người
dùng download nó vào ứng dụng. Tất cả code trong một file .apk được xem là một
ứng dụng.
Theo mặc định, mỗi ứng dụng Android chạy trên tiến trình Linux của chính nó.
Android bắt đầu tiến trình khi code của ứng dụng cần được thực thi và kết thúc
tiến trình khi nó không còn cần thiết và các tài nguyên của ứng dụng được yêu
cầu bởi các ứng dụng khác.
Mỗi một tiến trình đều có một máy ảo VM của riêng nó, vì vậy code của mỗi ứng
dụng chạy độc lập với các ứng dụng khác.
Theo mặc định, mỗi ứng dụng được chỉ định một ID người dùng Linux duy nhất.
Permission được thiết lập để các file của ứng dụng chỉ hiển thị cho người dùng đó
và chỉ cho ứng dụng đó - mặc dù có nhiều cách để export chúng vào các ứng dụng
khác.
Có thể sắp xếp cho hai ứng dụng chia sẻ cùng một ID người dùng, trong trường
hợp chúng có thể xem các file của nhau. Để tiết kiệm tài nguyên hệ thống, các
ứng dụng với cùng một ID cũng có thể sắp xếp để chạy trong cùng tiến trình
Linux, chia sẻ cùng một máy ảo.
I.Application Components
Một tính năng nổi bật của Android là một ứng dụng có thể sử dụng các thành
phần của các ứng dụng khác. Ví dụ, nếu ứng dụng của bạn cần hiển thị một danh
sách các image, và các ứng dụng khác đã phát triển danh sách này phù hợp với
yêu cầu của bạn, thì bạn chỉ cần gọi nó lên để sử dụng thay vì phát triển lại. Ứng
dụng của bạn không kết hợp mã nguồn của ứng dụng khác hay liên kết với nó,
thay vào đó nó chỉ đơn giãn start một mẫu của các ứng dụng khác khi nhu cầu
phát sinh.
Đối làm được điều này, hệ thống phải có khả năng start một tiến trình ứng dụng
khi bất kỳ thành phần nào của nó cần thiết, và khởi tạo các đối tượng Java cho
thành phần đó. Vì vậy, không giống như các ứng dụng trên các hệ thống khác, các
ứng dụng Android không có một entry point duy nhất cho ứng dụng (chẳng hạn
như không có phương thức main()). Thay vào đó, chúng có các thành phần mà hệ
thống có thể khởi tạo và chạy khi cần thiết. Có bốn loại thành phần:
1.Activities
Một Activity đại diện cho một giao diện người dùng trực quan mà người dùng có
thể thực hiện. Ví dụ, một Activity có thể là một danh sách các menu item mà
người dùng có thể lựa chọn. Một ứng dụng gửi tin nhắn văn bản có thể có một
Cẩm Nang Android
Nguyễn Công Tuệ Page 11 of 216
Activity để hiển thị một danh sách các contacts để gửi tin nhắn đến, một Activity
thứ hai để viết tin nhắn đến contact đã chọn, và các Activity khác để xem tin nhắn
cũ hoặc cài đặt các thay đổi. Mặc dù chúng làm việc cùng nhau để tạo thành một
giao diện người dùng gắn kết, nhưng mỗi Activity độc lập với nhau.
Mỗi Activity có một cửa sổ mặc định để vẽ. Thông thường, cửa sổ này fill đầy
màn hình nhưng cũng có thể nhỏ hơn màn hình và nổi lên trên các cửa sổ khác.
Một Activity cũng có thể sử dụng các cửa sổ bổ sung - ví dụ, một hộp thoại pop-
up được gọi cho một phản ứng người dùng, hoặc một cửa sổ mà trình bày cho
users thông tin quan trọng khi lựa chọn một mục cụ thể trên màn hình.
Các nội dung trực quan của cửa sổ được cung cấp bởi một hệ thống các views –
các đối tượng xuất phát từ lớp cơ sở View. Mỗi view kiểm soát một không gian
hình chữ nhật cụ thể trong cửa sổ. Các view cha sẽ bố trí layout cho các phần tử
con của nó. View là nơi mà hoạt động tương tác với người dùng diễn ra.
Để đưa một View vào cửa sổ của Acitivity, gọi phương thức
Acitivity.setContentView().
2.Services
Một Service không có một giao diện người dùng trực quan, mà nó chạy
background trong một khoản thời gian không xác định. Ví dụ, một Service có thể
chơi nhạc nền khi người dùng tham dự vào các vấn đề khác, hoặc nó có thể lấy dữ
liệu qua mạng hoặc tính toán một cái gì đó và cung cấp các kết quả cho các hoạt
động cần thiết. Mỗi dịch vụ kế thừa từ lớp cơ sở Service.
Có thể kết nối hay binding đến một dịch vụ đang diễn ra (ongoing) và start một
dịch vụ nếu nó chưa được chạy. Trong khi kết nối, bạn có thể giao tiếp với dịch
vụ thông qua một giao diện mà dịch vụ expose. Đối với các dịch vụ âm nhạc, giao
diện này cho phép người dùng có thể tạm dừng, tua lại, dừng lại, và khởi động lại
playback.
Cũng giống như các Activities và các thành phần khác, các dịch vụ chạy trong các
thread chính của tiến trình ứng dụng. Vì vậy, chúng sẽ không ngăn chặn các thành
phần khác hoặc giao diện người dùng, chúng thường sản sinh ra một thread khác
cho các task tốn thời gian.
3.Broadcast Receivers
Một Broadcast Receiver là một thành phần không làm gì nhưng nhận và phản ứng
với thông báo broadcast. Nhiều broadcast hình thành trong mã nguồn hệ thống -
ví dụ, thông báo các múi giờ đã thay đổi, pin yếu, một hình ảnh đã được thực
hiện, hoặc để user thay đổi tuỳ chọn ngôn ngữ. Ứng dụng cũng có thể start
broadcast - ví dụ, để cho các ứng dụng khác biết rằng một số dữ liệu đã được tải
về điện thoại và sẵn có cho chúng để sử dụng.
Một ứng dụng có thể có nhiều Broadcast Receiver để đáp ứng với bất kỳ thông
báo nào mà nó coi là quan trọng. Mọi Receiver đề kế thừa từ lớp cơ sở
BroadcastReceiver.
Broadcast Receivers không hiển thị một giao diện người dùng. Tuy nhiên, chúng
có thể bắt đầu một Activity để đáp ứng các thông tin mà chúng nhận được, hoặc
có thể sử dụng các NotificationManager để cảnh báo cho người dùng.
Cẩm Nang Android
Nguyễn Công Tuệ Page 12 of 216
Notifications có thể nhận được sự chú ý của người dùng trong nhiều cách khác
nhau - nhấp nháy đèn, rung thiết bị, chơi một đoạn nhạc. Chúng thường đặt một
icon liên tục trong status bar, người dùng có thể mở để nhận được thông báo.
4.Content Providers
Một Content Provider tạo ra một tập hợp dữ liệu của ứng dụng sẵn có cho các ứng
dụng khác. Các dữ liệu có thể được lưu trữ trong hệ thống tập tin, trong một cơ sở
dữ liệu SQLite, hoặc bằng bất cứ cách khác có ý nghĩa. Content Provider kế thừa
từ lớp cơ sở ContentProvider để thực thi một tập các phương pháp chuẩn cho
phép các ứng dụng khác lấy và lưu trữ dữ liệu của các loại mà nó điều khiển. Tuy
nhiên, các ứng dụng không gọi những phương thức này một cách trực tiếp. Thay
vào đó, chúng sử dụng một đối tượng ContentResolver và gọi các phương thức
của lớp này để thay thế. Một ContentResolver có thể trao đổi với bất kỳ content
provider nào, nó hợp tác với provider để quản lý bất kỳ giao tiếp InterProcess mà
nó tham gia.
Bất cứ khi nào có một yêu cầu cần được xử lý bởi một thành phần cụ thể, Android
đảm bảo rằng tiến trình ứng dụng của thành phần đang chạy, start nó nếu cần
thiết, và một thể hiện (instance) thích hợp của thành phần có sẵn, tạo ra instance
nếu cần thiết.
5.Activating components: intents
Content Providers được kích hoạt khi chúng là đích đến(target) bởi một yêu cầu
từ ContentResolver; 3 thành phần khác: Activities, Services và Broadcast
Receiver được kích hoạt bởi các thông điệp bất đồng bộ gọi là Intents. Một intent
là một đối tượng Intent nắm giữ nội dung thông điệp.
Đối với Activities và Services, nó xác định các hành động được yêu cầu và quy
định các URI của dữ liệu để hoạt động. Ví dụ, nó có thể truyền đạt một yêu cầu
cho một Acitivity để trình bày một hình ảnh đến user hoặc cho user chỉnh sửa một
số văn bản.
Đối với Broadcast Receivers, đối tượng Intent xác định hành động được công bố.
Ví dụ, nó có thể thông báo đến các bên quan tâm rằng các button camera đã được
nhấn.
Các phương thức để kích hoạt mỗi loại components:
Một Activity được launch bằng cách gán một đối tượng Intent làm đối số cho
phương thức Context.startActivity() hoặc
Activity.startActivityForResult(). Acitivity hồi đáp có thể nhìn vào
intent tạo ra nó để được launch bằng cách gọi phương thức getIntent().
Android gọi phương thức onNewIntent() của Activity để gán nó vào các
intents tiếp theo. Nếu một Activity trả về từ một Activity đang starting, gọi
phương thức startActivityForResult() thay vì gọi phương thức startActivity().
Ví dụ, nếu nó bắt đầu một Activity cho phép người dùng chọn một hình ảnh,
nó có thể mong muốn để được trả về các bức ảnh được chọn. Kết quả trả về là
Cẩm Nang Android
Nguyễn Công Tuệ Page 13 of 216
một đối tượng Intent mà được gán vào phương thức onActivityResult()
của Activity.
Một Service được bắt đầu (hoặc hướng dẫn mới được đưa vào một Service
ongoing) bằng cách truyền một đối tượng Intent vào phương thức
Context.startService() . Android gọi phương thức onStart() của
Service và gán đối tượng Intent này vào. Tương tự như vậy, một intent có thể
được gán vào phương thức Context.bindService() để thiết lập một kết nối
liên tục giữa các thành phần gọi và một dịch vụ đích. Dịch vụ này nhận được
đối tượng Intent trong lời gọi onBind(). (Nếu dịch vụ không phải là đang
chạy, bindService() có thể start nó.) Ví dụ, một Activity có thể thiết lập kết
nối với Service playback music đã đề cập trước đó để nó có thể cung cấp cho
người dùng các phương tiện (một giao diện người dùng) nhằm kiểm soát
playback. Activity sẽ gọi phương thức bindService() để thiết lập các kết
nối, và sau đó gọi các phương thức được định nghĩa bởi dịch vụ này để tác
động đến playback.
Một ứng dụng có thể khởi tạo một broadcast bằng cách gán một đối tượng
Intent vào phương thức Context.sendBroadcast(),
Context.sendOrderedBroadcast(), và Context.sendStickyBroadcast()
trong bất kỳ trường hợp nào.
6.Shutting down components
Một Content Provider được kích hoạt chỉ khi nó đáp ứng một yêu cầu từ một đối
tượng ContentResolver. Và Broadcast Receiver được kích hoạt chỉ khi nó đáp ứng
một thông điệp broadcast. Vì vậy, không cần phải kết thúc các thành phần này.
Mặc khác, Activities cung cấp giao diện người dùng. Chúng giao tiếp thường
xuyên và lâu dài với user và có thể vẫn hoạt động ngay cả khi nhàn rỗi, miễn là sự
giao tiếp đó vẫn tiếp tục. Tương tự như vậy, Services cũng có thể tiếp tục chạy
trong một thời gian dài. Vì vậy, Android có các phương thức kết thúc Activities
và Services một cách có trật tự:
Một Activity được kết thúc bằng cách gọi phương thức finish(). Một Activity
có thể kết thúc một Activity khác bằng cách gọi phương thức finishActivity().
Một Service được kết thúc bằng cách gọi phương thức stopSelf() hay
Context.stopService().
Các Component cũng có thể được kết thúc bởi hệ thống khi chúng không còn
được sử dụng hoặc khi Android phải lấy lại bộ nhớ cho nhiều thành phần khác
cần tài nguyên để hoạt động.
7.The manifest file
Trước khi Android có thể bắt đầu một thành phần ứng dụng, nó phải biết thành
phần đó tồn tại. Do đó, các ứng dụng khai báo các thành phần của chúng trong
một file manifest được bundled vào trong Android package, file .apk mà cũng có
code, các file , và tài nguyên của ứng dụng.
Cẩm Nang Android
Nguyễn Công Tuệ Page 14 of 216
Manifest là một file XML có cấu trúc và luôn được đặt tên AndroidManifest.xml
cho mọi ứng dụng.
Nhiệm vụ chính của Manifest là để thông báo cho Android về các component của
ứng dụng. Ví dụ, một Activity có thể được khai báo như sau:
<?xml version="1.0" encoding="utf-8"?>
<manifest . . . >
<application . . . >
<activity android:name="com.example.project.FreneticActivity"
android:icon="@drawable/small_pic.png"
android:label="@string/freneticLabel"
. . . >
</activity>
. . .
</application>
</manifest>
8.Intent filters
Một đối tượng Intent có thể khai báo tường minh hay ngầm định. Nếu nó được
khai báo tường mình thì Android sẽ dễ dàng tìm ra component đó (dựa vào khai
báo trong file manifest), đồng thời kích hoạt nó. Nhưng nếu nó được khai báo
ngầm định, Android phải xác định vị trí của component tốt nhất đáp ứng Intent.
Intent filters sử dụng để thông báo cho Android các loại intent có thể xử lý, và nó
cũng được khai báo trong file manifest.
Ví dụ:
<?xml version="1.0" encoding="utf-8"?>
<manifest . . . >
<application . . . >
<activity android:name="com.example.project.FreneticActivity"
android:icon="@drawable/small_pic.png"
android:label="@string/freneticLabel"
. . . >
<intent-filter . . . >
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter . . . >
<action android:name="com.example.project.BOUNCE" />
<data android:mimeType="image/jpeg" />
<category
android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
. . .
</application>
</manifest>
Cẩm Nang Android
Nguyễn Công Tuệ Page 15 of 216
II.Processes And Threads
Khi lần đầu tiên các component của ứng dụng muốn chạy, Android sẽ bắt đầu một tiến
trình(process) Linux cho nó với một thread đơn để thực thi. Theo mặc định, tất cả các
component của ứng dụng đều chạy trong process và thread. Tuy nhiên, bạn có thể sắp xếp
các thành phần để chạy trên các process khác và có thể sinh ra các thread bổ xung cho
các process đó.
1.Processes
Process là nơi mà một component chạy và được điều khiển trong file manifest.
Các phần tử của component như <activity>, <service>, <receiver> và
<provider>… mỗi phần tử này đều có một thuộc tính process để xác định process
mà thành phần đó nên chạy. Những thuộc tính này được thiết lập để mỗi
component chạy trên chính process của nó hay để một vài component chia sẽ một
process trong khi các thành phần khác thì không. Chúng cũng có thể được thiết
lập để các component của các ứng dụng khác có thể chạy trên cùng một process,
với điều kiện là các ứng dụng phải chia sẽ cùng một ID user Linux. Phần tử
<application> cũng có một thuộc tính process để thiết lập giá trị mặc định cho tất
cả các component.
Tất cả các component được khởi tạo trong main thread của process là xác định, và
hệ thống gọi đến các thành phần được dispatch từ thread đó. Các thread riêng biệt
không được tạo ra cho mỗi instance. Do đó, phương thức để hồi đáp với những lời
gọi - như View.onKeyDown() để report các action của người dùng - luôn luôn
chạy trong main thread của process. Bạn có thể sinh ra các thread riêng biệt cho
các hoạt động chiếm nhiều thời gian như kết nối mạng hay xử lý phép toán phức
tạp…
Android có thể quyết định kết thúc một process tại một số thời điểm, chẳng hạn
như khi bộ nhớ thấp và hay nhận được yêu cầu từ các process khác đang phục vụ
người sử dụng, lúc đó các component ứng dụng đang chạy trong process sẽ bị phá
hủy. Một tiến trình được khởi động lại cho các component đó khi có yêu cầu lại.
Khi quyết định kết thúc các process, Android sẽ xem xét tầm quan trọng của
chúng cho người dùng. Ví dụ, một process với các hoạt động mà không còn nhìn
thấy trên màn hình sẽ dễ dàng tắt hơn là một process với các hoạt động nhìn thấy
được. Do đó, quyết định về kết thúc một process phụ thuộc vào trạng thái của các
thành phần đang chạy trong process đó.
2.Threads
Mặc dù bạn có thể cấu hình cho ứng dụng chạy trên một process đơn, tuy nhiên sẽ
có một số thời điểm bạn cần phải sinh ra một thread mới để làm một số công việc
nền (background). Bởi vì giao diện người dùng phải được đáp ứng một cách
nhanh chóng với người dùng, nên thread mà nắm giữ một activity không được
thực hiện các hành động gây tốn nhiều thời gian như kết nối mạng… Vì vậy, bất
cứ điều gì không được hoàn thành nhanh chóng thì nên giao cho một thread khác.
Threads được tạo ra bằng cách sử dụng các đối tượng chuẩn của JAVA. Ngoài ra,
Android còn cung cấp một số các lớp thuận tiện cho việc quản lý Thread:
Cẩm Nang Android
Nguyễn Công Tuệ Page 16 of 216
o Looper để chạy một vòng lặp message bên trong một thread.
o Handler để xử lý các message.
o HandlerThread để thiết lập một thread với một vòng lặp message.
3.Remote procedure calls
Android có một cơ chế cho các lời gọi thủ tục từ xa (RPCs) - nơi mà một phương
thức được gọi cục bộ, nhưng được thực hiện từ xa (trong một process khác), với
bất kỳ kết quả trả về cho caller.
Android cung cấp một giao diện RPC để thực hiện các lời gọi thủ tục từ xa, các
phương thức của nó được thực hiện một cách đồng bộ, và các phương thức cục bộ
sẽ bị block cho đến khi các phương thức từ xa hoàn tất, ngay cả khi không có giá
trị trả về.
Cơ chế của nó hoạt động như sau: đầu tiên khai báo một giao diện RPC sử dụng
một IDL đơn (interface definition language). Từ khai báo đó, tool aidl sẽ phát
sinh một định nghĩa giao diện JAVA mà phải được sẵn có cho cả process cục bộ
và từ xa, nó chứa 2 lớp inner như mô hình dưới đây:
Các lớp inner đều có code cần thiết để quản lý các lời gọi thủ tục từ xa cho giao
diện mà bạn khai báo với IDL. Cả hai lớp inner đều thực thi giao diện IBinder.
Một trong số đó được sử dụng cục bộ và trong nội bộ của hệ thống; đoạn code bạn
viết có thể bỏ qua nó. Cái khác gọi là Stub, mở rộng của lớp Binder, ngoài code
nội bộ tác động đến các lời gọi IPC, nó còn chứa các khai báo cho các phương
Cẩm Nang Android
Nguyễn Công Tuệ Page 17 of 216
thức trong giao diện RPC mà bạn khai báo. Bạn sẽ kế thừa từ lớp Stub để cài đặt
các phương thức đó.
Thông thường, process từ xa sẽ được quản lý bởi một dịch vụ (vì một dịch vụ có
thể thông báo cho hệ thống về process và các kết nối của nó đến các process
khác). Nó chứa cả các file giao diện được tạo ra bởi công cụ aidl và các lớp con
của Stub thực hiện các phương thức RPC. Clients của dịch vụ chỉ có các tập tin
giao diện được tạo ra bởi công cụ aidl.
III.Component Lifecycles
Vòng đời của các component của ứng dụng bắt đầu khi Android khởi tạo nó để hồi đáp
đến các Intent và kết thúc khi một instance bị phá hủy. Trong phần này, chúng ta sẽ tìm
hiểu vòng đời của các component của Android như sau: Activity, Service, Broadcast
Receiver.
1.Activity lifecycle
Một Activity thường rơi vào một trong 3 trạng thái sau đây:
active hay running khi nó đang foreground trên màn hình, đó là Activity đang
focus đến các action của người dùng.
paused nếu mất focus nhưng vẫn còn visible đến người dùng. Đó là, một Activity
khác nằm trên top của nó hay nó làm transparent hoặc không hiển thị full màn
hình. Khi ở trạng thái paused thì Activity vẫn còn sống (nó vẫn duy trì tất cả các
trạng thái và thông tin) nhưng có thể bị kết thúc bởi hệ thống trong trường hợp bộ
nhớ thấp.
stopped nếu nó bị che khuất hoàn toàn bởi các Activity khác. Nó vẫn còn duy trì
tất cả các thông tin trạng thái và member. Tuy nhiên, nó không còn visible đến
user và cửa sổ của nó bị ẩn và nó thường được kết thúc khi bộ nhớ cần thiết ở
những nơi khác.
Nếu một Activity đang ở trạng thái paused hay stopped, hệ thống có thể drop nó khỏi bộ
nhớ bằng cách hoặc hỏi nó để kết thúc(gọi phương thức finish() của nó) hoặc chỉ đơn
giãn kill process của nó. Khi nó được hiển thị trở lại với user, nó phải restart và restore
trạng thái trước đó của nó.
Một Activity có thể chuyển từ trạng thái này sang trạng thái khác bằng cách gọi các
phương thức sau đây:
void onCreate(Bundle savedInstanceState)
void onStart()
void onRestart()
void onResume()
void onPause()
void onStop()
void onDestroy()
Tất cả các phương thức này đều có thể được override để thực hiện các công việc phù hợp
khi thay đổi trạng thái. Mọi Activity đều phải cài đặt phương thức onCreate() để tạo ra
Cẩm Nang Android
Nguyễn Công Tuệ Page 18 of 216
các thiết lập ban đầu khi đối tượng được khởi tạo lần đầu tiên. Ngoài ra, bạn có thể cài
đặt phương thức onPause() để commit các dữ liệu thay đổi và chuẩn bị để dừng các tương
tác với người dùng.
Bảy phương thức trên định nghĩa toàn bộ vòng đời của một Activity, có 3 vòng lặp mà
bạn có thể điều khiển để thực thi chúng:
Entire lifetime xảy ra từ phương thức onCreate() đến onDestroy(). Một Activity
thực hiện tất cả các công việc thiết lập ban đầu của nó của trạng thái ―global‖
trong phương thức onCreate() và giải phóng tất cả các tài nguyên đang chiếm
dụng trong phương thức onDestroy(). Ví dụ, nếu cần một thread chạy background
để download dữ liệu từ network, nó có thể tạo ra thread đó trong phương thức
onCreate() và dừng thread đó trong phương thức onDestroy().
Visible lifetime xảy ra từ phương thức onStart() đến phương thức onStop().
Trong suốt thời gian này, user có thể nhìn thấy Activity trên màn hình mặc dù có
thể nó không foreground hay đang tương tác với user. Giữa hai phương thức này,
bạn có thể duy trì nguồn tài nguyên cần thiết để hiển thị Activity đến user. Ví dụ,
bạn có thể đăng ký một BroadcastReceiver trong phương thức onStart() để giám
sát những thay đổi giao diện, và hủy đăng ký nó trong phương thức onStop() khi
user không còn có thể nhìn thấy những gì bạn đang hiển thị. Các phương thức
onStart() và onStop() có thể được gọi nhiều lần, để thiết lập Activity visible hay
hide đến người dùng.
Foreground lifetime xảy ra từ phương thức onResume() đến phương thức
onPause(). Trong thời gian này, Activity ở phía trước tất cả các Activity khác trên
màn hình và nó tương tác với người sử dụng. Một Activity có thể thường xuyên
chuyển đổi giữa trạng thái resume và pause - ví dụ, onPause() được gọi khi thiết
bị sleep hoặc khi một Activity mới được bắt đầu, onResume() được gọi khi một
Activity trả về hay Intent mới được deliver.
Mô hình dưới đây mô tả lifetime của một Activity:
Cẩm Nang Android
Nguyễn Công Tuệ Page 19 of 216
Bảng dưới đây mô tả chi tiết các phương thức trên:
Method
Description
Killable?
Next
onCreate()
Được gọi khi Activity lần đầu tiên được tạo
ra. Đây là nơi mà bạn nên thực hiện các công
No
onStart()
Cẩm Nang Android
Nguyễn Công Tuệ Page 20 of 216
việc thiết lập thông thường, như: tạo View,
bind dữ liệu vào List… Phương thức này
được gán thông qua đối tượng Bundle được
chứa trong trạng thái của Activity trước đó.
Theo sau nó là phương thức onStart().
onRestart()
Được gọi sau khi Activity đã được stop, ngay
trước khi nó được restart lại. Theo sau nó
luôn là phương thức onStart().
No
onStart()
onStart()
Được gọi trước khi Activity visible đến user.
Theo sau là phương thức onResume() nếu
Activity chuyển sang foreground, hoặc
onStop() nếu nó ẩn đến user.
No
onResume()
hoặc
onStop()
onResume()
Được gọi trước khi Activity bắt đầu tương tác
với user. Tại thời điểm này, Activity ở top
của activity stack. Theo sau nó là phương
thức onPause().
No
onPause()
onPause()
Được gọi khi hệ thống bắt đầu resume một
Activity khác. Thông thường, phương thức
này sử dụng để commit dữ liệu chưa được
save vào persistent data, dừng các chuyển
động và các công việc khác làm tiêu tốn
CPU… Các xử lý trong phương thức này phải
được trả về một cách nhanh chóng bởi vì
Activity tiếp theo sẽ không resume cho đến
khi phương thức này trả về. Theo sau nó là
phương thức onResume() nếu Activity trả về
trở lại để visible đến user, hoặc onStop() nếu
nó invisible đến user.
Yes
onResume()
hoặc
onStop()
onStop()
Được gọi khi Activity không còn visible đến
user. Điều này xảy ra có thể là do Activity đã
bị phá hủy hay do một Activity khác( activity
này có thể đang tồn tại hay tạo mới) đã được
resume và đang cover nó. Theo sau nó là
phương thức onRestart() nếu Activity đang
trở lại để tương tác với user, hoặc phương
thức onDestroy() nếu Activity go away.
Yes
onRestart()
hoặc
onDestroy()
onDestroy()
Được gọi trước khi Activity bị phá hủy. Đây
là lời goi cuối cùng mà một Activity sẽ gọi.
Nó có thể được gọi do nó đang kết thúc(gọi
phương thức finish() lên nó) hay do hệ thống
tạm thởi phá hủy instance này của Activity để
tiết kiệm không gian bộ nhớ. Bạn có thể phân
biệt giữa hai kịch bản với phương thức
isFinishing().
Yes
nothing
Cẩm Nang Android
Nguyễn Công Tuệ Page 21 of 216
Trong bản trên, cột ―Killable after?‖ cho biết rằng hệ thống có thể hoặc không thể kill
process đang nắm giữ (host) Activity tại bất kỳ thời điểm nào sau khi phương thức trả về,
mà không cần phải thực hiện các dòng code khác của activity.
Ba phương pháp được đánh dấu "Yes": onPause(), onStop(), và onDestroy(). Một khi
activity được tạo ra, onPause() là phương thức cuối cùng mà để đảm bảo rằng nó được
gọi trước khi process có thể bị kill, nếu hệ thống phải phục hồi bộ nhớ trong trường hợp
khẩn cấp, thì onStop() và onDestroy() có thể không được gọi. Do đó, bạn nên sử dụng
onPause() để ghi các dữ liệu persistent quan trọng (như khi user chỉnh sửa) để lưu trữ.
Tuy nhiên, bạn nên chọn lọc về những thông tin được giữ lại trong onPause(), bởi vì bất
kỳ các thủ tục blocking trong phương thức này sẽ block việc chuyển đổi sang activity tiếp
theo và làm chậm user experience.
Các phương thức được đánh dấu "No" trong cột ―Killable‖ bảo vệ process nắm giữ
activity đang bị kill kể từ thời điểm chúng được gọi. Vì vậy, một activity là killable từ
thời điểm onPause() trả về cho đến thời điểm onResume() được gọi. Nó sẽ không phải
killable một lần nữa cho đến khi onPause() được gọi lần nữa và trả về.
Lưu ý: Một activity không phải là "killable" theo định nghĩa này trong bảng 1 vẫn có thể
bị kill bởi hệ thống, nhưng điều đó sẽ xảy ra chỉ trong hoàn cảnh khi không có recourse.
Một activity có thể bị kill được thảo luận nhiều hơn trong tài liệu Processes and
Threading.
1.1.Saving activity state
Khi hệ thống tắt một Activity để bảo toàn bộ nhớ, user mong muốn lưu trữ trạng
thái của nó để sử dụng sau này. Để làm được điều đó, bạn phải cài đặt phương
thức onSaveInstanceState() cho một Activity, Android có thể gọi phương thức
này trước khi phương thức onPause() được gọi. Khi Activity được start lại,
phương thức onRestoreInstanceState() để lấy lại trạng thái trước đó.
Không giống như phương thức onPause(), cả phương thức onSaveInstanceState()
và onRestoreInstanceState() không có lifecycle, và chúng không phải lúc nào
cũng được gọi. Ví dụ, Android gọi phương thức onSaveInstanceState() trước khi
Activity trở nên dễ bị phá hủy bởi hệ thống nhưng nó sẽ không được gọi khi
instance của Activity đang bị phá hủy bởi người dùng(nhấn phím Back). Trong
trường hợp này, user không mong muốn trở lại Activity này nên không có lý do gì
để lưu trạng thái của nó.
1.2.Coordinating activities
Khi một Activity start trên một Activity khác, sẽ có một Activity pause hay stop, cái kia
thì start up, do đó, bạn cần sắp xếp (coordinate) các Activity này. Thứ tự của lifecycle
callback cũng cần được định nghĩa, cụ thể khi có 2 activity trên cùng một process:
Phương thức onPause() của Activity hiện tại được gọi
Tiếp theo, các phương thức onCreate(), onStart() và onResume() của Activity
starting được gọi theo tuần tự.
Sau đó, nếu Activity starting này không còn visible đến user, phương thức
onStop() của nó được gọi.
Cẩm Nang Android
Nguyễn Công Tuệ Page 22 of 216
2.Service lifecycle
Một Service có thể được sử dụng theo 2 cách:
Nó có thể được start và được phép chạy cho đến khi ai đó dừng nó hay nó tự dừng
chính nó. Ở chế độ này, nó được start bằng cách gọi phương thức
Context.startService() và dừng bằng cách gọi phương thức Context.stopService().
Nó có thể dừng chính nó bằng cách gọi phương thức Context.stopSelf() hay
Context.stopSelfResult().
Nó có thể hoạt động bằng cách sử dụng giao diện mà nó định nghĩa và export.
Client thiết lập kết nối đến đối tượng Service và sử dụng kết nối đó để gọi dịch
vụ. Kết nối này được tạo ra bằng cách gọi phương thức Context.bindService() và
được đóng bằng cách gọi phương thức Context.unbindService(). Nhiều client có
thể bind cùng một đối tượng Service. Nếu service chưa được launch, phương thức
bindService() có thể khởi chạy nó một cách tùy chọn.
Hai chế độ này không hoàn toàn tách biệt nhau. Bạn có thể bind một dịch vụ đã được bắt
đầu với startService(). Ví dụ, một dịch vụ nhạc nền có thể được bắt đầu bằng cách gọi
startService() với một đối tượng Intent xác định music để chơi. Sau đó, khi user muốn
thực hiện một số kiểm soát đối với các player hoặc nhận được thông tin về các bài hát
hiện hành, một Activity sẽ thiết lập kết nối với dịch vụ bằng cách gọi bindService().
Trong trường hợp như thế , stopService() sẽ không thực sự dừng dịch vụ cho đến khi
binding cuối cùng được đóng.
Giống như Activity, một Service cũng có các phương thức lifectycle mà bạn có thể cài
đặt để để kiểm soát sự thay đổi trạng thái. Tuy nhiên, nó chỉ có 3 phương thức:
void onCreate()
void onStart(Intent intent)
void onDestroy()
Có 2 vòng lặp trong lifecycle của Service:
Entire lifecycle xảy ra từ phương thức onCreate() đến phương thức onDestroy().
Một Service sẽ thực hiện các thiết lập ban đầu trong phương thức onCreate() và
giải phóng tất cả các tài nguyên trong phương thức onDestroy(). Ví dụ, một
service music playback có thể tạo ra thread để music có thể được play trong
onCreate(), và sau đó dừng thread đó trong phương thức onDestroy().
Active lifecycle bắt đầu với lời goi onStart(). Phương thức này được giao cho đối
tượng Intent đã được gán trong phương thức startService(). Service music sẽ mở
đối tượng Intent để discover music và bắt đầu playback.
Các phương thức onCreate() và onDestroy() được gọi cho tất cả các Service, dù cho
chúng được bắt đầu với phương thức Context.startService() hay Context.bindService().
Tuy nhiên, phương thức onStart() chỉ được gọi cho các Service bắt đầu bởi phương thức
startService().
Nếu một Service cho phép các Service khác bind vào nó, bạn phải cài đặt thêm các
phương thức callback sau đây:
IBinder onBind(Intent intent)
boolean onUnbind(Intent intent)
Cẩm Nang Android
Nguyễn Công Tuệ Page 23 of 216
void onRebind(Intent intent)
Mô hình dưới đây mô tả các phương thức callback cho một Service.
3.Broadcast receiver lifecylce
Một Broadcast receiver có một phương thức callback đơn:
void onReceive(Context curContext, Intent broadcastMsg)
Khi một message broadcast đến với receiver, Android gọi phương thức
onReceive() và gán nó vào đối tượng Intent có chứa các message. Broadcast
receiver chỉ được xem là active chỉ khi nó đang thực thi trên phương thức này.
Khi phương thức onReceive() trả về, nó chuyển sang trạng thái inactive.
Cẩm Nang Android
Nguyễn Công Tuệ Page 24 of 216
Một process với một Broadcast receiver ở trạng thái active sẽ được bảo vệ nếu nó
bị kill. Ngược lại, nếu nó đang ở trạng thái inactive thì các component của nó có
thể bị kill bởi hệ thống tại bất kỳ thời điểm nào, chẳng hạn như khi bộ nhớ mà nó
chiếm dụng cần thiết cho các process khác.
Đây là một vấn đề khi hồi đáp với message broadcast gây tiêu tốn nhiều thời gian.
Do đó, nên thực hiện trong một thread mới tách biệt, tránh xác main thread nơi
mà các thành phần khác của UI đang chạy. Nếu onReceive() phát sinh ra một
thread mới và sau đó trả về thì toàn bộ process(bao gồm cả thread mới) được xem
là inactive (ngoại trừ các component của ứng dụng khác được active trong
process) và có nguy cơ bị kill. Giải pháp cho vấn đề này là bắt đầu một dịch vụ và
để cho dịch vụ thực hiện công việc của mình, lúc đó hệ thống sẽ biết là nó vẫn
active trong process.
4.Processes and lifecycles
Hệ thống Android luôn cố gắng để duy trì process của ứng dụng càng lâu càng tốt, nhưng
cuối cùng nó vẫn phải loại bỏ các process cũ khi bộ nhớ cấp phát hạn hẹp. Để xác định
xem process này nên giữ lại và process nào nên kill, Android đặt mỗi process vào một
―cấp bậc quan trọng (hierarchy inportance)‖ dựa trên các component đang chạy trên đó
và các trạng thái của các component đó. Các tiến trình với tầm quan trọng thấp nhất sẽ bị
loại bỏ đầu tiên, sau đó sẽ đến các mức thấp tiếp theo. Có 5 level trong hierarchy.
4.1.Foreground process
Đó là tiến trình mà user đang làm việc hiện tại. Một process được xem là foreground nếu
nó thõa mãn một trong các điều kiện sau đây:
Nó đang chạy trên một Activity mà user đang tương tác(phương thức onResume()
của đối tượng Activity này đã được gọi).
Nó nắm giữ (host) đến một service mà service này có ràng buộc với activity mà
user đang tương tác.
Nó có một đối tượng Service mà đối tượng này đang thực thi một trong các
phương thức callback lifecycle của nó (onCreate(), onStart() hay onDestroy()).
Nó có một đối tượng BroadcastReceiver đang thực thi phương thức onReceive().
Chỉ có một vài foreground process sẽ tồn tại ở bất kỳ thời điểm nào. Chúng chỉ được kill
như là một phương án cuối cùng, đó là bộ nhớ còn lại quá bé và không thể tiếp tục chạy.
Nói chung, tại thời điểm đó, thiết bị bị phân mãnh bộ nhớ nên nó phải kill một vài
foreground process nhằm giữ cho giao diện người dùng được đáp ứng.
4.2.Visible process
Là process không có bất kỳ một component foreground nào nhưng vẫn còn ảnh hưởng
đến những gì mà user thấy trên màn hình. Một process được xem là visible nếu nó thõa
mãn một trong các điều kiện sau:
Nó host một activity không ở foreground, nhưng nó vẫn còn hiển thị đến
user(phương thức onPause() của nó đã được gọi). Ví dụ, điều này xảy ra khi
Cẩm Nang Android
Nguyễn Công Tuệ Page 25 of 216
foreground activity là một dialog và cho phép các activity khác có thể nhìn thấy ở
sau nó.
Nó host một service có ràng buộc với một visible activity.
Một visible process cũng rất quan trọng và nó chỉ được kill trong trường hợp nhằm đảm
bảo cho các foreground process vẫn chạy bình thường.
4.3.Service process
Đó là một process đang chạy trong một service đã được bắt đầu với phương thức
startService(). Service process không visible đến user, nhưng nó làm các công việc mà
user quan tâm đến (chẳng hạn như download dữ liệu từ mạng), nên hệ thống đảm bảo để
chạy chúng trừ khi không đủ bộ nhớ cho các process foreground và visible.
4.4.Bacground process
Là process nắm giữ một Activity mà hiện tại không được hiển thị đến user (phương thức
onStop() của đối tượng Activity đã được gọi). Loại process này không tác động trực tiếp
đến user, vì vậy chúng có thể bị kill ở bất kỳ thời điểm nào để giải phóng bộ nhớ sử dụng
cho các process foreground, visible và service. Thông thường, có nhiều background
process được chạy, nên chúng được lưu trong một danh sách LRU(least recently used) để
đảm bảo rằng process với activity mà user lần cuối cùng nhìn thấy bị kill.
4.5.Empty process
Là process không nắm giữ bất kỳ một component active nào của ứng dụng. Process này
được sử dụng như là bộ nhớ ―cache‖ để cải thiện thời gian khởi động cho lần tiếp theo mà
một một component cần chạy. Hệ thống thường kill các process này theo thứ tự nhằm cân
đối tài nguyên hệ thống giữa process caches và kernel caches.
Lưu ý Android sắp xếp một process ở mức cao nhất có thể dựa trên tầm quan trọng của
các component đang active hiện tại trong process. Ví dụ, một process host một service và
một activity visible, process đó sẽ được sắp xếp trở thành visible process chứ không phải
là service process. Ngoài ra, sự sắp xếp level của process có thể tăng lên bởi vì các
process khác phụ thuộc vào nó. Một process đang phục vụ một process khác sẽ không
bao giờ có thể xếp hạng thấp hơn process mà nó phục vụ. Ví dụ, nếu một content
provider trong process A đang phục vụ client trong process B, hay nếu một service trong
process A có ràng buộc với một component trong process B thì process A được xem tối
thiểu quan trọng như B.