android 网络请求管理 简书,android 网络请求

本文分析了如何在Android 4.0及以上版本中避免主线程阻塞,通过异步下载图片并利用缓存机制提高性能。作者详细介绍了在主线程之外处理网络请求的方法,以及如何使用Handler和MessageQueue实现UI更新。
摘要由CSDN通过智能技术生成

网络请求

// 以下代码只能运行在4.0一下, 4.0以上网络请求不能运行在主线程中

public void click1(View v) {

// 下载图片

// 1.确定网址

String path = "http://qxu1192580117.my3w.com/images/1.jpg";

try {

// 2.把网址封装成一个url对象

URL url = new URL(path);

// 3.获取客户端和服务器的连接对象,此时还没有建立连接

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

// 4.连接对象进行初始化

// 设置请求方法,注意大写

conn.setRequestMethod("GET");

// 设置连接超时

conn.setConnectTimeout(5000);

// 设置读取超时

conn.setReadTimeout(5000);

// 5发送请求,与服务器建立连接

conn.connect();

if (conn.getResponseCode() == 200) { // 如果状态码==200,说明请求成功

// 获取服务器响应头中的流,流里面的数据客户端请求的数据

InputStream is = conn.getInputStream();

Bitmap bm = BitmapFactory.decodeStream(is);

ImageView iv = (ImageView) findViewById(R.id.iv_image);

iv.setImageBitmap(bm);

} else {

Toast.makeText(this, "请求失败", 0).show();

}

} catch (MalformedURLException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

主线程阻塞

UI停止刷新,应用程序无法响应用户操作

耗时操作不应该在主线程进行

ANR

application not responding

应用无响应

主线程阻塞时间过长,就会抛出anr异常

主线程又叫UI线程,只有在主线程中才能刷新UI

消息队列机制

主线程创建时,系统会同时创建消息队列对象(MessageQueue)和消息轮询器对象(Looper)

轮询器的作用:不停的检测消息队列中是否有消息(Message)

消息队列一旦有消息,轮询器会把消息对象传给消息处理器Handler,处理器会调用handleMessage()方法来处理这条消息,handleMessage方法运行在主线程中,所以可以刷新UI

子线程如果需要刷新UI,只需要往消息队列发一条消息Message,触发handleMessage方法即可

子线程使用处理器对象的sendMessage()方法发送消息Message

package com.example.imagewatch;

import java.io.IOException;

import java.io.InputStream;

import java.net.HttpURLConnection;

import java.net.MalformedURLException;

import java.net.URL;

import android.app.Activity;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

import android.view.View;

import android.widget.ImageView;

import android.widget.Toast;

public class MainActivity extends Activity {

static ImageView iv;

static MainActivity ma;

static Handler handler = new Handler() {

// 此方法在主线程中调用,可以用来刷新UI

public void handleMessage(Message msg) {

switch (msg.what) {

case 1:

iv.setImageBitmap((Bitmap) msg.obj);

break;

case 2:

Toast.makeText(ma, "请求失败", 0).show();

break;

default:

break;

}

};

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}

// 以下代码可以在4.0以上运行

public void click2(View v) {

iv = (ImageView) findViewById(R.id.iv_image);

ma = this;

Thread thread = new Thread() {

@Override

public void run() {

// 下载图片

// 1.确定网址

String path = "http://qxu1192580117.my3w.com/images/1.jpg";

try {

// 2.把网址封装成一个url对象

URL url = new URL(path);

// 3.获取客户端和服务器的连接对象,此时还没有建立连接

HttpURLConnection conn = (HttpURLConnection) url

.openConnection();

// 4.连接对象进行初始化

// 设置请求方法,注意大写

conn.setRequestMethod("GET");

// 设置连接超时

conn.setConnectTimeout(5000);

// 设置读取超时

conn.setReadTimeout(5000);

// 5发送请求,与服务器建立连接

conn.connect();

if (conn.getResponseCode() == 200) { // 如果状态码==200,说明请求成功

// 获取服务器响应头中的流,流里面的数据客户端请求的数据

InputStream is = conn.getInputStream();

Bitmap bm = BitmapFactory.decodeStream(is);

// 把消息发送至主线程队列

Message msg = new Message();

// 消息对象可以携带数据

msg.obj = bm;

msg.what = 1;

handler.sendMessage(msg);

} else {

Message msg = handler.obtainMessage();

msg.what = 2;

handler.sendMessage(msg);

}

} catch (MalformedURLException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

};

thread.start();

}

}

代码优化,增加图片缓存

public class MainActivity extends Activity {

static ImageView iv;

static MainActivity ma;

static Handler handler = new Handler() {

// 此方法在主线程中调用,可以用来刷新UI

public void handleMessage(Message msg) {

switch (msg.what) {

case 1:

iv.setImageBitmap((Bitmap) msg.obj);

break;

case 2:

Toast.makeText(ma, "请求失败", 0).show();

break;

default:

break;

}

};

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}

// 以下代码可以在4.0以上运行

public void click2(View v) {

final String path = "http://qxu1192580117.my3w.com/images/1.jpg";

final File file = new File(getCacheDir(), getFileName(path));

iv = (ImageView) findViewById(R.id.iv_image);

ma = this;

// 如果缓存存在该图片,则从缓存读取

if (file.exists()) {

System.out.println("从缓存读取的");

Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());

iv.setImageBitmap(bm);

} else {// 从网络读取

Thread thread = new Thread() {

@Override

public void run() {

System.out.println("从网络读取");

// 下载图片

// 1.确定网址

try {

// 2.把网址封装成一个url对象

URL url = new URL(path);

// 3.获取客户端和服务器的连接对象,此时还没有建立连接

HttpURLConnection conn = (HttpURLConnection) url

.openConnection();

// 4.连接对象进行初始化

// 设置请求方法,注意大写

conn.setRequestMethod("GET");

// 设置连接超时

conn.setConnectTimeout(5000);

// 设置读取超时

conn.setReadTimeout(5000);

// 5发送请求,与服务器建立连接

conn.connect();

if (conn.getResponseCode() == 200) { // 如果状态码==200,说明请求成功

// 获取服务器响应头中的流,流里面的数据客户端请求的数据

InputStream is = conn.getInputStream();

// 读取服务器返回的流数据,把数据写到本地文件,缓存起来

FileOutputStream fos = new FileOutputStream(file);

byte[] b = new byte[1024];

int len = 0;

while ((len = is.read(b)) != -1) {

fos.write(b, 0, len);

}

fos.close();

Bitmap bm = BitmapFactory.decodeFile(file

.getAbsolutePath());

// 把消息发送至主线程队列

Message msg = new Message();

// 消息对象可以携带数据

msg.obj = bm;

msg.what = 1;

handler.sendMessage(msg);

} else {

Message msg = handler.obtainMessage();

msg.what = 2;

handler.sendMessage(msg);

}

} catch (MalformedURLException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

};

thread.start();

}

}

private String getFileName(String path) {

return path.substring(path.lastIndexOf("/") + 1);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值