Чтобы в приложении выполнять тяжелые задачи можно вводить отдельный поток и использовать 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