Java Android 上调用返回 JSON 响应的 HTTP Web API 调用的最有效方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19050294/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the most efficient way on Android to call HTTP Web API calls that return a JSON response?
提问by Dv_MH
I'm the perfectionist type, I already got web API calls working fine with Google Places API (just as an example), but I feel it's sometimes slow or maybe I'm not doing it right. Some blogs are saying I should use AndroidHttpClient, but I'm not, should I ?
我是完美主义者类型,我已经让网络 API 调用与 Google Places API 一起正常工作(仅作为示例),但我觉得它有时很慢或者我做得不对。一些博客说我应该使用 AndroidHttpClient,但我不是,应该吗?
The web API calls i'm using return json and I don't run them on the UI thread, hence using AsyncTask (is AsyncTask the most efficient way to run on background thread or should I use something else ?)
我使用的 Web API 调用返回 json 并且我不在 UI 线程上运行它们,因此使用 AsyncTask(AsyncTask 是在后台线程上运行的最有效方法还是应该使用其他方法?)
Please see my code and tell me how could it be more efficient in anyway
请查看我的代码并告诉我它如何更有效
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");
}
}
采纳答案by gunar
The Http engine you're using seems the best choice. Actually any other 3-rd party engines are based either on Apache, either on HttpUrlConnection. I prefer to use Spring for Androidas that API provide an abstraction over Http Engine and you don't really need to care how about what API to use based on API level. Or you can use Volley- a very fashionable library.
您使用的 Http 引擎似乎是最佳选择。实际上,任何其他第 3 方引擎都基于 Apache,或者基于 HttpUrlConnection。我更喜欢使用Spring for Android,因为该 API 提供了对 Http 引擎的抽象,并且您并不真正需要关心基于 API 级别使用什么 API。或者您可以使用Volley- 一个非常时尚的库。
I would touch however some of your code:
但是,我会触摸您的一些代码:
What if there is an exception while reading the stream? Then the stream remains open and also the connection. So I would suggest to have a finally block where the streams and connection is closed no matter if you get an exception or not:
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(); } }
JSON parsing: you're using the Android standard way of parsing JSON, but that's not the fastest and easiest to work with. GSONand Hymansonare better to use. To make a comparisonwhen it comes for JSON parsers, I would go for Hymanson. Here's another SO topicon this comparison.
Don't concatenate strings like that as concatenating strings will create each time another string. Use a
StringBuilder
instead.Exception handling (this is anyway a long-debate subject in all programming forums). First of all you have to log it (Use
Log
class notSystem.out.printXXX
). Then you need to either inform the user: either you toast a message, either you show a label or notification. The decision depends on the user case and how relevant is the call you're making.
如果在读取流时出现异常怎么办?然后流保持打开状态,连接也保持打开状态。所以我建议在 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(); } }
JSON 解析:您使用的是 Android 解析 JSON 的标准方式,但这并不是最快和最容易使用的方式。GSON和Hymanson更好用。为了对 JSON 解析器进行比较,我会选择 Hymanson。这是有关此比较的另一个 SO 主题。
不要像这样连接字符串,因为每次连接字符串都会创建另一个字符串。使用 a
StringBuilder
代替。异常处理(这在所有编程论坛中都是一个长期争论的话题)。首先,您必须记录它(使用
Log
class notSystem.out.printXXX
)。然后您需要通知用户:要么敬酒,要么显示标签或通知。该决定取决于用户案例以及您拨打的电话的相关性。
These are the topics I see in you code.
这些是我在您的代码中看到的主题。
EDITI realize I didn't answer this: is AsyncTask the most efficient way to run on background thread or should I use something else?
编辑我意识到我没有回答这个:is AsyncTask the most efficient way to run on background thread or should I use something else?
The short answer I would give is: if you're supposed to perform a short time lived request, then AsyncTask
is perfect. However, if you need to get some data and display it - but you don't want to worry about whether to download again if the screen is rotated and so on, I would strongly recommend using an AsyncTaskLoader
and Loaders
in general.
我要给出的简短回答是:如果你应该执行一个短时间的请求,那么它AsyncTask
是完美的。但是,如果您需要获取一些数据并显示它——但您不想担心如果屏幕旋转等情况是否再次下载,我强烈建议您使用AsyncTaskLoader
and Loaders
。
If you need to download some big data, then either you use an IntentService
or, for heavy-weight operations, DownloadManager
.
如果您需要下载一些大数据,那么IntentService
对于重量级操作,您可以使用或DownloadManager
。
Enjoy coding!
享受编码!
回答by Nikunj Desai
------Create a Service Handler Class to your Project--------
------为您的项目创建一个服务处理程序类------
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 For Login------------------
--------------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);
}
}
}
---------------Network Connection class---------------------
---------------网络连接类---------------------
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);