Android控件之ImageView(二)

前言

在上一篇文章中,咱們講解了如何加載本地圖片,那麼在實際項目中 ImageView 大多數使用場景是加載網絡圖片,網絡圖片其實就是存儲在服務器上的文件,咱們須要從服務器獲取到文件的二進制輸入流 Inpustream ,而後將其轉化爲 ImageView 能夠加載的 Bitmap 對象。實現網絡圖片的加載。java

這篇文章咱們經過使用原始的網絡鏈接和使用第三庫來簡單講解 ImageView 網絡圖片的加載。android

  • 怎麼使用原始方式加載網絡圖片?
  • 第三方網絡圖片加載庫與原始加載庫的對比?
  • 怎樣使用第三方網絡加載庫加載圖片?

使用原始方式加載網絡圖片

先上代碼(主要分爲三大步驟):git

  • 1~6 : 從網絡獲取圖片。因爲Android 系統規定網絡請求操做須要在子線程完成。主要是由於網絡請求屬於耗時操做,若是在主線程發起網絡請求會致使主線程在網絡請求期間,沒法及時響應用戶的操做,
  • 7:利用在 Activity聲明的 Handler對象把在子線從網絡獲取到的 Bitmap 對象,轉移到 UI 線程。
  • 8 : 更新UI
public class ImageNetActivity extends AppCompatActivity {

    /** * 7.要知道 這裏如今是子線程 更新UI的操做須要在主線程(UI線程)完成。 * 在 Activity 中聲明 Handler 對象,並複寫它的 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 系統強制網絡請求須要在子線程操做
        new Thread(new Runnable() {

            @Override
            public void run() {
                InputStream inputStream = null;
                try {
                    // 1. 把傳過來的路徑轉成URL
                    URL url = new URL(imageUrl);
                    // 2.經過URL 創建網絡鏈接
                    // --> url.openConnection() 返回 URLConnection
                    // ,它是一個抽象類,這裏須要經過Http協議創建鏈接,須要它的實現類 HttpURLConnection
                    HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                    // 3. 使用GET方法訪問網絡
                    urlConnection.setRequestMethod("GET");
                    // 配置網絡超時時間爲 10秒
                    urlConnection.setConnectTimeout(10000);

                    //4. 獲取Http協議 響應碼
                    int responseCode = urlConnection.getResponseCode();
                    // Http 協議 規定 響應碼爲200時 請求成功
                    if (responseCode == 200) {
                        // 5. 得知 請求資源成功後,獲取圖片文件輸入流
                        inputStream = urlConnection.getInputStream();

                        // 6. 把獲取到的 文件輸入流 經過 系統Api 轉換爲 ImageView 能夠識別的 Bitmap 對象

                        Bitmap bitmap = BitmapFactory.decodeStream(inputStream);

                        // 7.要知道 這裏如今是子線程 更新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 {
                            //關閉流
                            inputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();


    }
}
/** * 8.利用從 Mesage 從子線程中攜帶回來的 Bitmap 對象,在UI線程設置圖片 */
 private void setImageView(Bitmap bitmap) {
        mImageView.setImageBitmap(bitmap);
 }
}
複製代碼

上面是建立一個空的 Activity ,佈局文件中只有一個 ImageView 控件。 注意:在 Android中 主線程 也叫 UI線程。UI 線程是響應用戶操做的線程,一旦在 UI線程中存在好在操做,就會阻塞 UI 線程,致使沒法及時響應用戶操做事件。因此在Android 系統 4.0 後,強制網絡請求操做必須在子線程。但問題是:全部更新 UI 的操做又必須在UI線程,這就是咱們必須把網絡請求的結果,轉移到主線程才能更新 UI。怎麼轉移呢? 那就是 Handler。這個如今知道怎麼用就行,後面咱們會仔細講解。github

上面的代碼中,利用系統自帶 ULRConnection請求網絡請求的步驟註釋已經很詳細了。可仔細瞭解其網絡請求步驟,大體的套路是同樣的。緩存

特別特別特別注意:網絡請求是須要權限的,你須要在 AndroidManifet.xml 文件中聲明一句用戶權限。至於權限的概念後面咱們會細聊。如今只須要在AndroidManifet.xml文件申明便可。服務器

<uses-permission android:name="android.permission.INTERNET"/>
複製代碼

第三方網絡圖片加載庫與原始加載庫的對比

咱們來思考幾個問題,若是在真實項目中,咱們這樣加載圖片你以爲能夠嗎?微信

........網絡

答案是:不能夠。app

  • 問題1:上面就只單一使用了內存緩存來解決圖片加載問題,Android 系統爲每一個應用分配的內存是有限的,假如說咱們的圖片成千上萬,即便如今的 Android 手機硬件都配置很高,也頂不住這樣的操做,當內存不足時應用立刻會崩潰(Crash)。
  • 問題2:內存緩存,易失去性。即當你從新啓動應用程序後,原來已經加載過的圖片就會丟失,重啓後又會從新下載!這就會致使頁面加載緩慢,再次耗費用戶流量。

因此咱們須要一個比較完善的圖片加載系統,這個系統最基礎的要包括圖片的緩存策略:先從網絡請求圖片,在手機內存中和SD卡中各自保存一份圖片資源。當重啓應用時,若是圖片存在SD卡中,就能夠從SD卡中直接獲取圖片加載。而且SD卡所能存儲的圖片總數是必定的,會不斷的根據策略去捨去圖片的存留。框架

還有很是重要的一點:從圖片加載庫的使用者角度講,使用者無需關心內部究竟是使用內存緩存,仍是SD卡緩存,或是直接從網絡獲取的。這對於使用者來說,內部的一切用戶並不須要知道。使用者只須要知道加載圖片的接口

對於圖片加載框架,內部實現是極其複雜的,目前咱們並不須要瞭解其內部實現方式。

下面咱們就使用最經常使用的圖片加載框架 Glide來完成咱們圖片加載框架使用的演示。

怎樣使用第三方網絡加載庫加載圖片(Glide)

咱們要知道,由於Android是開源的,因此會產生各類各樣的第三方框架,而咱們不能盲目的去使用,要根據實際狀況,從這之中挑選出最優的、最適合本身項目的框架,合理有效的去使用各類資源。而咱們推薦的Glide是通過不斷的和其餘框架對比所挑選出來性價比最高的!

目前國內主流的第三方網絡圖片加載庫有Glide(主推)、ImageLoaderPicassoVolleyFresco等,感興趣的小夥伴能夠去搜索一下這些加載庫的全方面對比,百度一哈比比皆是,咱們就再也不這裏將網上的一些大神所對比的實際內容再複述一遍啦。下面請跟我走4步,完成你人生中第一次加載網絡圖片吧!!!

  1. 首先咱們要經過依賴 Glide 圖片加載庫。

    Glide github 官方地址

  2. 在官方文檔中咱們找到須要依賴的 Glide庫地址。

implementation 'com.github.bumptech.glide:glide:4.9.0'
複製代碼
  1. 將依賴地址放置到 app 模塊下的 build.gradle 中如圖:

添加完成後,咱們點擊 右上角的 Sync Now ,從網絡下載依賴庫到本地,並依賴到 app 模塊。

  1. 咱們在建立的空 Activity 當中,爲 ImageView控件利用 Glide加載圖片。

okay,搞定!!使用第三圖片加載庫是否是很簡單。

其實裏面的大體操做就是咱們在第一個問題中書寫的代碼,裏面多的就是各類緩存策略和邏輯處理。

結語

關於網絡圖片的加載咱們今天就講到這裏,請原諒小編沒有對Glide的源碼作詳解,由於內容過於複雜,涉及到不少初學者沒法理解的知識,我們目前只須要會使用,慢慢的跟着咱們一塊兒學習,後續這些都會融會貫通的~ 若是有小夥伴對Glide的源碼感興趣能夠加入咱們的微信羣一塊兒探討~ 在公衆號中回覆微信羣,就能夠加入其中,也能夠在公衆號中回覆視頻,裏面有一些初學者視頻哦~

PS:若是還有未看懂的小夥伴,歡迎加入咱們的QQ技術交流羣:892271582,裏面有各類大神回答小夥伴們遇到的問題,咱們的微信羣立刻也將要和你們見面啦,屆時但願你們踊躍加入其中~~

相關文章
相關標籤/搜索