网络图片查看器带缓存版
核心代码如下:
public class MainActivity extends Activity {
protected static final int SET_IMAGE = 1;
protected static final int ERROR = 2;
protected static final int FAILED = 3;
protected static final String TAG = "MainActivity";
private EditText et_url;
private ImageView iv_image;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case ERROR:
Toast.makeText(MainActivity.this, "图片url不能为空。。。", 0).show();
break;
case SET_IMAGE:
Bitmap bitmap = (Bitmap) msg.obj;
iv_image.setImageBitmap(bitmap);
break;
case FAILED:
Toast.makeText(MainActivity.this, "获取图片失败", 0).show();
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv_image = (ImageView) this.findViewById(R.id.iv_image);
et_url = (EditText) this.findViewById(R.id.et_url);
}
/**
* 点击查看图片
*
* @param view
*/
public void viewImage(View view) {
// 1、获取用户输入的url,并判空
final String url = et_url.getText().toString().trim();
if (TextUtils.isEmpty(url)) {
Looper.prepare();
Message msg = new Message();
msg.what = ERROR;
handler.sendMessage(msg);
// Toast.makeText(MainActivity.this, "图片url不能为空。。。", 0).show();
return;
}
// 7、判断请求的文件是否在缓存中,如果在,那么取出来,没有就去服务器上 下载
File imageFile = new File(MainActivity.this.getCacheDir(),getFileName(url));
if (imageFile != null && imageFile.exists()) {
iv_image.setImageURI(Uri.parse(imageFile.toString()));
Log.i(TAG, "文件从缓存中取出。。。");
}else {
Log.i(TAG, "文件从服务器下载。。。");
new Thread() { // 重新创建一个Thread处理请求网络的连接
// 原因: 访问网络 耗时的操作 需要一定的时间 为了避免界面卡死 无响应
// 4.0系统做了一个处理所有的网络访问的操作是不可以在主线程里面执行,所以要开启一个新的线程.
@Override
public void run() {
try {
// 2、将地址包装成url
URL imageUrl = new URL(url);
// 3、获取一个HttpURLConnection
HttpURLConnection conn = (HttpURLConnection) imageUrl
.openConnection();
// 4、设置请求头信息
conn.setRequestMethod("GET");// 设置http的请求方式 get / post 注意单词大写
conn.setConnectTimeout(5000);// 连接两秒超时
conn.setReadTimeout(5000);// 读取两秒超时
String userAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C)";
conn.setRequestProperty("User-Agent", userAgent);
// 5、获取服务器返回信息
int code = conn.getResponseCode();
if (code == 200) { // 返回正确码
InputStream in = conn.getInputStream();// 得到服务器返回的输入流
// 6、将图片给缓存起来
File file = new File(MainActivity.this.getCacheDir(), getFileName(url));
FileOutputStream fos = new FileOutputStream(file);
int len = 0;
byte[] buf = new byte[1024];
while ((len = in.read(buf)) != -1) {
fos.write(buf, 0, len);
}
// iv_image.setImageBitmap(bitmap);
Bitmap bitmap = BitmapFactory.decodeStream(in);
Message message = new Message();
message.what = SET_IMAGE;
message.obj = bitmap;
handler.sendMessage(message);
} else {
// Toast.makeText(MainActivity.this, "请求失败", 0).show();
}
} catch (MalformedURLException e) {
e.printStackTrace();
Message msg = new Message();
msg.what = FAILED;
handler.sendMessage(msg);
// Toast.makeText(MainActivity.this, "获取图片失败",
// 0).show();
} catch (IOException e) {
e.printStackTrace();
Message msg = new Message();
msg.what = FAILED;
handler.sendMessage(msg);
// Toast.makeText(MainActivity.this, "获取图片失败",
// 0).show();
}
}
}.start();
}
}
/**
* 根据请求的url获取文件名
*
* @param url url路径
* @return 请求的文件名
*/
public String getFileName(String url) {
int index = url.lastIndexOf("/");
String filename = url.substring(index + 1);
return filename;
}
}
思路及注意事项和用到的重要的api
思路:
- 每次去获取图片的时候先去判断一下缓存文件中有没有我们想要下载的那张照片
- 若有,直接把这张照片取出来,显示出来
- 若缓存文件中没有这张照片,就连接网络去获取照片
- 从网络中获取到的照片存到缓存文件中,把图片存到缓存文件中的好处是提高下次打开软件的的操作 体验,避免每次获取图片都是从网络中下载,这样的操作体验就太差了,也太费流量了.
注意事项
- 连网络一定要在子线程去操作
- 获取的数据做的严谨一点的话要先判断一下是什么类型的数据
- 图片流数据的解码可以用 BitmapFactory.decodeStream(in);这个 api来操作,返回一个bitmap对象
- 在子线程不能更新UI,要更新UI的时候应该用Handler对象发消息给主线程,也就是用消息机制来解决更新UI的问题
- 要记得添加访问网络的权限
使用到的重要api
- getCacheDir()获取手机缓存文件夹地址
- openConnection();获得 HttpURLConnection连接
- setRequestMethod(“GET”);// 设置http的请求方式
- setConnectTimeout(5000);// 设置连接网络的超时时间
- setReadTimeout(5000);//设置读取数据的超时时间
- setRequestProperty(“User-Agent”, userAgent);设置访问服务器的机器类型
- getInputStream();//得到服务器返回的数据流
- BitmapFactory.decodeStream(in);//把数据流解析成Bitmap图片类型