27.Android之ImageView获取图片学习
今天来学习imageview获得图片方法,实现本地访问和网络访问图片功能。
首先布局文件增加两个按钮和imageview控件:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 8 <LinearLayout 9 android:orientation="horizontal" 10 android:layout_width="match_parent" 11 android:layout_height="wrap_content" 12 android:layout_gravity="center_horizontal"> 13 14 <Button 15 android:layout_width="wrap_content" 16 android:layout_height="wrap_content" 17 android:text="读取本地图片" 18 android:id="@+id/get_localimg" /> 19 20 <Button 21 android:layout_width="wrap_content" 22 android:layout_height="wrap_content" 23 android:text="获取网络图片" 24 android:id="@+id/get_netimg" /> 25 </LinearLayout> 26 27 <ImageView 28 android:layout_width="wrap_content" 29 android:layout_height="wrap_content" 30 android:id="@+id/img_show" /> 31 </LinearLayout>
修改MainActivity.java文件:
1 package com.example.administrator.imageviewdemo; 2 3 import android.app.Activity; 4 import android.graphics.Bitmap; 5 import android.graphics.BitmapFactory; 6 import android.os.Bundle; 7 import android.os.Environment; 8 import android.os.Handler; 9 import android.util.Log; 10 import android.view.View; 11 import android.widget.Button; 12 import android.widget.ImageView; 13 14 import java.io.FileInputStream; 15 import java.io.FileNotFoundException; 16 import java.io.IOException; 17 import java.io.InputStream; 18 import java.net.HttpURLConnection; 19 import java.net.MalformedURLException; 20 import java.net.URL; 21 22 23 public class MainActivity extends Activity { 24 25 private Button btn_get_local; 26 private Button btn_get_net; 27 private ImageView iv; 28 private Handler handler = null; 29 private Bitmap bp = null; 30 private static final String TAG = MainActivity.class.getSimpleName(); 31 String imgFilePath = Environment.getExternalStorageDirectory().toString(); 32 33 @Override 34 protected void onCreate(Bundle savedInstanceState) { 35 super.onCreate(savedInstanceState); 36 setContentView(R.layout.activity_main); 37 38 handler = new Handler(); 39 btn_get_local = (Button) findViewById(R.id.get_localimg); 40 btn_get_net = (Button) findViewById(R.id.get_netimg); 41 iv = (ImageView) findViewById(R.id.img_show); 42 43 //访问本地路径图片 44 btn_get_local.setOnClickListener(new View.OnClickListener() { 45 @Override 46 public void onClick(View v) { 47 Log.e(TAG, "image path = " + imgFilePath); 48 new Thread() { 49 public void run() { 50 try { 51 String str = "/storage/sdcard0/DCIM/local_img.jpg"; 52 FileInputStream fis = new FileInputStream(str); 53 bp = BitmapFactory.decodeStream(fis); 54 handler.post(runnableUi); 55 56 } catch (IOException e) { 57 e.printStackTrace(); 58 } 59 60 } 61 }.start(); 62 63 } 64 }); 65 66 67 //访问网络路径图片 68 btn_get_net.setOnClickListener(new View.OnClickListener() { 69 @Override 70 public void onClick(View v) { 71 new Thread() { 72 73 public void run() { 74 try { 75 InputStream inputStream = HttpUtils.getImageViewInputStream(); 76 bp = BitmapFactory.decodeStream(inputStream); 77 handler.post(runnableUi); 78 79 } catch (IOException e) { 80 e.printStackTrace(); 81 } 82 83 } 84 }.start(); 85 86 } 87 }); 88 89 90 } 91 92 // 构建Runnable对象,在runnable中更新界面 93 Runnable runnableUi = new Runnable() { 94 @Override 95 public void run() { 96 //显示图片 97 iv.setImageBitmap(bp); 98 99 } 100 101 }; 102 103 104 // public static Bitmap getLoacalBitmap(String url) { 105 // try { 106 // FileInputStream fis = new FileInputStream(url); 107 // return BitmapFactory.decodeStream(fis); 108 // } catch (FileNotFoundException e) { 109 // e.printStackTrace(); 110 // return null; 111 // } 112 // } 113 114 // public static Bitmap getHttpBitmap(String url) { 115 // URL mNetUrl = null; 116 // Bitmap bitmap = null; 117 // try { 118 // Log.e(TAG, url); 119 // mNetUrl = new URL(url); 120 // } catch (MalformedURLException e) { 121 // e.printStackTrace(); 122 // } 123 // try { 124 // //打开连接 125 // HttpURLConnection conn = (HttpURLConnection) mNetUrl.openConnection(); 126 // //设置网络连接超时的时间为7秒 127 // conn.setConnectTimeout(7000); 128 // //打开输入流 129 // conn.setDoInput(true); 130 // //连接 131 // conn.connect(); 132 // //获取输入流 133 // InputStream is = conn.getInputStream(); 134 // bitmap = BitmapFactory.decodeStream(is); 135 // is.close(); 136 // } catch (IOException e) { 137 // e.printStackTrace(); 138 // } 139 // return bitmap; 140 // } 141 142 143 }
增加一个访问网络HttpUtils类:
1 package com.example.administrator.imageviewdemo; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.net.HttpURLConnection; 7 import java.net.URL; 8 9 public class HttpUtils { 10 11 //访问网络图片的路径 12 private final static String URL_PATH = "http://img.hb.aicdn.com/5eb8e4b4c43ae5a64cb888c811faa6b16d7495e5edad-rDDIRz_fw658"; 13 14 public HttpUtils() { 15 // TODO Auto-generated constructor stub 16 } 17 18 /** 19 * 从网络中获取图片信息,以流的形式返回 20 * @return 21 * @throws IOException 22 */ 23 public static InputStream getImageViewInputStream() throws IOException{ 24 25 InputStream inputStream = null; 26 URL url = new URL(URL_PATH); 27 if(url != null){ 28 //打开连接 29 HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection(); 30 //设置连接超时的时间 31 httpURLConnection.setConnectTimeout(3000); 32 //设置请求方法为GET 33 httpURLConnection.setRequestMethod("GET"); 34 //打开输入流 35 httpURLConnection.setDoInput(true); 36 //设置响应的代码 37 int response_code = httpURLConnection.getResponseCode(); 38 if(response_code == 200){ 39 //获取输入流 40 inputStream = httpURLConnection.getInputStream(); 41 } 42 } 43 44 return inputStream; 45 } 46 }
运行效果:
1)点击"读取本地图片“按钮显示如图:
2)点击"获取网络图片"按钮显示:
问题总结:
1.一开始我写访问图片没有用线程出现”Only the original thread that created a view hierarchy can touch“之类错误,这个错误很常见,基本上写线程操作都遇到过这个错误。根本原因是view控件的线程安全问题,通俗点讲就是所有的更新UI操作都需要在主线程(也就是UI线程中完成),而不能在新开的子线程中操作。
基本思路:既然子线程需要更新UI,但子线程自身又不能完成任务,所以只能通过建立一个通信机制,当子线程需要更新UI时,发消息通知主线程并将更新UI的任务post给主线程,让主线程来完成分内的UI更新操作。这个机制是什么呢?就是Handler。Handler 从属于谁?当然是主线程。每个线程都有自己的handler,来处理自己的消息队列,只不过平时写单线程操作,系统会缺省调用一个handler,对开发者透明。当多线程操作需要线程间通信时,handler才会被程序员们显示调用。
2.访问本地图片路径问题,一般图片文件都会放在DCIM文件夹下,而/storage/sdcard0我们可以通过Environment.getExternalStorageDirectory()方法获得这绝对路径,在加上自己放图片路径就是整个本地图片路径,其实我们adb shell控制台看到图片文件存放地址,比如我的local_img.jpg存放位置如图: