Чтобы в приложении выполнять тяжелые задачи можно вводить отдельный поток и использовать Handler для обратной связи и обновления экрана. Для решения подобных задач сделали отдельный класс – AsyncTask. Т.е. его цель – это выполнение тяжелых задач и передача в UI-поток результатов работы. При этом нам не надо задумываться о создании Handler и нового потока. Для отправки запросов вроде как тоже рекомендуется использовать AsyncTask.
JSONParser
Данные с сервера частенько отправляют в формате JSON. Поэтому, можно воспользоваться классом для отправки запросов в json формате. Код нашёл на просторах http://stackoverflow.com
public class JSONParser { static InputStream is = null; static JSONObject jObj = null; static String json = ""; // конструктор public JSONParser() { } /** * Получить ответ по ссылке в формате json * @param url запрашиваемая страница * @param method GET or POST * @param params параметры, которые необходимо передать * @return */ public JSONObject makeHttpRequest(String url, String method, List<NameValuePair> params) { // создаём HTTP запрос try { if(method == "POST"){ DefaultHttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(url); httpPost.setEntity(new UrlEncodedFormEntity(params)); HttpResponse httpResponse = httpClient.execute(httpPost); HttpEntity httpEntity = httpResponse.getEntity(); is = httpEntity.getContent(); }else if(method == "GET"){ DefaultHttpClient httpClient = new DefaultHttpClient(); String paramString = URLEncodedUtils.format(params, "utf-8"); url += "?" + paramString; HttpGet httpGet = new HttpGet(url); HttpResponse httpResponse = httpClient.execute(httpGet); HttpEntity httpEntity = httpResponse.getEntity(); is = httpEntity.getContent(); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8); StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } is.close(); json = sb.toString(); } catch (Exception e) { Log.e("Buffer Error", "Error converting result " + e.toString()); } // пробуем распарсит JSON объект try { jObj = new JSONObject(json); } catch (JSONException e) { Log.e("JSON Parser", "Error parsing data " + e.toString()); } return jObj; } }
AsyncTask
Чтобы работать с AsyncTask
, необходимо создать класс-наследник и в нём переопределить необходимые методы:
doInBackground
– будет выполнен в новом потоке, здесь решаем все свои задачи
onPreExecute
– выполняется перед doInBackground, имеет доступ к UI
onPostExecute
– выполняется после doInBackground (не срабатывает в случае, если AsyncTask был отменен), имеет доступ к UI
При описании класса-наследника AsyncTask мы в угловых скобках указываем три типа данных:
- Тип входных данных. Это данные, которые пойдут на вход AsyncTask.
- Тип промежуточных данных. Данные, которые используются для вывода промежуточных результатов.
- Тип возвращаемых данных. То, что вернет AsyncTask после работы.
Весь класс будет выглядеть примерно так:
public class UpdateTask extends AsyncTask<String, Void, JSONObject> { Context context; public UpdateTask(Context context) { super(); this.context = context; } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected JSONObject doInBackground(String... urls) { return loadJSON(urls[0]); } public JSONObject loadJSON(String url) { JSONParser jParser = new JSONParser(); // здесь параметры необходимые в запрос добавляем List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("my_param", "param_value")); // посылаем запрос методом GET JSONObject json = jParser.makeHttpRequest(url, "GET", params); return json; } @Override protected void onPostExecute(JSONObject jsonData) { // если какой-то фейл, проверяем на null // фейл может быть по многим причинам: сервер сдох, нет сети на устройстве и т.д. if (jsonData != null) { super.onPostExecute(jsonData); String res = ""; try { // прочитать параметр, который отправил сервер; // здесь вместо "result" подставляйте то, что вам надо res = jsonData.getString("result"); // что-то делаем, к примеру вызываем метод главного Activity на обновление GUI ((MainActivity) context).updateGUI(res); } catch (JSONException e) { e.printStackTrace(); } } else { ((MainActivity) context).updateGUI(res); } } }
Ну и само использование:
new UpdateTask(this).execute("http://страница_необходимая");
На сервере для нашего случая в php у нас к примеру (параметр «result» мы и пытаемся на клиенте получить):
$res['result'] = 'cool'; $json = json_encode($res);
Здравствуйте. Отличная статья!
Скажите, пожалуйста, а с чем может быть связано, что при POST запросе выдаётся ошибка
Error parsing data org.json.JSONException: Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject
?
Вот код:
public class POSTUpdateTask extends AsyncTask
{
Context context;
String par_name; String par_value;
String res = «», response;
public POSTUpdateTask(Context context, String par_name, String par_value, String response)
{
super();
this.context = context;
this.par_name = par_name;
this.par_value = par_value;
this.response = response;
}
@Override
protected void onPreExecute()
{
super.onPreExecute();
}
@Override
protected JSONObject doInBackground(String… urls)
{
return loadJSON(urls[0]);
}
public JSONObject loadJSON(String url)
{
JSONParser jParser = new JSONParser();
// здесь параметры необходимые в запрос добавляем
List params = new ArrayList();
params.add(new BasicNameValuePair(par_name, par_value));
params.add(new BasicNameValuePair(«Claim[date_time]», «param_value»));
params.add(new BasicNameValuePair(«Claim[contact_name]», «param_value»));
params.add(new BasicNameValuePair(«Claim[contact_phone]», «param_value»));
params.add(new BasicNameValuePair(«Claim[is_passenger]», «param_value»));
params.add(new BasicNameValuePair(«Claim[adress_from]», «param_value»));
params.add(new BasicNameValuePair(«Claim[is_point]», «param_value»));
params.add(new BasicNameValuePair(«Claim[points][0][address]», «param_value»));
params.add(new BasicNameValuePair(«Claim[points][0][note]», «param_value»));
params.add(new BasicNameValuePair(«Claim[adress_to]», «param_value»));
params.add(new BasicNameValuePair(«Claim[wishes]», «param_value»));
params.add(new BasicNameValuePair(«Claim[purposes]», «param_value»));
params.add(new BasicNameValuePair(«Claim[procuration]», «param_value»));
params.add(new BasicNameValuePair(«Claim[permit]», «param_value»));
// посылаем запрос методом POST
JSONObject json = jParser.makeHttpRequest(url, «POST», params);
return json;
}
@Override
protected void onPostExecute(JSONObject jsonData)
{
// если какой-то фейл, проверяем на null
// фейл может быть по многим причинам: сервер сдох, нет сети на устройстве и т.д.
if (jsonData != null)
{
super.onPostExecute(jsonData);
String res = «»;
try
{
res = jsonData.getString(response);
} catch (JSONException e)
{
e.printStackTrace();
}
Toast.makeText(context, res, Toast.LENGTH_LONG).show();
}
else
{
}
}
}
Вызывается следующим образом: String token = prefs.getString(«token», «»);
new POSTUpdateTask(getActivity(), «access_token», token, «id»)
.execute(«https://id20.ru/api/claim/create/»);
где токен приходит из другого GET запроса.
Спасибо!
Значит приходит на json, а html документ.
а как это исправить?
написать парсер под html