I. Multi-Thread
1: Thread là gì?
Thread là một luồng của một chương trình đang chạy. Một chương trình đang chay thường sẽ có 1 luồng chính chủ đạo và có thể tạo ra được nhiều các luồng khác chạy xung quanh để phục vụ cho luồng chính đó. Các luồng này có thể chạy song song với nhau. Mỗi luồng đều có call stack riêng với các phương thức được gọi, tham số và biến địa phương của chúng.
2: Cách tạo 1 thread?
Chúng ta có 2 cách chính để tạo 1 thread: Tạo một lớp thread mới kế thừa từ lớp Thread.
1 2 3 4 5 6 7 8 | public class NewThread extends Thread{ public void run() { print(“Hello”) } } |
Tạo một biến mới của lớp Thread với đối tượng Runnable
1 2 3 4 5 6 7 | Thread background = new Thread(new Runnable() { public void run() { print(“Hello”) } } |
Và để chạy bất kỳ một thread nào ta đều phải gọi phương thức start();
1 2 3 | background.start() |
3. Tác dụng của thread trong 1 chương trình
Các luồng có thể dùng chung tài nguyên của tiến trình để thực hiện các thao tác cần thiết.
Có thể tách các nhiệm vụ của ứng dụng ra thành các công việc nhỏ cho từng luồng xử lý.
Sử dụng luồng ta có thể thực thi song song các công việc 1 lúc một cách thực sự.
Sử dụng thread sẽ làm cho chương trình chạy một cách trơn chu hơn, nhanh hơn chứ ko phải đợi chờ lâu.
Bên cạnh đó ta cũng gặp một số vấn đề về việc xảy ra deadlock khi có nhiều luồng cùng sử dụng 1 tài nguyên cố định. Hoặc thay đổi tài nguyên đó một cách không có kiểm soát sẽ dẫn đến sai lệch kết quả.
4. Liên kết giữa thread chính với thread phụ
Trong android, các thread tương tác với nhau thông qua các đối tượng được gọi là Handler. Khi một tiến trình được tạo cho một ứng dụng, luồng chính của nó được dành riêng để chạy một message queue, queue này quản lý các đối tượng bậc cao của ứng dụng (activity, intent receiver, ..) và các cửa sổ mà chúng tạo ra.
Khi ta tạo một Handler mới, nó được gắn với message queue của thread tạo ra nó – từ đó trở đi, nó sẽ gửi các message và các runnable tới message queue đó và thực thi chúng khi chúng ra khỏi message queue.
Nhiệm vụ chính của Handler là: xếp lịch cho các message và runnable cần được thực thi vào thời điểm nào đó trong tương tai, và xếp hàng một action cần thực hiện tại một thread khác Mỗi luồng phụ cần liên lạc với luồng chính thì phải yêu cầu một message token bằng cách dùng phương thức obtainMessage().
Khi đã lấy được token, thread phụ đó dùng phương thức sendMessage() để ghi dữ liệu vào token và gắn nó vào message queue của Handler.
VD:
1 2 3 4 5 6 | Handler handler = new Handler() String data = “Messages 1” Message msg = handler.obtainMessage(1, (String)data); handler.sendMessage(msg); |
Handler liên tục xử lý các message mới được gửi tới thread chính bằng phương thức handleMessage() Mỗi message được lấy ra từ queue của thread có thể trả về dữ liệu cho thread chính hoặc yêu cầu chạy các đối tượng runnable qua phương thức post().
Ứng dụng demo hoạt động của thread tại : https://github.com/banlv54/ThreadAndroid
ứng dụng có màn hình chính hiển thi một số int random từ 1-100 do một thread phụ tạo ra và gửi về cho thread chính. Việc này được thực hiện liên tục cho đến khi processBar đặt mức 60. Mỗi lần gửi dữ liệu về thì ProgressBar được tăng lên 2.
II. Service
1. Service là gì?
Service là một thành phần ứng dụng chạy ở chế độ nền, không tương tác với người sử dụng, trong một thời gian không xác định thời gian.
Điều này có nghĩa rằng, nếu service của bạn sẽ làm bất cứ CPU chuyên sâu (như chơi nhạc MP3) hoặc ngăn chặn (như mạng) hoạt động, nó sẽ sinh ra tiến trình của mình, trong đó để làm công việc đó.
Mỗi Service phải có một khai báo tương ứng trong AndroidManifest.xml của gói của nó.
Dịch vụ có thể được bắt đầu với Context.startService () và Context.bindService ().
Service có thể được khởi tạo nhiều lần Context.startService () nhưng sẽ được ngừng lại chỉ với một lần gọi Context.stopService () hoặc stopSelf ().
Một Service có thể được bắt đầu và cho phép chạy cho đến khi một người nào đó hoặc chính nó tự dừng lại.
Chỉ có một stopService () gọi là cần thiết để dừng dịch vụ, không có vấn đề bao nhiêu lần startService () được gọi.
2. Các tạo và khởi chạy service
Giả sử hoạt động chính MyService muốn tương tác với một dịch vụ gọi là MyService1. Các hoạt động chính là chịu trách nhiệm về các công việc sau:
Khởi tạo và start MyService1.
1 2 3 4 5 | Intent intentMyService = new Intent(this, MyService1.class); Service myService = startService(intentMyService); |
Định nghĩa IntentFilter và đăng ký BroadcastReceiver
1 2 3 4 5 6 | IntentFilter mainFilter = new IntentFilter("matos.action.GOSERVICE3"); BroadcastReceiver receiver = new MyMainLocalReceiver(); registerReceiver(receiver, mainFilter); |
Implement và override phương thức onReceive
1 2 3 4 | public void onReceive(Context localContext, Intent callerIntent) |
Dừng hoạt động của Service:
1 2 3 4 | stopService(new Intent(intentMyService) ); |
Sử dụng phương pháp onDestroy của dịch vụ để đảm bảo rằng tất cả các hoạt động của nó chạy được chấm dứt và hủy đăng ký dịch vụ
1 2 3 4 | myService.onDestroy() unregisterReceiver(receiver); |
Techtalk via viblo