在Android上调用返回JSON响应的HTTP Web API调用的最有效方法是什么?

Dv_*_*_MH 38 java android httprequest android-asynctask asp.net-web-api

我是完美主义者类型,我已经使用Google Places API处理网络API调用(仅作为示例),但我觉得它有时很慢或者说我做得不对.有些博客说我应该使用AndroidHttpClient,但我不是,不是吗?

Web API调用我正在使用return json并且我不在UI线程上运行它们,因此使用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");
    }
}
Run Code Online (Sandbox Code Playgroud)

gun*_*nar 43

你正在使用的Http引擎似乎是最好的选择.实际上,任何其他第三方引擎都基于Apache,或者基于HttpUrlConnection.我更喜欢使用Spring for 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();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. JSON解析:您使用的是Android标准解析JSON的方式,但这并不是最快和最容易使用的方法.GSONJackson更好用.为了对JSON解析器进行比较,我会选择杰克逊.这是比较的另一个SO主题.

  3. 不要连接类似的字符串,因为连接字符串每次都会创建另一个字符串.请StringBuilder改用.

  4. 异常处理(无论如何,这在所有编程论坛中都是一个长期争论的主题).首先你要记录它(Log不要使用class System.out.printXXX).然后,您需要通知用户:您要么是一个消息,要么显示标签或通知.决定取决于用户案例以及您正在进行的通话的相关性.

这些是我在您的代码中看到的主题.

编辑我意识到我没有回答这个问题:is AsyncTask the most efficient way to run on background thread or should I use something else?

我要给出的简短答案是:如果你应该执行短时间的请求,那么AsyncTask就是完美的.但是,如果您需要获取一些数据并显示它 - 但您不想担心是否在屏幕旋转等情况下再次下载,我强烈建议您使用AsyncTaskLoaderLoaders一般.

如果您需要下载一些大数据,那么您可以使用IntentService或者进行重量级操作DownloadManager.

享受编码!


小智 6

------为您的项目创建一个服务处理程序类--------

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;
}
}
Run Code Online (Sandbox Code Playgroud)

-------------- AsyncTask For Login ------------------

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);
    }
}
}
Run Code Online (Sandbox Code Playgroud)

---------------网络连接类---------------------

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;
}
}
Run Code Online (Sandbox Code Playgroud)
JSONArray main1 = js.getJSONArray("Test 1");

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

    JSONObject jsonObject = main1.getJSONObject(i);
Run Code Online (Sandbox Code Playgroud)