Tôi đang gặp sự cố với AsyncTask và onPostExecute. Tôi thấy rằng onPostExecute đang thực thi trên một luồng khác với luồng ui chính, mà gây ra một lời gọi CalledFromWrongThreadException xảy ra khi tôi sửa đổi bất kỳ khung nhìn nào.Android AsyncTask onPostExecute tắt chủ đề ui chính
Tôi đặt trong một số đăng nhập để xem những chủ đề nào trênPreExecute, doInBackground và onPostExecute đang chạy. Tôi sẽ thấy một kết quả như thế này ...
onPreExecute ThreadId: 1
doInBackground ThreadId: 25
onPostExecute ThreadId: 18
Tôi tin rằng thread ui chính id là 1 và tôi mong chờ cả onPre và onPost để cả hai thực hiện trên thread 1. Tôi đang làm cho chắc chắn để tạo ra và cũng gọi phương thức thực hiện từ chuỗi ui (ví dụ trong onCreate of a Activity).
Một điều cần lưu ý là tôi đã nhận thấy rằng các tác vụ không đồng bộ sau này sẽ chạy phương thức onPostExecute của họ trên cùng một luồng như các tác vụ không đồng bộ trước phương thức onPostExecute (trong trường hợp này là chuỗi 18).
Ngay bây giờ để giải quyết vấn đề này, tôi gói mã trong các phương thức onPostExecute của tôi trong một cuộc gọi đến runOnUiThread, nhưng tôi nghĩ rằng điều này là hacky và muốn gặp vấn đề thực sự.
Tôi hết ý tưởng! Bất kỳ ai có bất kỳ cái nhìn sâu sắc? Tôi rất sẵn lòng trả lời bất kỳ câu hỏi nào có thể trợ giúp cho việc điều tra thêm!
EDIT:
Có hai cách mà tác vụ không đồng bộ đang được chạy trong mã. Tôi tự hỏi nếu sau này trong những ví dụ này gây ra một cái gì đó kỳ lạ xảy ra?
public class SomeActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
new SomeAsyncTask().execute();
}
private class SomeAsyncTask extends AsyncTask<String, Void, Integer> {
@Override
public void onPreExecute() {
Thread.currentThread().getId() // 1
//Show a dialog
}
@Override
public Integer doInBackground(String... params) {
Thread.currentThread().getId() // 25
return 0;
}
@Override
public void onPostExecute(Integer result) {
Thread.currentThread().getId() // 18
//hide dialog
//update text view -> CalledFromWrongThreadException!!!
}
}
}
dường như ở trên giống như một sử dụng vani của AsyncTask, nhưng tôi vẫn thấy vấn đề này xảy ra ngay cả trong trường hợp đơn giản như thế này. Ví dụ tiếp theo sử dụng tác vụ không đồng bộ để chạy các tác vụ không đồng bộ khác. Có lẽ có một cái gì đó tôi không biết về những gì sẽ xảy ra khi một nhiệm vụ async được xây dựng đang gây ra một số hành vi kỳ lạ?
public class SomeActivity extends Activity implements TaskRunner.OnFinishListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
TaskRunner taskRunner = new TaskRunner();
taskRunner.setOnFinishListener(this);
taskRunner.addTask(new SingleTask());
taskRunner.addTask(new SingleTask());
taskRunner.execute();
}
@Override
public void onTaskFinish(List<Integer> results) {
//Thread id is 18 when it should be 1
//do something to a view - CalledFromWrongThreadException!!
}
}
//In a different file
public class SingleTask extends AsyncTask<String, Void, Integer> {
//This is a an async task so we can run it separately as an asynctask
//Or run it on whatever thread runnerExecute is called on
@Override
public Integer doInBackground(String... params) {
return runnerExecute(params);
}
//Can be called outside of doInBackground
public Integer runnerExecute(String... params) {
//some long running task
return 0;
}
}
//In a different file
public class TaskRunner {
private List<SingleTask> tasks;
private OnFinishListener onFinishListener;
public interface OnFinishListener {
public void onTaskFinish(List<Integer> results);
}
public TaskRunner() {
this.tasks = new ArrayList<SingleTask>();
}
public void setOnFinishListener(OnFinishListener listener) {
this.onFinishListener = listener;
}
public void addTask(SingleTask task) {
tasks.add(task);
}
public void executeTasks() {
new RunnerTask().execute((SingleTask[]) tasks.toArray());
}
//Calls the runnerExecute method on each SingleTask
private class RunnerTask extends AsyncTask<SingleTask, Integer, List<Integer>> {
@Override
public void onPreExecute() {
//Runs on thread 1
}
@Override
public List<Integer> doInBackground(SingleTask... params) {
//Runs on arbitrary thread
List<Integer> results = new ArrayList<Integer>();
for(SingleTask task : params) {
int result =task.runnerExecute(task.getParams());
results.add(result);
}
return results;
}
@Override
public void onPostExecute(List<Integer> results) {
//Runs on thread 18
onFinishListener.onTaskFinish(results);
}
}
}
Có thể những gì đang xảy ra ở đây chỉ là siêu lạ và không phải là cách sử dụng các tác vụ không đồng bộ, cách tốt nhất để tìm hiểu vấn đề.
Hãy cho tôi biết nếu bạn cần thêm bất kỳ ngữ cảnh nào.
Bạn có thể hiển thị mã có liên quan không? – Eric
Bạn sẽ không thực hiện 'Hoạt động' khác trước khi 'AsyncTask' kết thúc, đúng không? – codeMagic
Không, tôi đợi cho đến khi asynctask hoàn tất và sau đó bắt đầu một hoạt động trong onPostExecuteMethod. Tôi sẽ thêm một số mã có liên quan vào câu hỏi của mình. – fxfilmxf