前段时间看到一个数据,据说中国网民数量已经达到7亿多,看到这个数字就尿了,现在连小学生玩微信都啪啪啪的6,作为移动应用开发者,你的APP要是没有联网功能的话那就太low了,当然要让APP进行一些网络请求也不是扫码难事,今天咱就来一起加载一个网络图片玩玩。
首先你要准备一张用于加载的网络图片,取到它的网络地址,当然为了方便,我用Tomcat在本地搭建了一个web服务器,把它运行,图片放到我web服务器的根目录下。
服务器启动以后,在我的浏览器访问图片。
OK,是可以访问的,我的图片就是放在上边那个地址所对应的服务器位置里,它就是一个网络图片,当然你可以从网上找你喜欢的图片地址。
准备工作做好以后,下面就要在安卓应用中去请求网络加载它了。
我在创建好安卓工程后,制作了下面这样的布局,很简单,就是一个Button,下面还有一个ImageView。
接着就是在Activity里声明初始和化View控件了
private ImageView iv_downpic_main;
public void downPic (View v) {
<span style="white-space:pre"> </span>//图片的网络path路径
<span style="white-space:pre"> String path = "http://192.168.0.109:8080/cool_man.jpg";</span>
<span style="white-space:pre"> </span>//声明一个连接对象
<span style="white-space:pre"> HttpURLConnection conn = null;
//声明一个输入流</span>
<span style="white-space:pre"> InputStream is = null;
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>try {
<span style="white-space:pre"> </span>URL url = new URL(path);</span>
<span style="white-space:pre"><span style="white-space:pre"> </span>//打开url连接
<span style="white-space:pre"> </span>conn = (HttpURLConnection) url.openConnection();</span>
<span style="white-space:pre"><span style="white-space:pre"> </span>//设置请求方式为GET
<span style="white-space:pre"> </span>conn.setRequestMethod("GET");</span>
<span style="white-space:pre"><span style="white-space:pre"> </span>//设置连接超时时间为5秒
<span style="white-space:pre"> </span>conn.setConnectTimeout(5000);</span>
<span style="white-space:pre"><span style="white-space:pre"> </span>//设置读取超时时间为5秒
<span style="white-space:pre"> </span>conn.setReadTimeout(5000);</span>
<span style="white-space:pre"><span style="white-space:pre"> </span>//建立连接
<span style="white-space:pre"> </span>conn.connect();
<span style="white-space:pre"> //如果返回的请求码为200的话 </span>
<span style="white-space:pre"> </span>if(conn.getResponseCode() == 200){</span>
<span style="white-space:pre"><span style="white-space:pre"> </span>//得到一个连接输入流
<span style="white-space:pre"> <span style="white-space:pre"> </span></span>is = conn.getInputStream();</span>
<span style="white-space:pre"><span style="white-space:pre"> </span>//用bitmap读取输入流
<span style="white-space:pre"> <span style="white-space:pre"> </span></span>bitmap = BitmapFactory.decodeStream(is);</span>
<span style="white-space:pre"><span style="white-space:pre"> </span>//设置图片为bitmap读取到的图片
<span style="white-space:pre"> <span style="white-space:pre"> </span></span>iv_downpic_main.setImageBitmap(bitmap);
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>} else {</span>
<span style="white-space:pre"><span style="white-space:pre"> </span>//请求码不为200的话,toast提示请求失败
<span style="white-space:pre"> <span style="white-space:pre"> </span></span>Log.e("TAG", "请求失败!");//
<span style="white-space:pre"> <span style="white-space:pre"> </span></span>Toast.makeText(MainActivity.this, "请求失败!", 0).show();
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>} catch (Exception e) {
<span style="white-space:pre"> </span>// TODO Auto-generated catch block
<span style="white-space:pre"> </span>e.printStackTrace();
<span style="white-space:pre"> </span>}finally{
<span style="white-space:pre"> </span>if(conn != null){</span>
<span style="white-space:pre"><span style="white-space:pre"> </span>//关闭连接
<span style="white-space:pre"> </span>conn.disconnect();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>if(is != null){
<span style="white-space:pre"> </span>try {</span>
<span style="white-space:pre"><span style="white-space:pre"> </span>//关闭输入流
<span style="white-space:pre"> </span>is.close();
<span style="white-space:pre"> </span>} catch (IOException e) {
<span style="white-space:pre"> </span>// TODO Auto-generated catch block
<span style="white-space:pre"> </span>e.printStackTrace();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}</span>
</pre><pre name="code" class="java">
}
这样的方法在安卓4.0之前是行的通的,然而在安卓4.0以后,这些代码就不好使了,为避免ANR的产生,程序在进行联网等耗时操作时是禁止在主线程里执行的。
改进的做法是,把联网获取图片的操作拿到分线程去执行,然而跟新UI界面的操作用Handler在主线程进行UI跟新。
public class MainActivity extends Activity {
private static final int WHAT_DAWNLOAD_PICTURE = 0;
protected static final int WAHT_TOAST = 1;
private ImageView iv_downpic_main;
private Bitmap bitmap;
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 0:
iv_downpic_main.setImageBitmap(bitmap);
break;
case 1 :
Toast.makeText(MainActivity.this, "请求失败!", 0).show();
break;
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv_downpic_main = (ImageView) findViewById(R.id.iv_downpic_main);
}
public void downPic (View v) {
final String path = "http://192.168.0.109:8080/cool_man.jpg";
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection conn = null;
InputStream is = null;
try {
URL url = new URL(path);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.connect();
if(conn.getResponseCode() == 200){
is = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
handler.sendEmptyMessage(WHAT_DAWNLOAD_PICTURE);
} else {
Log.e("TAG", "请求失败!");//
handler.sendEmptyMessage(WAHT_TOAST);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(conn != null){
conn.disconnect();
}
if(is != null){
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}).start();
}
}
这里要说的是,Toast提示信息也需要在主线程进行跟新,如果单独把它放在分线程执行的话,是么有效果的,而且后台也会报错:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
代码写好以后,就运行测试吧。
点击按钮把酷男显示出来。
效果还不错!