Я думаю, вы не понимаете, что делает AsyncTask. Вы не можете определить методы, такие как postLastName, postFirstName, postWh независимо от одного подкласса AsyncTask, и заставить его выполнять этот метод из потока пользовательского интерфейса. AsyncTask предназначен для облегчения выполнения фоновых заданий, которые должны обновлять пользовательский интерфейс, не заставляя вас обрабатывать потоки напрямую.
Для связи с сервером вы используете HttpClient, и вызов HttpClient.execute () будет блокироваться, пока ответ сервера не вернется. Это может занять много времени, особенно если сервер занят, умирает или отключается сотовая связь. Когда этот вызов занимает слишком много времени, вы не хотите, чтобы ваш пользовательский интерфейс перестал отвечать на запросы пользователя. Вы хотите показать вращающийся спиннер, чтобы пользователь знал, что что-то происходит. Если вы использовали код, который вы предоставили, ваш пользовательский интерфейс прекратил бы рисовать до тех пор, пока не будет возвращен вызов HttpClient.execute (), потому что вы вызываете его в потоке пользовательского интерфейса.
Чтобы обойти эту проблему, переместите этот вызов из потока пользовательского интерфейса в другой поток. Пусть этот поток ожидает ответа, затем уведомляет поток пользовательского интерфейса о завершении и использует поток пользовательского интерфейса для обновления пользовательского интерфейса новыми данными. Почему вы не можете позволить этому фоновому потоку обновлять интерфейс? Потому что это нарушило бы правило потоков Android, которое гласит, что ТОЛЬКО поток пользовательского интерфейса может обновлять пользовательский интерфейс.
AsyncTask позволяет вам запускать что-либо вне потока пользовательского интерфейса (doInBackground ()) и отправлять возвращаемое значение в поток пользовательского интерфейса (onPostExecute ()), чтобы он мог безопасно обновлять пользовательский интерфейс, не нарушая правила Android. Вы не вызываете doInBackground () или onPostExecute () напрямую, вместо этого вы вызываете AsyncTask.execute (), и код в AsyncTask вызывает doInBackground () в фоновом потоке, а когда он завершается, он вызывает onPostExecute () в потоке пользовательского интерфейса , Таким образом, вы не запутаетесь, выполняя все потоки самостоятельно.
Теперь ваша идея о том, чтобы несколько запросов проходили через один подкласс, не сработает, потому что AsyncTask связывает воедино две части выполнения сервисных вызовов: детали выполнения сервисного вызова для получения ответа и что с этим делать. ответ на обновление пользовательского интерфейса. Если вызывается метод postFirstName (), то, что вы делаете после того, как он возвращает этот ответ, вероятно, отличается от того, если вы вызывали postLastName (). И потому что это отличается, вы не можете просто определить ОДИН AsyncTask для всех этих различных вызовов. Вы можете поделиться кодом либо с помощью композиции, либо с помощью подклассов базового класса, но вам придется создавать подкласс для каждой уникальной операции, которую вы хотите выполнить на сервере. Так что думайте класс вместо метода для каждого вызова.
Вам не нужно использовать параметры, переданные в doInBackground (). Если у вас есть несколько типов параметров для передачи в AsyncTask. Передайте их в конструкторе. Поскольку вы не можете повторно использовать экземпляры AsyncTask (то есть не можете вызывать AsyncTask.execute () более одного раза за экземпляр). Их жизненный цикл ДОЛЖЕН быть реализован, выполнить () и бросить. Это означает, что передача ввода в конструкторе не повредит вашей способности использовать AsyncTask.
Я написал свою собственную версию AsyncTask, которая разделяет три метода обратного вызова: success () для обработки результата, возвращенного из doInBackground (); handleException () вызывается, когда любое исключение выдается из doInBackground (); и doFinally () вызывается независимо от doInBackground (), что-то возвращает или выдает исключение. По умолчанию AsyncTask onPostExecute () вызывается независимо от ошибки или успеха. Это будет выглядеть примерно так:
public class MyTask extends EnhancedAsyncTask<Param,Integer,MyResult> {
MyParam1 param1;
MyParam2 param2;
public MyTask( MyParam1 param1, MyParam2 param2 ) {
this.param1 = param;
this.param2 = param2;
}
protected MyResult doInBackground( Param... params ) {
// do server work here
server.send( param1, param2 );
}
protected void success( MyResult result ) {
// do Update of the UI
}
protected void handleException( Exception ex ) {
// show an error here
}
}
// Now to use this AsyncTask you would do something like this:
MyTask task = new MyTask( param1, param2 ).execute();
Часто я делаю это как анонимный внутренний класс, поэтому передача ссылок на пользовательский интерфейс не требуется, но, опять же, если вы не делаете классы Anon, вы можете просто передать их конструктору. Вы просто должны быть осторожны, чтобы не касаться пользовательского интерфейса, если действие будет уничтожено (например, пользователь переворачивает экран).