Подтвердить что ты не робот

Какой самый эффективный способ для Android вызывать вызовы HTTP Web API, которые возвращают ответ JSON?

Я тип перфекциониста, у меня уже есть API-интерфейсы API, отлично работающие с API Google Адресов (как пример), но я чувствую, что это иногда медленный или, возможно, я не делаю это правильно. Некоторые блоги говорят, что я должен использовать AndroidHttpClient, но я не, должен ли я?

В API-интерфейсе Web я использую return json, и я не запускаю их в потоке пользовательского интерфейса, следовательно, используя AsyncTask (это AsyncTask - самый эффективный способ запуска в фоновом потоке или я должен использовать что-то еще?)

Пожалуйста, посмотрите мой код и скажите мне, как он может быть более эффективным в любом случае

public static class NearbySearchRequest extends AsyncTask<String, Void, JSONObject>
{
    Exception mException = null;

    @Override
    protected void onPreExecute()
    {
        super.onPreExecute();
        this.mException = null;
    }

    @Override
    protected JSONObject doInBackground(String... params)
    {
        StringBuilder urlString = new StringBuilder();
        urlString.append("https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
        urlString.append("key=").append(Constants.GOOGLE_SIMPLE_API_KEY);
        urlString.append("&location=").append(params[0]);
        urlString.append("&sensor=").append("true");
        urlString.append("&language=").append("en-GB");
        urlString.append("&name=").append(params[1]);
        urlString.append("&rankby=").append("distance");

        LogHelper.Log(urlString.toString());

        HttpURLConnection urlConnection = null;
        URL url = null;
        JSONObject object = null;

        try
        {
            url = new URL(urlString.toString());
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.connect();
            InputStream inStream = null;
            inStream = urlConnection.getInputStream();
            BufferedReader bReader = new BufferedReader(new InputStreamReader(inStream));
            String temp, response = "";
            while ((temp = bReader.readLine()) != null)
                response += temp;
            bReader.close();
            inStream.close();
            urlConnection.disconnect();
            object = (JSONObject) new JSONTokener(response).nextValue();
        }
        catch (Exception e)
        {
            this.mException = e;
        }

        return (object);
    }

    @Override
    protected void onPostExecute(JSONObject result)
    {
        super.onPostExecute(result);

        if (this.mException != null)
            ErrorHelper.report(this.mException, "Error # NearbySearchRequest");
    }
}
4b9b3361

Ответ 1

Двигатель Http, который вы используете, кажется лучшим выбором. На самом деле любые другие 3-х сторонние движки основаны либо на Apache, либо на HttpUrlConnection. Я предпочитаю использовать Spring для Android, поскольку этот API обеспечивает абстракцию над Http Engine, и вам действительно не нужно заботиться о том, какой API использовать на уровне API. Или вы можете использовать Volley - очень модную библиотеку.

Я бы коснулся некоторых ваших кодов:

  1. Что делать, если при чтении потока есть исключение? Затем поток остается открытым, а также соединение. Поэтому я предложил бы иметь блок finally, где потоки и соединение закрыты независимо от того, получаете ли вы исключение или нет:

    HttpURLConnection urlConnection = null;
    URL url = null;
    JSONObject object = null;
    InputStream inStream = null;
    try {
        url = new URL(urlString.toString());
        urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setRequestMethod("GET");
        urlConnection.setDoOutput(true);
        urlConnection.setDoInput(true);
        urlConnection.connect();
        inStream = urlConnection.getInputStream();
        BufferedReader bReader = new BufferedReader(new InputStreamReader(inStream));
        String temp, response = "";
        while ((temp = bReader.readLine()) != null) {
            response += temp;
        }
        object = (JSONObject) new JSONTokener(response).nextValue();
    } catch (Exception e) {
        this.mException = e;
    } finally {
        if (inStream != null) {
            try {
                // this will close the bReader as well
                inStream.close();
            } catch (IOException ignored) {
            }
        }
        if (urlConnection != null) {
            urlConnection.disconnect();
        }
    }
    
  2. JSON-синтаксический анализ: вы используете стандартный способ Android для анализа JSON, но это не самый быстрый и простой в работе. Лучше использовать GSON и Jackson. Чтобы сделать сравнение, когда дело касается парсеров JSON, я бы пошел за Джексоном. Вот еще одна тема для этого сравнения.

  3. Не объединяйте такие строки, как конкатенация строк, каждый раз создавая строку. Вместо этого используйте StringBuilder.

  4. Обработка исключений (в любом случае это тема длительной дискуссии на всех форумах программирования). Прежде всего вам нужно его зарегистрировать (используйте Log class not System.out.printXXX). Затем вам нужно либо сообщить об этом пользователю: либо вы хотите отправить сообщение, либо вы увидите ярлык или уведомление. Решение зависит от случая пользователя и того, насколько релевантен ваш звонок.

Это те темы, которые я вижу в вашем коде.

EDIT Я понимаю, что я не ответил на это: is AsyncTask the most efficient way to run on background thread or should я use something else?

Короткий ответ, который я бы дал, заключается в следующем: если вы должны выполнить короткий запрос времени, то AsyncTask идеально подходит. Однако, если вам нужно получить некоторые данные и отобразить их, но вы не хотите беспокоиться о том, загружать ли снова, если экран повернут и так далее, я настоятельно рекомендую использовать AsyncTaskLoader и Loaders в целом.

Если вам нужно загрузить некоторые большие данные, то либо вы используете IntentService либо, для тяжелых операций, DownloadManager.

Наслаждайтесь кодированием!

Ответ 2

------ Создайте класс обработчика службы для вашего проекта --------

public class ServiceHandler {

static String response = null;
public final static int GET = 1;
public final static int POST = 2;

public ServiceHandler() {
}

/*
 * Making service call
 * @url - url to make request
 * @method - http request method
 * */
public String makeServiceCall(String url, int method) {
    return this.makeServiceCall(url, method, null);
}

/*
 * Making service call
 * @url - url to make request
 * @method - http request method
 * @params - http request params
 * */
public String makeServiceCall(String url, int method,
        List<NameValuePair> params) {
    try {
        // http client
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpEntity httpEntity = null;
        HttpResponse httpResponse = null;

        // Checking http request method type
        if (method == POST) {
            Log.e("in POST","in POST");
            HttpPost httpPost = new HttpPost(url);
            // adding post params
            if (params != null) {
                Log.e("in POST params","in POST params");
                httpPost.setEntity(new UrlEncodedFormEntity(params));
            }
            Log.e("url in post service",url);
            httpResponse = httpClient.execute(httpPost);

        } else if (method == GET) {
            // appending params to url
            Log.e("in GET","in GET");
            if (params != null) {
                Log.e("in GET params","in GET params");
                String paramString = URLEncodedUtils
                        .format(params, "utf-8");
                url += "?" + paramString;
            }
            Log.e("url in get service",url);
            HttpGet httpGet = new HttpGet(url);

            httpResponse = httpClient.execute(httpGet);

        }
        httpEntity = httpResponse.getEntity();
        response = EntityUtils.toString(httpEntity);

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return response;

}
public String makeServiceCallIMAGE(String url, int method,
        List<NameValuePair> params) {
    try {
        // http client
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpEntity httpEntity = null;
        HttpResponse httpResponse = null;

        // Checking http request method type
        if (method == POST) {
            HttpPost httpPost = new HttpPost(url);
            // adding post params
            if (params != null) {
                httpPost.setEntity(new UrlEncodedFormEntity(params));

            }

            httpResponse = httpClient.execute(httpPost);

        } else if (method == GET) {
            // appending params to url
            if (params != null) {
                String paramString = URLEncodedUtils
                        .format(params, "utf-8");
                url += "?" + paramString;
            }
            HttpGet httpGet = new HttpGet(url);

            httpResponse = httpClient.execute(httpGet);

        }
        httpEntity = httpResponse.getEntity();
        response = EntityUtils.toString(httpEntity);

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return response;
}
}

-------------- AsyncTask для входа ------------------

public class Login_Activity extends ActionBarActivity {

//Internet Service
NetworkConnection nw;
ProgressDialog prgDialog;
Boolean netConnection = false;
//

//Login API
String loginURL ="url";
//

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);

    nw = new NetworkConnection(getApplicationContext());
    prgDialog = new ProgressDialog(this);
    // Set Cancelable as False
    prgDialog.setCancelable(false);

    new LoginOperation().execute();
}

private class LoginOperation  extends AsyncTask<String, Void, Void> {

    String status, message;
    @Override
    protected void onPreExecute() {
        // Set Progress Dialog Text
        prgDialog.setMessage("Logging...");
        prgDialog.show();
    }

    @Override
    protected Void doInBackground(String... urls) {

        if(nw.isConnectingToInternet() == true)
        {
            try
            {
                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
                nameValuePairs.add(new BasicNameValuePair("method", "ClientesLogin"));
                nameValuePairs.add(new BasicNameValuePair("Email", str_Email));
                nameValuePairs.add(new BasicNameValuePair("Senha", str_Password));
                ServiceHandler sh  = new ServiceHandler();
                String response = sh.makeServiceCall(loginURL, ServiceHandler.GET,
                        nameValuePairs);

                Log.e("response", response);

                JSONObject js = new JSONObject(response);
                status = js.getString("status");
                Log.e("status",status);

                if(status.contains("Fail"))
                {
                    message = js.getString("message");
                }
                /*else
                {
                    JSONObject jslogin=js.getJSONObject("user_list");
                    for (int i = 0; i < jslogin.length(); i++) {
                    }
                }*/

            }catch(Exception ex){

            }
            netConnection = true;
        }else
        {
            netConnection = false;
        }

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        prgDialog.dismiss();

        if(netConnection == false)
        {
            Toast toast = Toast.makeText(getApplicationContext(),"Internet is not available. Please turn on and try again.", Toast.LENGTH_LONG);
            toast.setGravity(Gravity.CENTER, 0, 0);
            toast.show();
        }
        else
        {
            if(status.contains("Success"))
            {
                Toast toast = Toast.makeText(getApplicationContext(), "Login Successful", Toast.LENGTH_SHORT);
                toast.setGravity(Gravity.CENTER, 0, 0);
                toast.show();

                Intent i=new Intent(Login_Activity.this,home_page_activity.class);
                startActivity(i);
            }
            else{
                Toast toast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT);
                toast.setGravity(Gravity.CENTER, 0, 0);
                toast.show();
            }
        }
        super.onPostExecute(result);
    }
}
}

--------------- Класс сетевого подключения ---------------------

public class NetworkConnection {

Context context;

public NetworkConnection(Context context){
    this.context = context;
}

public boolean isConnectingToInternet(){
    ConnectivityManager connectivity = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
      if (connectivity != null) 
      {
          NetworkInfo[] info = connectivity.getAllNetworkInfo();
          if (info != null) 
              for (int i = 0; i < info.length; i++) 
                  if (info[i].getState() == NetworkInfo.State.CONNECTED)
                  {
                      return true;
                  }
      }
      return false;
}
}

JSONArray main1 = js.getJSONArray("Test 1");

  for (int i = 0; i < main1.length(); i++) {

    JSONObject jsonObject = main1.getJSONObject(i);