李老師安卓筆記:加載網絡圖片

前段時間看到一個數據,據說中國網民數量已經達到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()


代碼寫好以後,就運行測試吧。

點擊按鈕把酷男顯示出來。


效果還不錯!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章