首页 > 代码库 > Android读取网络图片

Android读取网络图片

  本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020  

      在android4.0之后,已不允许在主线程中进行网络请求操作了, 否则会出现NetworkOnMainThreadException异常。而为了解决在android4.0之上可以进行网络的请求,可以有两种方法来解决,以读取网络的图片为例,先看效果图:


  当点击按钮时,会将指定地址的网络图片加载在imageVIew中进行显示。

读取网络图片:

  1. 获得指定地址网络图片数据

            有两种方式将指定地址的网络读取到Bitmap中,然后通过imageView加载显示。

    1). 将输入流解码成Bitmap

private static String path = "http://221.203.108.70:8080/jxzy/UploadFiles_4517/201005/2010052615165701.jpg";

public Bitmap getData(){
		Bitmap bitmap = null;
		try {
			URL url = new URL(path);
			URLConnection conn = url.openConnection();
			conn.connect();
			InputStream is = conn.getInputStream(); 
			bitmap = BitmapFactory.decodeStream(is);
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return bitmap;
}
  2). 通过字节数据将输入流写入到输入流中,并通过BitmapFactory.decodeByteArray()方法将其转换成Bitmap

public Bitmap getData1(){
		Bitmap bitmap = null;
		ByteArrayOutputStream bos = null;
		try {
			URL url = new URL(path);
			URLConnection conn = url.openConnection();
			InputStream is = conn.getInputStream();
			bos = new ByteArrayOutputStream();
			byte[] data = http://www.mamicode.com/new byte[1024];>
      

       2. 将得到的Bitmap装载在imageView中显示。

       开始也提到了,在android4.0之上不就不能在主线程中直接进行网络请求等操作了,因此为了将网络图片加载到ImageView中,也有两种方法,具体如下:

  方法1:不新建线程;

       直接在onCreate()方法中加入以下两行代码,然后直接在主线程中进行读取网络图片的操作。

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());		   

  有了这两行代码,当然了,这些只适用android4.0之上,你如果targetSDK在4.0之下,也可以不加这两行代码,直接在主线程中进行读取网络图片的操作,但是这种方法并不推荐。

      接下来就是将第一步两种方法得到Bitmap加载到imageView中,主要代码如下:

<span style="white-space:pre">		</span>imageView = (ImageView)findViewById(R.id.imageView);
		
		button = (Button)findViewById(R.id.button);
		button.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				imageView.setImageBitmap(getData());
			}
		});


      方法2: 利用Thread+Handler

      因为,android也不允许在非UI线程中更新UI,所以不能直接将imageView.setImageBitmap()写在线程中,这就要借助于Handler了,因为Handler是运行在主线程中的,所以在读取网络数据利用Message消息来通知Handler来通知更新UI。主要代码如下:

 <span style="white-space:pre">	</span>Handler handler = new Handler(){
		public void handleMessage(Message msg) {
			if(msg.what == 1){
				imageView.setImageBitmap(mBitmap);
			}
		};
	};
	Runnable runnable = new Runnable() {
		
		@Override
		public void run() {
			// TODO Auto-generated method stub
			Message msg = new Message();
			msg.what = 1;
			//mBitmap = getData();
			mBitmap = getData1();
			handler.sendMessage(msg);
		}
	};
      接下来,就是在按钮的单击事件中新建一个线程并启动即可。
<span style="white-space:pre">	</span>button = (Button)findViewById(R.id.button);
		button.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				new Thread(runnable).start();
			}
		});

     最后,给出布局文件,如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >
	<Button 
	    android:id="@+id/button"
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:text="读取网络图片"
	    />
    <ImageView 
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

</RelativeLayout>








Android读取网络图片