android显示网络图片控件,Android控件之ImageView(二)
前言
在上一篇文章中,我們講解了如何加載本地圖片,那么在實際項目中 ImageView 大多數(shù)使用場景是加載網(wǎng)絡(luò)圖片,網(wǎng)絡(luò)圖片其實就是存儲在服務(wù)器上的文件,我們需要從服務(wù)器獲取到文件的二進制輸入流 Inpustream ,然后將其轉(zhuǎn)化為 ImageView 可以加載的 Bitmap 對象。實現(xiàn)網(wǎng)絡(luò)圖片的加載。
這篇文章我們通過使用原始的網(wǎng)絡(luò)連接和使用第三庫來簡單講解 ImageView 網(wǎng)絡(luò)圖片的加載。
怎么使用原始方式加載網(wǎng)絡(luò)圖片?
第三方網(wǎng)絡(luò)圖片加載庫與原始加載庫的對比?
怎樣使用第三方網(wǎng)絡(luò)加載庫加載圖片?
使用原始方式加載網(wǎng)絡(luò)圖片
先上代碼(主要分為三大步驟):
1~6 : 從網(wǎng)絡(luò)獲取圖片。由于Android 系統(tǒng)規(guī)定網(wǎng)絡(luò)請求操作需要在子線程完成。主要是因為網(wǎng)絡(luò)請求屬于耗時操作,如果在主線程發(fā)起網(wǎng)絡(luò)請求會導(dǎo)致主線程在網(wǎng)絡(luò)請求期間,無法及時響應(yīng)用戶的操作,
7:利用在 Activity聲明的 Handler對象把在子線從網(wǎng)絡(luò)獲取到的 Bitmap 對象,轉(zhuǎn)移到 UI 線程。
8 : 更新UI。
public class ImageNetActivity extends AppCompatActivity {
/**
* 7.要知道 這里現(xiàn)在是子線程 更新UI的操作需要在主線程(UI線程)完成。
* 在 Activity 中聲明 Handler 對象,并復(fù)寫它的 handleMessage 方法
*/
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1010) {
Bitmap bitmap = (Bitmap) msg.obj;
setImageView(bitmap);
}
}
};
private ImageView mImageView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_net);
mImageView = findViewById(R.id.image);
loadImageUrl("https://cdn.pixabay.com/photo/2017/05/09/23/02/dog-2299482_960_720.jpg");
}
private void loadImageUrl(final String imageUrl) {
// Android 系統(tǒng)強制網(wǎng)絡(luò)請求需要在子線程操作
new Thread(new Runnable() {
@Override
public void run() {
InputStream inputStream = null;
try {
// 1. 把傳過來的路徑轉(zhuǎn)成URL
URL url = new URL(imageUrl);
// 2.通過URL 建立網(wǎng)絡(luò)連接
// --> url.openConnection() 返回 URLConnection
// ,它是一個抽象類,這里需要通過Http協(xié)議建立連接,需要它的實現(xiàn)類 HttpURLConnection
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// 3. 使用GET方法訪問網(wǎng)絡(luò)
urlConnection.setRequestMethod("GET");
// 配置網(wǎng)絡(luò)超時時間為 10秒
urlConnection.setConnectTimeout(10000);
//4. 獲取Http協(xié)議 響應(yīng)碼
int responseCode = urlConnection.getResponseCode();
// Http 協(xié)議 規(guī)定 響應(yīng)碼為200時 請求成功
if (responseCode == 200) {
// 5. 得知 請求資源成功后,獲取圖片文件輸入流
inputStream = urlConnection.getInputStream();
// 6. 把獲取到的 文件輸入流 通過 系統(tǒng)Api 轉(zhuǎn)換為 ImageView 可以識別的 Bitmap 對象
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
// 7.要知道 這里現(xiàn)在是子線程 更新UI的操作需要再主線程(UI線程)完成。
Message message = mHandler.obtainMessage();
message.obj = bitmap;
message.what = 1010;//
mHandler.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
//關(guān)閉流
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
}
/**
* 8.利用從 Mesage 從子線程中攜帶回來的 Bitmap 對象,在UI線程設(shè)置圖片
*/
private void setImageView(Bitmap bitmap) {
mImageView.setImageBitmap(bitmap);
}
}
上面是創(chuàng)建一個空的 Activity ,布局文件中只有一個 ImageView 控件。
注意:在 Android中 主線程 也叫 UI線程。UI 線程是響應(yīng)用戶操作的線程,一旦在 UI線程中存在好在操作,就會阻塞 UI 線程,導(dǎo)致無法及時響應(yīng)用戶操作事件。所以在Android 系統(tǒng) 4.0 后,強制網(wǎng)絡(luò)請求操作必須在子線程。但問題是:所有更新 UI 的操作又必須在UI線程,這就是我們必須把網(wǎng)絡(luò)請求的結(jié)果,轉(zhuǎn)移到主線程才能更新 UI。怎么轉(zhuǎn)移呢? 那就是 Handler。這個現(xiàn)在知道怎么用就行,后面我們會仔細講解。
上面的代碼中,利用系統(tǒng)自帶 ULRConnection請求網(wǎng)絡(luò)請求的步驟注釋已經(jīng)很詳細了。可仔細了解其網(wǎng)絡(luò)請求步驟,大致的套路是一樣的。
特別特別特別注意:網(wǎng)絡(luò)請求是需要權(quán)限的,你需要在?AndroidManifet.xml 文件中聲明一句用戶權(quán)限。至于權(quán)限的概念后面我們會細聊。現(xiàn)在只需要在AndroidManifet.xml文件申明即可。
第三方網(wǎng)絡(luò)圖片加載庫與原始加載庫的對比
我們來思考幾個問題,如果在真實項目中,我們這樣加載圖片你覺得可以嗎?
........
答案是:不可以。
問題1:上面就只單一使用了內(nèi)存緩存來解決圖片加載問題,Android 系統(tǒng)為每個應(yīng)用分配的內(nèi)存是有限的,假如說我們的圖片成千上萬,即使現(xiàn)在的 Android 手機硬件都配置很高,也頂不住這樣的操作,當(dāng)內(nèi)存不足時應(yīng)用馬上會崩潰(Crash)。
問題2:內(nèi)存緩存,易失去性。即當(dāng)你重新啟動應(yīng)用程序后,原來已經(jīng)加載過的圖片就會丟失,重啟后又會重新下載!這就會導(dǎo)致頁面加載緩慢,再次耗費用戶流量。
所以我們需要一個比較完善的圖片加載系統(tǒng),這個系統(tǒng)最基礎(chǔ)的要包括圖片的緩存策略:先從網(wǎng)絡(luò)請求圖片,在手機內(nèi)存中和SD卡中各自保存一份圖片資源。當(dāng)重啟應(yīng)用時,如果圖片存在SD卡中,就可以從SD卡中直接獲取圖片加載。并且SD卡所能存儲的圖片總數(shù)是一定的,會不斷的根據(jù)策略去舍去圖片的存留。
還有非常重要的一點:從圖片加載庫的使用者角度講,使用者無需關(guān)心內(nèi)部到底是使用內(nèi)存緩存,還是SD卡緩存,或是直接從網(wǎng)絡(luò)獲取的。這對于使用者來講,內(nèi)部的一切用戶并不需要知道。使用者只需要知道加載圖片的接口。
對于圖片加載框架,內(nèi)部實現(xiàn)是極其復(fù)雜的,目前我們并不需要了解其內(nèi)部實現(xiàn)方式。
下面我們就使用最常用的圖片加載框架 Glide來完成我們圖片加載框架使用的演示。
怎樣使用第三方網(wǎng)絡(luò)加載庫加載圖片(Glide)
我們要知道,因為Android是開源的,所以會產(chǎn)生各種各樣的第三方框架,而我們不能盲目的去使用,要根據(jù)實際情況,從這之中挑選出最優(yōu)的、最適合自己項目的框架,合理有效的去使用各種資源。而我們推薦的Glide是經(jīng)過不斷的和其他框架對比所挑選出來性價比最高的!
目前國內(nèi)主流的第三方網(wǎng)絡(luò)圖片加載庫有Glide(主推)、ImageLoader、Picasso、Volley、Fresco等,感興趣的小伙伴可以去搜索一下這些加載庫的全方面對比,百度一哈比比皆是,我們就不再這里將網(wǎng)上的一些大神所對比的實際內(nèi)容再復(fù)述一遍啦。下面請跟我走4步,完成你人生中第一次加載網(wǎng)絡(luò)圖片吧!!!
首先我們要通過依賴 Glide 圖片加載庫。
在官方文檔中我們找到需要依賴的 Glide庫地址。
implementation 'com.github.bumptech.glide:glide:4.9.0'
將依賴地址放置到 app 模塊下的 build.gradle 中如圖:
添加完成后,我們點擊 右上角的 Sync Now ,從網(wǎng)絡(luò)下載依賴庫到本地,并依賴到 app 模塊。
我們在創(chuàng)建的空 Activity 當(dāng)中,為 ImageView控件利用 Glide加載圖片。
okay,搞定!!使用第三圖片加載庫是不是很簡單。
其實里面的大致操作就是我們在第一個問題中書寫的代碼,里面多的就是各種緩存策略和邏輯處理。
結(jié)語
關(guān)于網(wǎng)絡(luò)圖片的加載我們今天就講到這里,請原諒小編沒有對Glide的源碼做詳解,因為內(nèi)容過于復(fù)雜,涉及到很多初學(xué)者無法理解的知識,咱們目前只需要會使用,慢慢的跟著我們一起學(xué)習(xí),后續(xù)這些都會融會貫通的~ 如果有小伙伴對Glide的源碼感興趣可以加入我們的微信群一起探討~ 在公眾號中回復(fù)微信群,就可以加入其中,也可以在公眾號中回復(fù)視頻,里面有一些初學(xué)者視頻哦~
PS:如果還有未看懂的小伙伴,歡迎加入我們的QQ技術(shù)交流群:892271582,里面有各種大神回答小伙伴們遇到的問題,我們的微信群馬上也將要和大家見面啦,屆時希望大家踴躍加入其中~~
總結(jié)
以上是生活随笔為你收集整理的android显示网络图片控件,Android控件之ImageView(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle tb级别数据量,备份TB级
- 下一篇: localstorage存储大小_Coo