HTTPURLConnection总结
之前说过安卓网络一般都是http协议的,其实觉得工作原理就是客户端向服务器发一条请求,服务器收到这个请求就返回相应的东西,然后客户端解析就好了,再把解析的数据处理下。安卓有很多网络框架,但是实质上还是HTTPURLConnection为基础的东西,只不过就是他们封装的好一些,或者优化了不少。
HttpURLConnection的工作原理
Http协议工作原理特别的简单,就是客户端向服务器发出一条HTTP请求,服务器收到请求之后会返回一些数据给客户端,然后客户端再对这些数据进行解析和处理就可以了。
我们可以简单理解为,客户端发送一个URL,通过这个URL就可以找到服务器,然后服务器通过地址一看,就知道你要什么东西,就返回数据给你。
我们都知道计算式的所有数据是0和1的数据,这些数据我们可以想象成小水滴,小水滴的传输我们需要一个管道,从我们这里流出去的,叫做输出流,可从别人那里流过来的,叫做输入流
判断输入流还是输出流 :都是相对自身而言的。
安卓的耗时操作的逻辑不能写在主线程,必须写在子线程(I/O流操作肯定是耗时,肯定得写在子线程)
I/O流的简单操作//I就是input,O就是output
HttpURLConnection的工作过程
- 得到URL
- 开启连接
- 声明是那种方式 是发送还是接收
- 打开流
- 对流进行操作
- 关闭流
URL url = new URL(requestUrl); // 打开一个HttpURLConnection连接
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
// 设置连接主机超时时间
urlConn.setConnectTimeout(5 * 1000);
// 设置从主机读取数据超时
urlConn.setReadTimeout(5 * 1000);
// 设置是否使用缓存 默认是true
urlConn.setUseCaches(true); /
/ 设置为Post请求 urlConn.setRequestMethod("GET");
// urlConn设置请求头信息
// 设置请求中的媒体类型信息。
urlConn.setRequestProperty("Content-Type", "application/json");
// 设置客户端与服务连接类型 urlConn.addRequestProperty("Connection", "Keep-Alive");
// 开始连接 urlConn.connect();
// 判断请求是否成功 if (urlConn.getResponseCode() == 200)
{ // 获取返回的数据
String result = streamToString(urlConn.getInputStream());
Log.e(TAG, "Get方式请求成功,result--->" + result); }
else { Log.e(TAG, "Get方式请求失败"); }
// 关闭连接 urlConn.disconnect(); }
catch (Exception e)
}
}
注意
1HttpURLConnection的connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。 无论是post还是get,http请求实际上HttpURLConnection的getInputStream()这个函数里面才正式发送出去。
2在用POST方式发送URL请求时,URL请求参数的设定顺序是重中之重,对connection对象的一切配置(那一堆set函数) 都必须要在connect()函数执行之前完成。而对outputStream的写操作,又必须要在inputStream的读操作之前。这些顺序实际上是由http请求的格式决定的。
3http请求实际上由两部分组成,一个是http头,所有关于此次http请求的配置都在http头里面定义, 一个是正文content。connect()函数会根据HttpURLConnection对象的配置值生成http头部信息,因此在调用connect函数之前,就必须把所有的配置准备好。
4在http头后面紧跟着的是http请求的正文,正文的内容是通过outputStream流写入的,实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络, 而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。至此,http请求的东西已经全部准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求 正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回信息。由于http 请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数 之后对connection对象进行设置(对http头的信息进行修改)或者写入outputStream(对正文进行修改)都是没有意义的了,执行这些操作会导致异常的发生。
简单的网络请求练习
就简单的输入URL在网上获取这张图片,然后放在app里面
效果图
第一步:打开网络权限//这个肯定是必须的啊
在res/androidManifest.xml里面添加权限
第二步:布局界面
这个也蛮简单的就是一个ImagView和EditText再加上一个Button
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http:///apk/res/android"
xmlns:tools="http:///tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
<EditText
android:id="@+id/et_path"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="输入图片的路径"
android:singleLine="true"/>
<Button
android:id="@+id/bt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="获取" />
</LinearLayout>
第三步:MainActivity
就是网络请求这块重新开个线程 然后用handler控制一下
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button bt;
private ImageView show;
private EditText et;
private HttpURLConnection conn;
private String path;
private Bitmap bitmap;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if (msg.what==1){
bitmap = (Bitmap)msg.obj;
show.setImageBitmap(bitmap);
}else if (msg.what==0){
Toast.makeText(MainActivity.this,"失败",Toast.LENGTH_SHORT).show();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et = (EditText) findViewById(.et_path);
show = (ImageView) findViewById(.iv);
bt = (Button) findViewById(.bt);
bt.setOnClickListener(this);
et.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case .bt:
path = et.getText().toString().trim();
//子线程网络请求
Log.d("233","1");
if (TextUtils.isEmpty(path)) {
Toast.makeText(MainActivity.this, "路径不为空", Toast.LENGTH_SHORT).show();
} else {
sendConnection();
Log.d("233","1");
}
}
}
private void sendConnection(){
new Thread(new Runnable() {
@Override
public void run() {
URL url;
try {
url = new URL(path);
//打开连接
conn = (HttpURLConnection)url.openConnection();
//设置请求方式
conn.setRequestMethod("GET");
//超时时间
conn.setReadTimeout(5000);
//得到服务器的返回码
int code =conn.getResponseCode();
if (code==200){
//获取服务器的返回输入流
InputStream is = conn.getInputStream();
//转换成BIth对象
bitmap = BitmapFactory.decodeStream(is);
Message msg = new Message();
msg.what =1;
msg.obj=bitmap;
handler.sendMessage(msg);
}else {
Message message = new Message();
message.what = 0;
handler.sendMessage(message);
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
总结
网络这块虽然以后用的别人的框架,但是最基础的还是要会的,就是一个简单的小Dome,最近自己要抓紧时间学习了哇哇哇,没时间了哇咔咔。
Dome的git地址https:///sakurakid/HttpDome