OkHttp 库 - 简单的 NetworkOnMainThreadException post
OkHttp Library - NetworkOnMainThreadException on simple post
我想在 Android 中使用 OkHttp 网络库。
我从他们网站上写的简单 post 示例开始:
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
通过此调用:
String response = post("http://www.roundsapp.com/post", json);
此调用以 NetworkOnMainThreadException.
结束
我可以用 AsyncTask 包装调用, 但据我从示例中了解到,OkHttp 库应该已经处理好了。
我做错了什么吗?
根据 OkHttp 文档:
它支持同步阻塞调用和带回调的异步调用。
您的示例在主线程上,Android 因为如果您尝试在主线程上进行网络调用,3.0 版会抛出该异常
更好的选择是将它与 retrofit 和 Gson 一起使用:
http://square.github.io/retrofit/
https://code.google.com/p/google-gson/
示例如下:
http://engineering.meetme.com/2014/03/best-practices-for-consuming-apis-on-android/
http://heriman.net/?p=5
你应该使用 OkHttp 的异步方法。
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
Call post(String url, String json, Callback callback) {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Call call = client.newCall(request);
call.enqueue(callback);
return call;
}
然后您的响应将在回调中处理 (OkHttp 2.x):
post("http://www.roundsapp.com/post", json, new Callback() {
@Override
public void onFailure(Request request, Throwable throwable) {
// Something went wrong
}
@Override public void onResponse(Response response) throws IOException {
if (response.isSuccessful()) {
String responseStr = response.body().string();
// Do what you want to do with the response.
} else {
// Request not successful
}
}
});
或 OkHttp 3.x/4.x:
post("http://www.roundsapp.com/post", "", new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// Something went wrong
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String responseStr = response.body().string();
// Do what you want to do with the response.
} else {
// Request not successful
}
}
});
查看他们的食谱以获取更多示例:http://square.github.io/okhttp/recipes/
如果您按照这些步骤来实现 OKHTTP,那么您肯定会通过仅应用两行代码在多个屏幕上调用多个 API
UpdateListener updateListener = new UpdateListener(HitAPIActivity.this, baseHTTPRequest);
updateListener.getJsonData();
第 1 步:
baseHTTPRequest = new BaseHTTPRequest();
// baseHTTPRequest.setURL("https://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demohttps://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo");
baseHTTPRequest.setURL("http://jsonparsing.parseapp.com/jsonData/moviesDemoItem.txt");
baseHTTPRequest.setRequestCode(reqType);
baseHTTPRequest.setCachedRequired(true);
UpdateListener updateListener = new UpdateListener(HitAPIActivity.this, baseHTTPRequest);
updateListener.executeRequest();
第 2 步:创建请求 class
/**
* 由 Deepak Sharma 于 2016 年 4 月 7 日创建。
* 这是一个包含基本参数的 HTTP 请求 class。
* 如果你想添加更多的参数,请做一个 class 的子class
* 并添加您的 subclass。不要修改此 class。
*/
public class BaseHTTPRequest<T> {
private Context context;
private String URL;
private int requestCode;
private List<T> listParameters;
private String header;
private boolean isCachedRequired;
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
public void setURL(String URL) {
this.URL = URL;
}
public String getURL() {
return URL;
}
public int getRequestCode() {
return requestCode;
}
public void setRequestCode(int requestCode) {
this.requestCode = requestCode;
}
public List<T> getListParameters() {
return listParameters;
}
public void setListParameters(List<T> listParameters) {
this.listParameters = listParameters;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public boolean isCachedRequired() {
return isCachedRequired;
}
public void setCachedRequired(boolean cachedRequired) {
isCachedRequired = cachedRequired;
}
}
第 4 步:创建监听器class
进口android.util.Log;
导入 com.google.gson.Gson;
导入 java.io.IOException;
导入 dxswifi_direct.com.wifidirectcommunication.base.model.request.BaseHTTPRequest;
导入 okhttp3.Call;
导入 okhttp3.MediaType;
导入 okhttp3.OkHttpClient;
导入okhttp3.Call返回;
导入 okhttp3.Request;
导入 okhttp3.Request正文;
导入 okhttp3.Response;
/**
* 由 Deepak Sharma 于 2016 年 4 月 7 日创建。
* @电子邮件:dpsharma.sharma1@gmail.com
* 这是一个简单的 java class,它将帮助您实现 HTTP request/response,它将
* 回复你的信件 activity。
*/
public class UpdateListener {
private OnUpdateViewListener onUpdateViewListener;
OkHttpClient okHttpClient = new OkHttpClient();
BaseHTTPRequest mRequestModel;
private String mURL = null;
private Request mRequest = null;
public interface OnUpdateViewListener {
void updateView(String responseString, boolean isSuccess,int reqType);
}
public UpdateListener(OnUpdateViewListener onUpdateView, final BaseHTTPRequest requestModel) {
this.mRequestModel = requestModel;
this.onUpdateViewListener = onUpdateView;
if (requestModel.isCachedRequired())
{
/*File httpCacheDirectory = new File(requestModel.getContext().getCacheDir(), "responses");
Cache cache = null;
cache = new Cache(httpCacheDirectory, 10 * 1024 * 1024);
if (cache != null) {
okHttpClient.setCache(cache);
}*/
}
/*mURL = null;
if (requestModel.getListParameters()!=null && requestModel.getListParameters().size()>0)
{
HttpUrl.Builder urlBuilder = HttpUrl.parse(requestModel.getURL()).newBuilder();
List<RequestParameter> requestParameters = requestModel.getListParameters();
for (int i=0; i<requestParameters.size();i++)
{
urlBuilder.addQueryParameter(requestParameters.get(i).getKey(),requestParameters.get(i).getValue());
}
mURL = urlBuilder.build().toString();
}
else
{
mURL = requestModel.getURL();
}*/
mURL = requestModel.getURL();
if (mRequestModel.getListParameters()!=null && mRequestModel.getListParameters().size()>1)
{
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
mRequest = new Request.Builder()
.url(mURL)
.post(RequestBody.create(JSON, new Gson().toJson(BaseHTTPRequest.class)))
.build();
}
else
{
mRequest = new Request.Builder()
.url(mURL)
.build();
}
}
public void executeRequest()
{
Call call = okHttpClient.newCall(mRequest);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
onUpdateViewListener.updateView(NetworkException.getErrorMessage(e), false, mRequestModel.getRequestCode());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful()) {
// You can also throw your own custom exception
throw new IOException("Unexpected code " + response);
} else {
Log.i("Response:",response.toString());
Log.i("Response body:",response.body().toString());
Log.i("Response message:",response.message());
onUpdateViewListener.updateView(response.body().string(),true, mRequestModel.getRequestCode());
}
// do something wih the result
}
});
}
}
第 5 步:根据您请求的 activity,实施侦听器
public class HitAPIActivity extends AppCompatActivity implements View.OnClickListener, UpdateListener.OnUpdateViewListener{
@Override
public void updateView(final String responseString, boolean isSuccess, int reqType) {
if (isSuccess)
{
if (!responseString.contains("failure")
&& !responseString.contains("Error")) {
// Handle request on the basis of Request Type.
switch (reqType) {
case ApiConstants.GET_CONTACTS:
break;
default:
break;
}
}
}
}
我想在 Android 中使用 OkHttp 网络库。 我从他们网站上写的简单 post 示例开始:
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
通过此调用:
String response = post("http://www.roundsapp.com/post", json);
此调用以 NetworkOnMainThreadException.
结束
我可以用 AsyncTask 包装调用, 但据我从示例中了解到,OkHttp 库应该已经处理好了。
我做错了什么吗?
根据 OkHttp 文档: 它支持同步阻塞调用和带回调的异步调用。 您的示例在主线程上,Android 因为如果您尝试在主线程上进行网络调用,3.0 版会抛出该异常
更好的选择是将它与 retrofit 和 Gson 一起使用: http://square.github.io/retrofit/ https://code.google.com/p/google-gson/
示例如下: http://engineering.meetme.com/2014/03/best-practices-for-consuming-apis-on-android/ http://heriman.net/?p=5
你应该使用 OkHttp 的异步方法。
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
Call post(String url, String json, Callback callback) {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Call call = client.newCall(request);
call.enqueue(callback);
return call;
}
然后您的响应将在回调中处理 (OkHttp 2.x):
post("http://www.roundsapp.com/post", json, new Callback() {
@Override
public void onFailure(Request request, Throwable throwable) {
// Something went wrong
}
@Override public void onResponse(Response response) throws IOException {
if (response.isSuccessful()) {
String responseStr = response.body().string();
// Do what you want to do with the response.
} else {
// Request not successful
}
}
});
或 OkHttp 3.x/4.x:
post("http://www.roundsapp.com/post", "", new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// Something went wrong
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String responseStr = response.body().string();
// Do what you want to do with the response.
} else {
// Request not successful
}
}
});
查看他们的食谱以获取更多示例:http://square.github.io/okhttp/recipes/
如果您按照这些步骤来实现 OKHTTP,那么您肯定会通过仅应用两行代码在多个屏幕上调用多个 API
UpdateListener updateListener = new UpdateListener(HitAPIActivity.this, baseHTTPRequest);
updateListener.getJsonData();
第 1 步:
baseHTTPRequest = new BaseHTTPRequest();
// baseHTTPRequest.setURL("https://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demohttps://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo");
baseHTTPRequest.setURL("http://jsonparsing.parseapp.com/jsonData/moviesDemoItem.txt");
baseHTTPRequest.setRequestCode(reqType);
baseHTTPRequest.setCachedRequired(true);
UpdateListener updateListener = new UpdateListener(HitAPIActivity.this, baseHTTPRequest);
updateListener.executeRequest();
第 2 步:创建请求 class
/** * 由 Deepak Sharma 于 2016 年 4 月 7 日创建。 * 这是一个包含基本参数的 HTTP 请求 class。 * 如果你想添加更多的参数,请做一个 class 的子class * 并添加您的 subclass。不要修改此 class。 */
public class BaseHTTPRequest<T> {
private Context context;
private String URL;
private int requestCode;
private List<T> listParameters;
private String header;
private boolean isCachedRequired;
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
public void setURL(String URL) {
this.URL = URL;
}
public String getURL() {
return URL;
}
public int getRequestCode() {
return requestCode;
}
public void setRequestCode(int requestCode) {
this.requestCode = requestCode;
}
public List<T> getListParameters() {
return listParameters;
}
public void setListParameters(List<T> listParameters) {
this.listParameters = listParameters;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public boolean isCachedRequired() {
return isCachedRequired;
}
public void setCachedRequired(boolean cachedRequired) {
isCachedRequired = cachedRequired;
}
}
第 4 步:创建监听器class
进口android.util.Log; 导入 com.google.gson.Gson; 导入 java.io.IOException; 导入 dxswifi_direct.com.wifidirectcommunication.base.model.request.BaseHTTPRequest; 导入 okhttp3.Call; 导入 okhttp3.MediaType; 导入 okhttp3.OkHttpClient; 导入okhttp3.Call返回; 导入 okhttp3.Request; 导入 okhttp3.Request正文; 导入 okhttp3.Response;
/** * 由 Deepak Sharma 于 2016 年 4 月 7 日创建。 * @电子邮件:dpsharma.sharma1@gmail.com * 这是一个简单的 java class,它将帮助您实现 HTTP request/response,它将 * 回复你的信件 activity。 */
public class UpdateListener {
private OnUpdateViewListener onUpdateViewListener;
OkHttpClient okHttpClient = new OkHttpClient();
BaseHTTPRequest mRequestModel;
private String mURL = null;
private Request mRequest = null;
public interface OnUpdateViewListener {
void updateView(String responseString, boolean isSuccess,int reqType);
}
public UpdateListener(OnUpdateViewListener onUpdateView, final BaseHTTPRequest requestModel) {
this.mRequestModel = requestModel;
this.onUpdateViewListener = onUpdateView;
if (requestModel.isCachedRequired())
{
/*File httpCacheDirectory = new File(requestModel.getContext().getCacheDir(), "responses");
Cache cache = null;
cache = new Cache(httpCacheDirectory, 10 * 1024 * 1024);
if (cache != null) {
okHttpClient.setCache(cache);
}*/
}
/*mURL = null;
if (requestModel.getListParameters()!=null && requestModel.getListParameters().size()>0)
{
HttpUrl.Builder urlBuilder = HttpUrl.parse(requestModel.getURL()).newBuilder();
List<RequestParameter> requestParameters = requestModel.getListParameters();
for (int i=0; i<requestParameters.size();i++)
{
urlBuilder.addQueryParameter(requestParameters.get(i).getKey(),requestParameters.get(i).getValue());
}
mURL = urlBuilder.build().toString();
}
else
{
mURL = requestModel.getURL();
}*/
mURL = requestModel.getURL();
if (mRequestModel.getListParameters()!=null && mRequestModel.getListParameters().size()>1)
{
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
mRequest = new Request.Builder()
.url(mURL)
.post(RequestBody.create(JSON, new Gson().toJson(BaseHTTPRequest.class)))
.build();
}
else
{
mRequest = new Request.Builder()
.url(mURL)
.build();
}
}
public void executeRequest()
{
Call call = okHttpClient.newCall(mRequest);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
onUpdateViewListener.updateView(NetworkException.getErrorMessage(e), false, mRequestModel.getRequestCode());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful()) {
// You can also throw your own custom exception
throw new IOException("Unexpected code " + response);
} else {
Log.i("Response:",response.toString());
Log.i("Response body:",response.body().toString());
Log.i("Response message:",response.message());
onUpdateViewListener.updateView(response.body().string(),true, mRequestModel.getRequestCode());
}
// do something wih the result
}
});
}
}
第 5 步:根据您请求的 activity,实施侦听器
public class HitAPIActivity extends AppCompatActivity implements View.OnClickListener, UpdateListener.OnUpdateViewListener{
@Override
public void updateView(final String responseString, boolean isSuccess, int reqType) {
if (isSuccess)
{
if (!responseString.contains("failure")
&& !responseString.contains("Error")) {
// Handle request on the basis of Request Type.
switch (reqType) {
case ApiConstants.GET_CONTACTS:
break;
default:
break;
}
}
}
}