Intereting Posts

AsyncTask Android – шаблон дизайна и возвращаемые значения

Я пишу приложение, которое проверяет учетные данные для входа на внешний веб-сервер, поэтому у меня есть основная проблема создания экрана входа, который при отправке отправит HTTP-запрос на сервер в фоновом режиме, а не приведет к зависанию пользовательского интерфейса. ProgressDialog для пользователя.

Моя проблема заключается в том, что я хочу написать общий класс HTTP-запроса, который расширяет AsyncTask, поэтому, когда я вызываю .execute() я .execute() параметры String, которые могут содержать что-то вроде «post», и когда doInBackground вызывается, это увидит 'Post', а затем переместите эти параметры на соответствующий вызов в моем классе. Псевдокод был бы чем-то вроде

 public class HTTPOperations extends AsyncTask<String, Void, String> { doInBackground(String... string1,additionalParams) { if string1.equals "post" response = httpPost(additionalParams) return response; } httpPost(params) { // do http post request } } 

Это все, о чем я мог подумать, кроме создания класса для каждого запроса HTTP Post / GET и т. Д. Я хочу создать и расширить ASyncTask …

Что приводит меня к моей следующей проблеме, если HTTP POST успешна и возвращает токен аутентификации, как мне получить доступ к этому токену?

Поскольку новый httpOperations.execute () не возвращает строку из doInBackground, но значение типа

Извините, если это не имеет смысла, я не могу понять это вообще. Если вам это нужно, попросите уточнить. Дизайн и идеи дизайна AsyncTask очень приветствуются.

Solutions Collecting From Web of "AsyncTask Android – шаблон дизайна и возвращаемые значения"

Если вы разрабатываете многоразовую задачу для чего-то вроде этого, вам нужно определить возвращаемый тип повторного использования. Его дизайнерское решение с вашей стороны. Спросите себя: «Являются ли мои HTTP-операции одинаковыми как в механизмах, с которыми они вызваны, так и в процессе обработки их данных?» Если это так, вы можете создать отдельный класс для выполнения обоих. Если нет, вам, вероятно, нужны разные классы для разных удаленных операций.

В моем личном использовании у меня есть объект, который присоединяет пары ключевых значений, а общий тип возвращаемого значения – HttpEntity . Это тип возвращаемого значения для HTTP Get и Post, и это, похоже, работает нормально в моих сценариях, потому что я бросаю исключения в исключительных ситуациях с результатом HTTP, например, 404. Другим приятным аспектом этой настройки является то, что код для присоединения параметров к get Или почта довольно похожи, поэтому эту логику довольно легко построить.


Примером может быть что-то вроде этого (psuedo):

 public interface DownloadCallback { void onSuccess(String downloadedString); void onFailure(Exception exception); } 

Затем в вашем коде, где вы собираетесь выполнять загрузку:

 DownloadCallback dc = new DownloadCallback(){ public void onSuccess(String downloadedString){ Log.d("TEST", "Downloaded the string: "+ downloadedString); } public void onFailure(Exception e){ Log.d("TEST", "Download had a serious failure: "+ e.getMessage()); } } DownloadAsyncTask dlTask = new DownloadAsyncTask(dc); 

Затем внутри конструктора DownloadAsyncTask сохраните DownloadCallback и, когда загрузка будет завершена или завершится неудачно, вызовите метод в обратном вызове загрузки, который соответствует событию. Так…

 public class DownloadAsyncTask extends AsyncTask <X, Y, Z>(){ DownloadCallback dc = null; DownloadAsyncTask(DownloadCallback dc){ this.dc = dc; } ... other stuff ... protected void onPostExecute(String string){ dc.onSuccess(string); } } 

Я буду повторять, что я думаю, что на благо себя, вы должны передать HttpEntities. Теперь строка может показаться хорошей идеей, но на самом деле это приводит к проблемам позже, когда вы хотите сделать более сложную логику своих http-звонков. Конечно, это зависит от вас. Надеюсь, это поможет.

Предположим, что формат данных с web api – json, мой шаблон дизайна:

Общие классы
1.MyAsyncTask: расширяет AsyncTask
2.BackgroundBase: параметры для сервера
3.API_Base: параметры с сервера
4.MyTaskCompleted: интерфейс обратного вызова

 public class MyAsyncTask<BackgroundClass extends BackgroundBase,APIClass extends API_Base> extends AsyncTask<BackgroundClass, Void, APIClass> { private ProgressDialog pd ; private MyTaskCompleted listener; private Context cxt; private Class<APIClass> resultType; private String url; private int requestCode; public MyAsyncTask(MyTaskCompleted listener, Class<APIClass> resultType, int requestCode, String url){ this.listener = listener; this.cxt = (Context)listener; this.requestCode = requestCode; this.resultType = resultType; this.url = url; } public MyAsyncTask(MyTaskCompleted listener, Class<APIClass> resultType, int requestCode, String url, ProgressDialog pd){ this(listener, resultType, requestCode, url); this.pd = pd; this.pd.show(); } @Override protected APIClass doInBackground(BackgroundClass... params) { APIClass result = null; try { //do something with url and params, and get data from WebServer api BackgroundClass oParams = params[0]; String sUrl = url + "?d=" + URLEncoder.encode(oParams.getJSON(), "UTF-8"); String source = "{\"RtnCode\":1, \"ResultA\":\"result aaa\", \"ResultB\":\"result bbb\"}"; //to see progressdialog Thread.sleep(2000); result = new com.google.gson.Gson().fromJson(source, resultType); } catch (Exception e) { e.printStackTrace(); } return result; } @Override protected void onPostExecute(APIClass result) { super.onPostExecute(result); try { if(pd != null && pd.isShowing()) pd.dismiss(); API_Base oApi_Base = (API_Base)result; listener.onMyTaskCompleted(result , this.requestCode); } catch (Exception e) { e.printStackTrace(); } } } public class API_Base { public int RtnCode; public String getJSON(Context context) throws Exception { return new com.google.gson.Gson().toJson(this); } public String toString(){ StringBuilder sb = new StringBuilder(); for (Field field : this.getClass().getFields()) { try { field.setAccessible(true); Object value = field.get(this); if (value != null) { sb.append(String.format("%s = %s\n", field.getName(), value)); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } return sb.toString(); } } public class BackgroundBase { public String getJSON() throws Exception { return new com.google.gson.Gson().toJson(this); } } public interface MyTaskCompleted { void onMyTaskCompleted(API_Base oApi_Base, int requestCode) ; } 

Например, давайте назовем два api в одном действии
предполагать :
API 1. http://www.google.com/action/a
Входные параметры: ActionA
Выходные параметры: RtnCode, ResultA

API 2. http://www.google.com/action/b
Входные параметры: ActionB
Выходные параметры: RtnCode, ResultB

Классы с примером:
1.MyActivity: расширяет активность и реализует MyTaskCompleted
2.MyConfig: класс утилиты, я устанавливаю requestCode здесь
3.BackgroundActionA, BackgroundActionB: классы моделей для входных параметров api
4.API_ActionA, API_ActionB: классы моделей для выходных параметров api

 public class MyActivity extends Activity implements MyTaskCompleted { ProgressDialog pd; Button btnActionA, btnActionB; TextView txtResult; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.my_layout); btnActionA = (Button)findViewById(R.id.btn_actionA); btnActionB = (Button)findViewById(R.id.btn_actionB); txtResult = (TextView)findViewById(R.id.txt_result); btnActionA.setOnClickListener(listener_ActionA); btnActionB.setOnClickListener(listener_ActionB); pd = new ProgressDialog(MyActivity.this); pd.setTitle("Title"); pd.setMessage("Loading"); } Button.OnClickListener listener_ActionA = new Button.OnClickListener(){ @Override public void onClick(View v) { //without ProgressDialog BackgroundActionA oBackgroundActionA = new BackgroundActionA("AAA"); new MyAsyncTask<BackgroundActionA, API_ActionA>(MyActivity.this, API_ActionA.class, MyConfig.RequestCode_actionA, "http://www.google.com/action/a").execute(oBackgroundActionA); } }; Button.OnClickListener listener_ActionB = new Button.OnClickListener(){ @Override public void onClick(View v) { //has ProgressDialog BackgroundActionB oBackgroundActionB = new BackgroundActionB("BBB"); new MyAsyncTask<BackgroundActionB, API_ActionB>(MyActivity.this, API_ActionB.class, MyConfig.RequestCode_actionB, "http://www.google.com/action/b", MyActivity.this.pd).execute(oBackgroundActionB); } }; @Override public void onMyTaskCompleted(API_Base oApi_Base, int requestCode) { // TODO Auto-generated method stub if(requestCode == MyConfig.RequestCode_actionA){ API_ActionA oAPI_ActionA = (API_ActionA)oApi_Base; txtResult.setText(oAPI_ActionA.toString()); }else if(requestCode == MyConfig.RequestCode_actionB){ API_ActionB oAPI_ActionB = (API_ActionB)oApi_Base; txtResult.setText(oAPI_ActionB.toString()); } } } public class MyConfig { public static String LogTag = "henrytest"; public static int RequestCode_actionA = 1001; public static int RequestCode_actionB = 1002; } public class BackgroundActionA extends BackgroundBase { public String ActionA ; public BackgroundActionA(String actionA){ this.ActionA = actionA; } } public class BackgroundActionB extends BackgroundBase { public String ActionB; public BackgroundActionB(String actionB){ this.ActionB = actionB; } } public class API_ActionA extends API_Base { public String ResultA; } public class API_ActionB extends API_Base { public String ResultB; } 

Преимущество с этим шаблоном проектирования :
Преимущество 1.one для multi api
2. просто добавьте классы классов для новых api, например: BackgroundActionA и API_ActionA
3. определить, какой API по другому запросуCode в функции обратного вызова: onMyTaskCompleted