Thread trong lập trình Android

(Zmikisoft.com) – Thread trong lập trình Android.
Thread là một khái niệm, cũng là một thành phần gần như không thể thiếu trong bất kỳ một ứng dụng bất kỳ của mọi hệ điều hành. Trong bài hôm nay chúng ta sẽ tìm hiểu về khái niệm thread trong hệ điều hành Android.

VỚI ỨNG DỤNG:

Khi một ứng dụng được khởi chạy, hệ thống sẽ tạo một luồng thực thi cho ứng dụng, gọi là luồng “chính.” Luồng này rất quan trọng bởi nó phụ trách phân phối các sự kiện tới những widget giao diện người dùng phù hợp, bao gồm các sự kiện vẽ. Nó cũng là luồng mà trong đó ứng dụng của bạn tương tác với các thành phần từ bộ công cụ UI của Android (các thành phần từ các gói android.widgetandroid.view). Như vậy, luồng chính đôi khi cũng được gọi là luồng UI.

Hệ thống không tạo một luồng riêng cho từng thực thể của thành phần. Tất cả thành phần chạy trong cùng tiến trình đều được khởi tạo trong luồng UI, và các lệnh gọi của hệ thống tới từng thành phần được phân phối từ luồng đó. Hệ quả là các phương pháp hồi đáp lại lệnh gọi lại của hệ thống (chẳng hạn như onKeyDown() để báo cáo hành động của người dùng hoặc một phương pháp gọi lại vòng đời) sẽ luôn chạy trong luồng UI của tiến trình.

Ví dụ, khi người dùng chạm vào một nút trên màn hình, luồng UI của ứng dụng của bạn sẽ phân phối sự kiện chạm tới widget, đến lượt mình, widget sẽ đặt trạng thái được nhấn và đăng một yêu cầu vô hiệu hóa tới hàng đợi sự kiện. Luồng UI loại yêu cầu khỏi hàng đợi và thông báo với widget rằng nó nên tự vẽ lại .

Khi ứng dụng của bạn thực hiện công việc nặng để hồi đáp tương tác của người dùng, mô hình luồng đơn nhất này có thể dẫn đến hiệu năng kém trừ khi bạn triển khai ứng dụng của mình một cách phù hợp. Cụ thể, nếu mọi thứ đang xảy ra trong luồng UI, việc thực hiện những thao tác kéo dài như truy cập mạng hay truy vấn cơ sở dữ liệu sẽ chặn toàn bộ UI. Khi luồng bị chặn, không sự kiện nào có thể được phân phối, bao gồm cả sự kiện vẽ. Từ phương diện của người dùng, ứng dụng có vẻ như đang bị treo. Thậm chí tệ hơn, nếu luồng UI bị chặn trong lâu hơn vài giây (hiện tại là khoảng 5 giây), người dùng sẽ được hiển thị hộp thoại không phổ biến “ứng dụng không phản hồi” (ANR). Khi đó, người dùng có thể quyết định thoát ứng dụng của mình và gỡ cài đặt nó nếu họ không thoải mái.

Ngoài ra, bộ công cụ UI của Android không an toàn với luồng. Vì vậy, bạn không được thao tác UI của mình từ một luồng trình thực hiện—bạn phải thực hiện tất cả thao tác đối với giao diện người dùng của mình từ luồng UI. Vì vậy, có hai quy tắc đơn giản đối với mô hình luồng đơn lẻ của Android:

  1. Không được chặn luồng UI
  2. Không được truy cập bộ công cụ UI của Android từ bên ngoài luồng UI

CÁCH THỰC HIỆN:

Để thực hiện thao tác luồng, và nhớ rằng phải đảm bảo đúng 2 quy tắc 1 và 2 như trên. Một số phương pháp được đưa ra sử dụng:

  1. Activity.runOnUiThread(Runnable)
  2. View.post(Runnable)
  3. View.postDelayed(Runnable, long)
  4.  Thread – handle
  5.  Asyntask
  6. Sử dụng kết nối các thành phần như Bindservice
  7. Sử dụng Broadcast để gửi tín hiệu từ workerThread

Một ví dụ về View.post

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
            mImageView.post(new Runnable() {
                public void run() {
                    mImageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();
}

Ví dụ về Asyntask 

public void onClick(View v) {
    new DownloadImageTask().execute("http://example.com/image.png");
}

private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    /** The system calls this to perform work in a worker thread and
      * delivers it the parameters given to AsyncTask.execute() */
    protected Bitmap doInBackground(String... urls) {
        return loadImageFromNetwork(urls[0]);
    }

    /** The system calls this to perform work in the UI thread and delivers
      * the result from doInBackground() */
    protected void onPostExecute(Bitmap result) {
        mImageView.setImageBitmap(result);
    }
}

Trong việc sử dụng Thread chúng ta cần phải rất cẩn thận, và tuỳ tình huống mà áp dụng cách thức phù hợp. Nhưng cho dù sử dụng cách nào đi chăng nữa vẫn phải đảm bảo việc đó đảm bảo không vị phạm 2 quy định như ở phần 1.

Khóa học lập trình Android
Khóa học lập trình Java
Khóa học lập trình iOS
Khóa học lập trình Objective-C/Swift