Android Threads, Handlers AsyncTask. Bài viết này mô tả cách sử dụng của tiến trình bất đồng bộ trong ứng dụng android (asynchronous ). Bao gồm làm thế nào để xử lý vòng đời ứng dụng với Threads. Được dựa trên Android Studio.
1. Background processing in Android
1.1. Why using concurrency?
Theo mặc định, code được chạy trong main thread. Do đó mỗi câu lệnh được thực hiện theo trình tự. Nếu bạn thực hiện một hoạt động với thời gian lâu, ứng dụng sẽ bị khóa cho đến khi hoạt động đó đã kết thúc.
Để cung cấp trải nghiệm người dùng tốt, tất cả các hoạt động chạy chậm và tốn thời gian trong ứng dụng Android sẽ chạy bất đồng bộ. Các hoạt có thể ví dụ như truy cập mạng, tải tập tin và cơ sở dữ liệu và tính toán phức tạp.
1.2. Main thread
Android thay đổi giao diện người dùng và xử lý các dữ liệu đầu vào từ một single thread, được gọi là main thread. Android thu thập tất cả sự kiện trong Thread đưa lên hàng đợi và xử lý hàng đợi này qua lớp Looper.
1.3. Threading in Android
Android hỗ trợ việc sử dụng lớp Thread để thực hiện quá trình không đồng bộ. Android cũng cung cấp gói java.util.concurrent
để thực hiện một hoạt động trong background. Ví dụ, bằng cách sử dụng các lớp ThreadPools
và Executor
.
Nếu bạn cần phải cập nhật giao diện người dùng từ một new Thread, bạn cần đồng bộ với main thread. Do những hạn chế này, nhà phát triển Android thường sử dụng một cấu trúc riêng của Android.
Android cung cấp các cấu trúc bổ sung để xử lý đồng thời so với Java chuẩn.
Bạn có thể sử dụng lớp android.os.Handler
hoặc các lớp AsyncTasks
. Cách tiếp cận hay hơn dựa trên lớp Loader
, giữ lại các fragment và service.
1.4. Providing feedback to a long running operation
Nếu bạn đang thực hiện một hoạt động trong thời gian dài, nó là cách tốt để cung cấp thông tin phản hồi cho người sử dụng.
Bạn có thể cung cấp phản hồi về tiến trình thông qua action bar, ví dụ như thông qua action view. Ngoài ra, bạn có thể sử dụng một ProgressBar
trong bộ layout của bạn thiết lập để hiển thị và cập nhật nó cho người dùng.
2. Handler
2.1. Purpose of the Handler class
Một đối tượng Handler
đăng ký chính nó với main thread
nó được tạo ra. Nó cung cấp một kênh để gửi dữ liệu cho thread này. Ví dụ: nếu bạn tạo new Handler
instance trong phương thức onCreate () của activity , nó có thể được dùng để đẩy dữ liệu lên main thread. Dữ liệu có thể được đẩy qua lớp Handler có thể là một instance của lớp Message hoặc Runnable. Handler rất hữu ích nếu bạn muốn đẩy nhiều lần dữ liệu vào mainThread.
2.2. Creating and reusing instances of Handlers
Để triển khai một lớp handler subclass và ghi đè lên handleMessage (
) để xử lý các message. Bạn có thể gửi message đến nó thông qua sendMessage (Message) hoặc thông qua phương thức sendEmptyMessage ()
. Sử dụng phương thức post ()
để gửi một Runnable đến nó.
Để tránh việc tạo đối tượng, bạn cũng có thể sử dụng lại đối tượng Handler hiện có trong actiity hiện tại.
// Reuse existing handler if you don't // have to override the message processing handler = getWindow().getDecorView().getHandler();
Class View cho phép bạn gửi các đối tượng kiểu Runnable thông qua phương thức post ().
2.3. Example
Đoạn code sau cho thấy việc sử dụng một handle từ một view.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ProgressBar android:id="@+id/progressBar1" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:indeterminate="false" android:max="10" android:padding="4dip" > </ProgressBar> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" > </TextView> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="startProgress" android:text="Start Progress" > </Button> </LinearLayout>
Với đoạn code sau, ProgressBar được cập nhật khi người dùng nhấn button.
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.ProgressBar; import android.widget.TextView; public class ProgressTestActivity extends Activity { private ProgressBar progress; private TextView text; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); progress = (ProgressBar) findViewById(R.id.progressBar1); text = (TextView) findViewById(R.id.textView1); } public void startProgress(View view) { // do something long Runnable runnable = new Runnable() { @Override public void run() { for (int i = 0; i <= 10; i++) { final int value = i; doFakeWork(); progress.post(new Runnable() { @Override public void run() { text.setText("Updating"); progress.setProgress(value); } }); } } }; new Thread(runnable).start(); } // Simulating something timeconsuming private void doFakeWork() { SystemClock.sleep(5000);e.printStackTrace(); } }
3. AsyncTask
3.1. Purpose of the AsyncTask class
Lớp AsyncTask cho phép bạn chạy trong nền và đồng bộ lại với main thread. Nó cũng báo cáo tiến độ của các nhiệm vụ đang chạy. AsyncTasks nên được sử dụng cho hoạt động nền ngắn cần cập nhật giao diện người dùng.
3.2. Using the AsyncTask class
Để sử dụng AsyncTask
bạn phải phân lớp nó. AsyncTask
sử dụng generics và varargs. Các tham số là AsyncTask <TypeOfVarArgParams, ProgressValue, ResultValue>
.
Một AsyncTask
được bắt đầu thông qua phương thức execute ()
. Phương thức execute ()
này gọi phương thức doInBackground () và onPostExecute ()
.
TypeOfVarArgParams được đưa vào phương thức doInBackground ()
làm input.
ProgressValue được sử dụng cho thông tin tiến trình và ResultValue phải được trả lại từ phương thức doInBackground ()
. Tham số này được chuyển tới onPostExecute ()
dưới dạng một tham số.
Phương pháp doInBackground () nên được thực hiện trong background thread. Phương pháp này chạy tự động trong một Thread riêng biệt.
Phương thức onPostExecute ()
synchronizes với giao diện người dùng cho phép cập nhật giao diện. Được gọi tới khi phương thức doInBackground ()
kết thúc.
3.3. Example: AsyncTask
Ví dụ minh họa cách sử dụng lớp AsyncTask để tải nội dung của một trang web.
Thêmandroid.permission.INTERNET
vào trong AndroidManifest.xml file.
Layout:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/readWebpage" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="onClick" android:text="Load Webpage" > </Button> <TextView android:id="@+id/TextView01" android:layout_width="match_parent" android:layout_height="match_parent" android:text="Placeholder" > </TextView> </LinearLayout>
Thay đổi code Activity như sau:
public class ReadWebpageAsyncTask extends Activity { private TextView textView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); textView = (TextView) findViewById(R.id.TextView01); } private class DownloadWebPageTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... urls) { // we use the OkHttp library from https://github.com/square/okhttp OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(urls[0]) .build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) { return response.body().string(); } } return "Download failed"; } @Override protected void onPostExecute(String result) { textView.setText(result); } } public void onClick(View view) { DownloadWebPageTask task = new DownloadWebPageTask(); task.execute(new String[] { "http://www.androidcoban.com/" }); } }
Tiến hành Chạy ứng dụng. Trang web được xác định được đọc dưới nền. Sau khi hoàn thành textview được cập nhật.
Xem thêm ví dụ khác về Asyctask return multple value… tại đây.
Còn tiếp……
LINK GỐC: XEM TẠI ĐÂY
Bình luận đã bị khoá.