Có khái niệm gọi lại cũng tồn tại rất nhiều trong Java. Trong Java bạn định nghĩa một callback như thế này:
public interface TaskListener {
public void onFinished(String result);
}
Người ta sẽ thường xuyên tổ các loại định nghĩa người nghe bên trong AsyncTask
như thế này:
public class ExampleTask extends AsyncTask<Void, Void, String> {
public interface TaskListener {
public void onFinished(String result);
}
...
}
Và một thực hiện đầy đủ các callback trong AsyncTask
sẽ trông như thế này:
public class ExampleTask extends AsyncTask<Void, Void, String> {
public interface TaskListener {
public void onFinished(String result);
}
// This is the reference to the associated listener
private final TaskListener taskListener;
public ExampleTask(TaskListener listener) {
// The listener reference is passed in through the constructor
this.taskListener = listener;
}
@Override
protected String doInBackground(Void... params) {
return doSomething();
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// In onPostExecute we check if the listener is valid
if(this.taskListener != null) {
// And if it is we call the callback function on it.
this.taskListener.onFinished(result);
}
}
}
onPostExecute()
được gọi càng sớm càng nhiệm vụ nền kết thúc. Bạn có thể sử dụng toàn bộ điều như thế này:
ExampleTask task = new ExampleTask(new ExampleTask.TaskListener() {
@Override
public void onFinished(String result) {
// Do Something after the task has finished
}
});
task.execute();
Hoặc bạn có thể xác định TaskListener
hoàn toàn riêng rẽ như thế này:
ExampleTask.TaskListener listener = new ExampleTask.TaskListener() {
@Override
public void onFinished(String result) {
// Do Something after the task has finished
}
};
ExampleTask task = new ExampleTask(listener);
task.execute();
Hoặc bạn có thể phân lớp TaskListener
như thế này:
public class ExampleTaskListener implements TaskListener {
@Override
public void onFinished(String result) {
}
}
Và sau đó sử dụng nó như sau:
ExampleTask task = new ExampleTask(new ExampleTaskListener());
task.execute();
Bạn có thể dĩ nhiên chỉ ghi đè lên các phương pháp onPostExecute()
của AsyncTask
, nhưng điều đó là không nên và trong nhiều trường hợp thực hành thực sự khá xấu. Ví dụ, bạn có thể làm điều này:
ExampleTask task = new ExampleTask() {
@Override
public void onPostExecute(String result) {
super.onPostExecute(result);
// Your code goes here
}
};
này sẽ chỉ làm việc cũng như việc thực hiện ở trên với một giao diện người nghe riêng biệt, nhưng có một vài vấn đề với điều này:
Trước hết bạn thực sự có thể phá vỡ ExampleTask
tất cả cùng nhau. Tất cả đều đi xuống cuộc gọi super.onPostExecute()
ở trên. Nếu bạn là nhà phát triển ghi đè onPostExecute()
như trên và quên bao gồm cuộc gọi siêu hoặc chỉ cần xóa cuộc gọi đó hoặc vì lý do nào đó, phương thức onPostExecute()
gốc trong số ExampleTask
sẽ không được gọi nữa. Ví dụ: việc thực hiện toàn bộ người nghe với TaskListener
đột nhiên sẽ không hoạt động nữa kể từ khi cuộc gọi đến gọi lại được thực hiện trong onPostExecute()
. Bạn cũng có thể phá vỡ TaskListener
theo nhiều cách khác bằng cách vô tình hoặc vô tình ảnh hưởng đến trạng thái của ExampleTask
để nó không hoạt động nữa.
Nếu bạn nhìn vào những gì thực sự xảy ra khi bạn ghi đè lên một phương pháp như thế này hơn là nó sẽ trở nên rõ ràng hơn những gì đang xảy ra.Bằng cách ghi đè onPostExecute()
bạn đang tạo một lớp con mới là ExampleTask
. Nó sẽ là điều tương tự chính xác như làm điều này:
public class AnotherExampleTask extends ExampleTask {
@Override
public void onPostExecute(String result) {
super.onPostExecute(result);
// Your code goes here
}
}
Tất cả điều này chỉ là ẩn đằng sau một tính năng ngôn ngữ được gọi là lớp nặc danh. Đột nhiên ghi đè lên một phương pháp như thế này có vẻ không sạch sẽ và nhanh chóng nữa phải không?
Để tóm tắt:
- Trọng một phương pháp như thế này thực sự tạo ra một lớp con mới. Bạn không chỉ cần thêm một cuộc gọi lại, bạn đang sửa đổi cách thức hoạt động của lớp này và có thể vô tình phá vỡ quá nhiều thứ.
- Lỗi gỡ lỗi như thế này có thể nhiều hơn chỉ là một nỗi đau trong **. Bởi vì đột nhiên
ExampleTask
có thể ném Exceptions
hoặc đơn giản là không hoạt động nữa vì không có lý do rõ ràng, bởi vì bạn không bao giờ thực sự sửa đổi mã của nó.
- Mỗi lớp phải cung cấp việc triển khai người nghe ở những nơi phù hợp và dự định. Chắc chắn bạn chỉ có thể thêm chúng sau này bằng cách ghi đè
onPostExecute()
nhưng điều đó luôn luôn rất nguy hiểm. Ngay cả @flup với danh tiếng 13k của anh ấy đã quên bao gồm cuộc gọi super.onPostExecute()
trong câu trả lời của anh ấy, hãy tưởng tượng những gì một số khác không phải là nhà phát triển có kinh nghiệm có thể làm!
- Một chút trừu tượng không bao giờ làm tổn thương bất kỳ ai. Viết trình nghe cụ thể có thể hơi mã hơn, nhưng đó là giải pháp tốt hơn nhiều. Mã sẽ sạch hơn, dễ đọc hơn và dễ bảo trì hơn nhiều. Sử dụng các phím tắt như ghi đè
onPostExecute()
về cơ bản là hy sinh chất lượng mã cho một chút tiện lợi. Đó là không bao giờ là một ý tưởng tốt một sẽ chỉ gây ra vấn đề trong thời gian dài.
Đó không phải cách bạn làm điều đó^_ ^. Bạn tạo ra một chủ đề nền bằng cách sử dụng công việc async và mã của bạn aka httprequest đi vào phương thức doInBackground() và bạn định nghĩa lại kiểu chữ cho nó. Sau khi hoạt động nền kết thúc onPostExecute() được gọi là trong đó bạn viết mã để xử lý các phản ứng như bây giờ bạn nhận được để cập nhật quan điểm và tất cả. Có một phương thức progressupdate được kích hoạt khi đạt được tiến trình xác định. Tôi sẽ nhận được liên kết tài liệu trong một thời gian – Rico
http://developer.android.com/reference/android/os/AsyncTask.html – Rico