編輯:關於Android編程
首先需要搭建一個Tomcat服務器,然後測試服務器上的圖片使用PC上的浏覽器是否可以正常下載下來

可以看到服務器上的圖片數據是可以正常訪問的。圖片的地址:http://localhost:8080/meinv.jpg
那如何在我們Android上從網絡下載圖片呢?
直接上獲取網絡圖片的代碼:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void click(View v)
{
//1: 確定網址
String path = http://localhost:8080/meinv.jpg;
try {
//2:把網址封裝為一個URL對象
URL url = new URL(path);
//3:獲取客戶端和服務器的連接對象,此時還沒有建立連接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//4:初始化連接對象
conn.setRequestMethod(GET);
//設置連接超時
conn.setConnectTimeout(5000);
//設置讀取超時
conn.setReadTimeout(5000);
//5:發生請求,與服務器建立連接
conn.connect();
//如果響應碼為200,說明請求成功
if(conn.getResponseCode() == 200)
{
//獲取服務器響應頭中的流
InputStream is = conn.getInputStream();
//讀取流裡的數據,構建成bitmap位圖
Bitmap bm = BitmapFactory.decodeStream(is);
//顯示在界面上
ImageView imageView = (ImageView) findViewById(R.id.lv);
imageView.setImageBitmap(bm);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

從控制台的打印可以是警告: 網絡工作在主線程中異常。
上面的警告就是從4.0以後引入的,如果網絡任務在主線程中,就會報警告。所以我們需要開啟一個線程來執行網絡任務。
修改後的代碼為:
public void click(View v)
{
//開啟一個線程
Thread thread = new Thread()
{
@Override
public void run() {
// TODO Auto-generated method stub
//1: 確定網址
String path = http://localhost:8080/meinv.jpg;
try {
//2:把網址封裝為一個URL對象
URL url = new URL(path);
//3:獲取客戶端和服務器的連接對象,此時還沒有建立連接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//4:初始化連接對象
conn.setRequestMethod(GET);
//設置連接超時
conn.setConnectTimeout(5000);
//設置讀取超時
conn.setReadTimeout(5000);
//5:發生請求,與服務器建立連接
conn.connect();
//如果響應碼為200,說明請求成功
if(conn.getResponseCode() == 200)
{
//獲取服務器響應頭中的流
InputStream is = conn.getInputStream();
//讀取流裡的數據,構建成bitmap位圖
Bitmap bm = BitmapFactory.decodeStream(is);
//顯示在界面上
ImageView imageView = (ImageView) findViewById(R.id.lv);
imageView.setImageBitmap(bm);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
//啟動線程任務
thread.start();
}

又報出一個警告: 調用錯誤線程異常,也就是說只有創建它的view,才能調用該view。 直白點就是只有主線程(UI線程)才能更新UI,別的線程是不能隨便更新UI的。
如果需要更新UI,那只能主線程來更新UI,那別的線程如何告訴主線程需要更新UI呢? 這就需要引入另一個知識點:消息
如果別的線程需要更新UI,就發生消息給主線程,主線程收到後會自動的更新UI
代碼修改為:
if(conn.getResponseCode() == 200)
{
//獲取服務器響應頭中的流
InputStream is = conn.getInputStream();
//讀取流裡的數據,構建成bitmap位圖
Bitmap bm = BitmapFactory.decodeStream(is);
//發生更新UI的消息
Message msg = handler.obtainMessage();
msg.obj = bm;
handler.sendMessage(msg);
//顯示在界面上
//ImageView imageView = (ImageView) findViewById(R.id.lv);
//imageView.setImageBitmap(bm);
}
Handler handler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
//更新UI
ImageView imageView = (ImageView) findViewById(R.id.lv);
imageView.setImageBitmap((Bitmap) msg.obj);
};
};

可以看到圖片正常顯示出來了。
我們再次修改代碼增加獲取失敗的處理邏輯
if(conn.getResponseCode() == 200)
{
//獲取服務器響應頭中的流
InputStream is = conn.getInputStream();
//讀取流裡的數據,構建成bitmap位圖
Bitmap bm = BitmapFactory.decodeStream(is);
//發生更新UI的消息
Message msg = handler.obtainMessage();
msg.obj = bm;
msg.what = GET_OK;
handler.sendMessage(msg);
//顯示在界面上
//ImageView imageView = (ImageView) findViewById(R.id.lv);
//imageView.setImageBitmap(bm);
}
else {
//發送獲取失敗的消息
Message msg = handler.obtainMessage();
msg.what = GET_ERROR;
handler.sendMessage(msg);
}
static final int GET_ERROR = 0;
static final int GET_OK = 1;
Handler handler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
//更新UI
switch (msg.what) {
case GET_OK:
ImageView imageView = (ImageView) findViewById(R.id.lv);
imageView.setImageBitmap((Bitmap) msg.obj);
break;
case GET_ERROR:
Toast.makeText(MainActivity.this, 訪問失敗!, Toast.LENGTH_SHORT).show();
break;
default:
break;
}
};
};

關於消息機制簡單說明一下:
1:發生消息系統會使用消息隊列(MessageQueue)和消息輪詢對象(Looper)
2:消息輪詢對象的作用就是不停的檢測消息隊列中是否有小心,如果一旦有消息,消息輪詢器就會將消息對象交給消息處理器(Handler),處理器會調用handleMessage方法來處理這條消息。handleMessage方法運行在主線程中,所以可以刷新ui
但是平常應用中,比如微信朋友圈的大量圖片,第一次浏覽時都是先緩沖到本地,第二次浏覽時直接從本地讀取即可,那我們來實現一下:
public void click(View v)
{
//指定文件的路徑
final File file = new File(getCacheDir(), info.jpg);
//如果文件存在,直接從本地打開
if(file.exists())
{
System.out.println(從緩存讀取的);
Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());
ImageView imageView = (ImageView) findViewById(R.id.lv);
imageView.setImageBitmap(bm);
}
else {
System.out.println(從網上下載的);
//開啟一個線程
Thread thread = new Thread()
{
@Override
public void run() {
// TODO Auto-generated method stub
//1: 確定網址
String path = http://192.168.1.109:8080/meinv.jpg;
try {
//2:把網址封裝為一個URL對象
URL url = new URL(path);
//3:獲取客戶端和服務器的連接對象,此時還沒有建立連接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//4:初始化連接對象
conn.setRequestMethod(GET);
//設置連接超時
conn.setConnectTimeout(5000);
//設置讀取超時
conn.setReadTimeout(5000);
//5:發生請求,與服務器建立連接
conn.connect();
//如果響應碼為200,說明請求成功
if(conn.getResponseCode() == 200)
{
//獲取服務器響應頭中的流
InputStream is = conn.getInputStream();
//讀取服務器返回流裡的數據,把數據寫入到本地,緩沖起來
FileOutputStream fos = new FileOutputStream(file);
byte[] b = new byte[1024];
int len = 0;
while((len = is.read(b)) != -1)
{
fos.write(b, 0, len);
}
fos.close();
is.close();
//從本地加載圖片
Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());
//讀取流裡的數據,構建成bitmap位圖
//Bitmap bm = BitmapFactory.decodeStream(is);
//發生更新UI的消息
Message msg = handler.obtainMessage();
msg.obj = bm;
msg.what = GET_OK;
handler.sendMessage(msg);
//顯示在界面上
//ImageView imageView = (ImageView) findViewById(R.id.lv);
//imageView.setImageBitmap(bm);
}
else {
//發送獲取失敗的消息
Message msg = handler.obtainMessage();
msg.what = GET_ERROR;
handler.sendMessage(msg);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
//啟動線程任務
thread.start();
}
}
第一次運行時:包文件名下的cache下就會存在info.jpg文件

緩沖文件

當退出再次進來,就會直接從緩沖去獲取

關於從網絡上獲取文件,就簡單的說到這裡
Android中使用ListView繪制自定義表格技巧分享
先上一下可以實現的效果圖 要實現的效果有幾方面 1、列不固定:可以根據數據源的不同生成不同的列數 2、表格內容可以根據數據源的定義合並列 3、要填寫的單元格可
Android - 安裝應用(APP) 不顯示圖標
安裝應用(APP) 不顯示圖標 本文地址:www.2cto.com 在啟動的activity的AndroidManifest注冊中,添加隱式啟
View的事件分發機制學習筆記
好不容易周末有空,作為一個零基礎非計算機專業剛培訓出來7個月的小白,對付博大精深的Android源碼真的是心有余而力不足,但是東西還是要學滴,這不!找到Hongyang大
Android中使用ZXing生成二維碼(支持添加Logo圖案)
ZXing是谷歌的一個開源庫,可以用來生成二維碼、掃描二維碼。本文所介紹的是第一部分。首先上效果圖:ZXing相關各種文件官方下載地址:https://github.co