我遇到了AsyncTask和onPostExecute的问题.我发现onPostExecute正在与主ui线程不同的线程上执行,这导致在修改任何视图时发生CalledFromWrongThreadException.
我进行了一些日志记录,以查看运行onPreExecute,doInBackground和onPostExecute的线程.我会看到这样的结果……
onPreExecute ThreadId: 1 doInBackground ThreadId: 25 onPostExecute ThreadId: 18
我相信主ui线程id是1,我希望onPre和onPost都在线程1上执行.我确保创建并从ui线程调用execute方法(例如在Activity的onCreate中).
另外需要注意的是,我注意到后来的异步任务将在与前一个异步任务onPostExecute方法相同的线程上运行其onPostExecute方法(在本例中为线程18).
现在为了解决这个问题,我在调用runOnUiThread的过程中将代码包装在我的onPostExecute方法中,但我认为这很糟糕,并且想要解决真正的问题.
我没有想法!任何人有任何见解?我很乐意回答任何可以帮助进一步调查的问题!
编辑:
有两种方法可以在代码中运行异步任务.我想知道这些例子中的后者是否会导致一些奇怪的事情发生?
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!!! } }
}
以上看起来像AsyncTask的使用,但我仍然看到这个问题即使在这样的简单情况下也会发生.下一个示例使用异步任务来运行其他异步任务.也许有些东西我不知道当异步任务被构造导致一些奇怪的行为时会发生什么?
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,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); } } }
也许这里发生的事情只是非常奇怪,而且根本不是如何使用异步任务,无论哪种方式都可以很好地解决问题的根源.
如果您需要更多背景,请告诉我.