一、HttpURLConnection简介
标准Java接口(java.net) ,HttpURLConnection,可以实现简单的基于URL请求、响应功能。示例如下:
//请求网络数据
private String requestData(String cityName) {
try {
URL url = new URL("http://apis.baidu.com/heweather/weather/free?city=" + cityName);
//某一用于获取天气数据的免费API接口,参数为城市名
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(30000);
//设置连接限时
connection.setRequestMethod("GET");
// 设置模式,分GET/POST, 区别如下
// a:) get请求可以获取静态页面,也可以把参数放在URL字串后面,传递给servlet,
// b:) post与get的不同之处在于post的参数不是放在URL字串里面,而是放在http请求的正文内。
connection.setRequestProperty("apikey", "56703948b38c34b4a41557b55968739b");
//设置Header参数APIKEY的值(该API限制)
connection.connect();
//以上的设置必须置于该连接命令前
int responseCode = connection.getResponseCode();
String responseMessage = connection.getResponseMessage();
Log.d("MainActivity", "code:" + responseCode);
String result = null;
if(responseCode == HttpURLConnection.HTTP_OK){
InputStream inputStream = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine())!= null){
response.append(line);
}
}
return result;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
注意事项:
a:) HttpURLConnection的connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。
无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。
b:) 在用POST方式发送URL请求时,URL请求参数的设定顺序是重中之重, 对connection对象的一切配置(那一堆set函数) 都必须要在connect()函数执行之前完成。而对outputStream的写操作,又必须要在inputStream的读操作之前。 这些顺序实际上是由http请求的格式决定的。
如果inputStream读操作在outputStream的写操作之前,会抛出例外: java.net.ProtocolException: Cannot write output after reading input…….
c:) http请求实际上由两部分组成, 一个是http头,所有关于此次http请求的配置都在http头里面定义,一个是正文content。
connect()函数会根据HttpURLConnection对象的配置值生成http头部信息,因此在调用connect函数之前,就必须把所有的配置准备好。
d:) 在http头后面紧跟着的是http请求的正文,正文的内容是通过outputStream流写入的,实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络, 而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文
二、网络请求为耗时操作,必须异步执行,此处可利用AsyncTask类
class RequestNetworkDataTask extends AsyncTask<String, Integer, String>{
//在后台处理之前,在主线程中执行(可执行UI操作)
@Override
protected void onPreExecute() {
super.onPreExecute();
//UI Loading
}
//异步操作,此处执行上述网络请求
@Override
protected String doInBackground(String[] params) {
String str;
try {
str = requestData(params[0]);
} catch (Exception e){
str = null;
}
return str;
}
//执行完之后,在主线程中的操作
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if (s == null){
Toast.makeText(MainActivity.this, "网络连接失败", Toast.LENGTH_SHORT).show();
return;
}
if (!s.contains("unknown city")) {
//利用ContentResolver存入数据库,可忽略
ContentResolver contentResolver = getContentResolver();
Uri uri = Uri.parse("content://com.example.binh/WeatherData");
contentResolver.delete(uri, null, null);
ContentValues values = new ContentValues();
values.put("city_name", getCityName());
values.put("city_weather", s);
contentResolver.insert(uri, values);
showWeather(s);
Toast.makeText(MainActivity.this, "天气更新成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "城市名(拼音)输入有误", Toast.LENGTH_SHORT).show();
}
}
}
调用语句:new RequestNetworkDataTask().execute(cityName);
三、网络请求返回的数据多数为JSON格式,可利用GSON解码
第一步,添加GSON支持:
打开Project Structure设置,选择Dependencies标签页,点击“+”,选择“1、Library dependency”,搜索com.google.code.gson:gson:2.6.2(或其他版本),点击OK。
Gson gson = new Gson();
weatherData = gson.fromJson(s, WeatherData.class);
参数s为网络请求返回的jsonString字符串;WeatherData为数据类名,和JSON内的key一一对应。该类可利用GsonFormat插件快速生成:
GsonFormat安装方法:
1、Android studio File->Settings..->Plugins–>Browse repositores..
2、搜索GsonFormat;
3、安装插件;
4、重启android studio。
GsonFormat插件主要是用于一键创建实体类的,创建一个类,在类的内部使用alt+Inset后,在弹出的对话框中将json数据粘贴到里边,json格式正确即可生成对应的类。