使用Glide在Android應用中加載網絡圖片

使用Glide在Android應用中加載網絡圖片

代碼由於寬度比較小被換行了,看着很不整齊,其實很整齊,註釋寫得比較詳細,比較多不容易閱讀,可以先複製到ide或者Vscode裏閱讀

佈局文件裏只有一個imageview

動畫資源文件可以不需要

  1. Json文件放置的目錄爲

/rememberWords/internetPic/src/main/assets/test.json
如果沒有assets文件夾的話就自己創建

  1. gradle的設置

注意選擇自己Module的build.gradle文件在這裏插入圖片描述

//這裏是需要添加的代碼段,注意是在dependencies添加,不是再創建一個dependencies
dependencies {
    implementation 'com.github.bumptech.glide:glide:4.11.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'

    compile 'org.apache.httpcomponents:httpcore:4.4.4'
}
//這裏是需要直接添加在build.gradle文件中的
repositories {
    mavenCentral()
    google()
}

MainActivity類
實現主要功能

package com.example.internetpic;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.request.RequestOptions;

import org.apache.http.util.EncodingUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Random;

import javax.xml.transform.Transformer;

public class MainActivity extends AppCompatActivity {

    private ArrayList<String> arrPicPath = new ArrayList<>();//list存儲圖片URL
    private String Str_json;//全局變量存儲json文件轉換來的字符串
    private int index = 0;//List下標(索引)
    private float touchDownX,touchUpX;//按下、擡起時的X座標
    ImageView imageView;//這個就不要寫了吧
    Animation animation;//存儲動畫資源



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = findViewById(R.id.imageview);//ID獲取image view

        animation = AnimationUtils.loadAnimation(this,R.anim.anim_alpha_in);//加載本地動畫資源文件

        imageView.setAnimation(animation);//給image view設置動畫

        doReadJson();//自定義方法,從本地讀取Json文件
        doParseJson();//自定義方法,解析Json文件

        RequestOptions options = new RequestOptions();//實例化一個option對象,並設置屬性
            options.centerCrop()//設置居中
                    .transform(new dictionaryTransform())//調用transform,實例化dictionaryTransform類調用自定義方法BitmapMosaic實現打碼
                    .placeholder(R.drawable.img_load)//設置加載時顯示的圖片(佔位)
                    .error(R.drawable.img_load)//失敗時顯示的圖片
                    .fallback(R.drawable.img_load);//反饋圖片

        final RequestBuilder<Drawable> requestBuilder =//定義一個RequestBuilder<Drawable>對象
                Glide.with(this)//實例化一個Glide對象
                        .asDrawable()//設置對象類型爲Drawable
                        .apply(options);//應用options的設置

        final RequestBuilder<Drawable> requestBuilderwithout =//同上,但是這個對象不設置option,用以設置無打碼的圖片
                Glide.with(this)                       //其實嚴謹點應該設置兩個option
                        .asDrawable();

        requestBuilder.clone()//清除
                .load(arrPicPath.get(index))//根據索引找到list中對應URL,load方法加載網絡圖片
                .into(imageView);//把圖片放進image view,注意:此時使用的是設置過option的對象,即打碼的圖片

//        Glide.with(this).load("https://www.baidu.com/img/bd_logo1.png").into(imageView);

        imageView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {//爲image view設置觸摸監聽事件
                if (event.getAction() == MotionEvent.ACTION_DOWN) {//event.getAction()獲取當前事件,利用常量判斷該事件是否爲按下事件
                    touchDownX = event.getX();//獲取按下時的座標,並存儲
                    return false;//返回false表示按下事件沒有被處理完,下面的監聽事件纔可以繼續處理該按下事件
                } else if (event.getAction() == MotionEvent.ACTION_UP) {//同上,判斷是否擡起
                    touchUpX = event.getX();//獲取擡起時座標,儲存
                    if (touchUpX - touchDownX > 50) {//判斷按下擡起座標間隔,並定義爲一次從左到右滑動
                        Random r = new Random();//定義並實例化一個隨機數對象
                        index = index == 0 ? arrPicPath.size() - 1 : r.nextInt(arrPicPath.size());//三位運算符,判斷index是否等於0,
                        // 若等於0則使index等於List的最後一個元素,若不等於0則使index等於生成的(0-list元素個數)一個隨機數
                        //其實這一步邏輯上有錯,因爲一開始設置爲有順序的循環顯示圖片,所以需要判斷左右滑動和List的下標防止越界
                        //改爲隨機後可直接刪除左右滑動判斷,和下標判斷,直接隨機數設置下標即可
                        requestBuilder.clone()//清除
                                .load(arrPicPath.get(index))//加載隨機後的圖片
                                .into(imageView);//設置進image view,同上,注意:此時依然設置的是打碼圖片


                    } else if (touchDownX - touchUpX > 50) {//同上,不再贅述
                        Random r = new Random();
                        index = index == arrPicPath.size() - 1 ? 0 : r.nextInt(arrPicPath.size());
                        requestBuilder.clone()
                                .load(arrPicPath.get(index))
                                .into(imageView);

                    }
                }
                return false;//注意!返回false表示擡起事件沒有處理完,由於我下面的監聽使用的是長按事件,所以上面兩個是false還是true沒有影響
                //如果想使用單擊事件(onClick)則按下事件要返回false
            }
        });

//        Glide.with(this)
//                .load(R.drawable.img01)
//                .apply(options)
//                .into(imageView);
        imageView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {//給image view設置長按事件
                requestBuilderwithout.clone()//注意:此時使用的是沒有設置option的對象,即加載的圖片是無碼的
                        .load(arrPicPath.get(index))
                        .into(imageView);
                return true;//返回true,表示長按事件處理完畢
            }
        });

    }
    /*讀取Json*/
    public void doReadJson(){
        try {
            InputStream is = getResources().getAssets().open("test.json");//根據文件名打開json文件,並存入輸入流對象
            int length = is.available();//獲取輸入流字節長度
            byte[] buffer = new byte[length];//定義一個字節數組作爲緩衝,長度爲輸入流的長度
            is.read(buffer);//將輸入流中數據放進緩衝字節數組中
            Str_json = EncodingUtils.getString(buffer,"utf-8");//把字節數組中的數據放入字符串中,這樣就把json文件讀取成了字符串
            is.close();//切記,不要忘記關閉流
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*解析Json*/
    public void doParseJson() {
        if (Str_json == null) {// 判斷用戶是否讀取了Json文件
            Toast.makeText(this, "請先讀取Json文件!", Toast.LENGTH_SHORT).show();//沒有就彈出提示
        } else {
            try {
                JSONArray jsonArray = new JSONArray(Str_json);// 基於Str_json字符串創建Json對象數組
                for (int i = 0; i < jsonArray.length(); i++) {// 遍歷Json數組
                    JSONObject jsonObject = jsonArray.getJSONObject(i);// 通過下標獲取json數組元素——Json對象
                    // 對Json對象按鍵取值,其實我只需要image的網址就行了,也不需要組成對象2333,但是這只是個demo,組成對象是爲了供後面使用
                    int id = jsonObject.getInt("id");
                    String word = jsonObject.getString("word");
                    String explain = jsonObject.getString("explain");
                    String sound = jsonObject.getString("sound");
                    String image = "https://fox.ftqq.com/"+jsonObject.getString("image");
                    Word wordObject = new Word(id, word, explain, sound, image);// 組成Word對象
                    arrPicPath.add(wordObject.getImage());//獲取對象中的image的值,並添加到List中
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

}

dictionaryTransform類
用來實現打碼功能
其中的打碼方法是在一篇文章裏看到的,找不到來源了,原作者如果看到的話可以加上您的鏈接嗷

package com.example.internetpic;

import android.graphics.Bitmap;
import android.graphics.Color;

import androidx.annotation.NonNull;

import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;

import java.security.MessageDigest;

public class dictionaryTransform extends BitmapTransformation {
    @Override
    protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
        return BitmapMosaic(toTransform,40);
    }

    @Override
    public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {

    }

    public static Bitmap BitmapMosaic(Bitmap bitmap, int BLOCK_SIZE) {

        if (bitmap == null || bitmap.getWidth() == 0 || bitmap.getHeight() == 0
                || bitmap.isRecycled()) {
            return null;
        }
        int mBitmapWidth = bitmap.getWidth();
        int mBitmapHeight = bitmap.getHeight();
        Bitmap mBitmap = Bitmap.createBitmap(mBitmapWidth, mBitmapHeight,
                Bitmap.Config.ARGB_8888);//創建畫布
        int row = mBitmapWidth / BLOCK_SIZE;// 獲得列的切線
        int col = mBitmapHeight / BLOCK_SIZE;// 獲得行的切線
        int[] block = new int[BLOCK_SIZE * BLOCK_SIZE];
        for (int i = 0; i <=row; i++)
        {
            for (int j =0; j <= col; j++)
            {
                int length = block.length;
                int flag = 0;// 是否到邊界標誌
                if (i == row && j != col) {
                    length = (mBitmapWidth - i * BLOCK_SIZE) * BLOCK_SIZE;
                    if (length == 0) {
                        break;// 邊界外已經沒有像素
                    }
                    bitmap.getPixels(block, 0, BLOCK_SIZE, i * BLOCK_SIZE, j
                                    * BLOCK_SIZE, mBitmapWidth - i * BLOCK_SIZE,
                            BLOCK_SIZE);

                    flag = 1;
                } else if (i != row && j == col) {
                    length = (mBitmapHeight - j * BLOCK_SIZE) * BLOCK_SIZE;
                    if (length == 0) {
                        break;// 邊界外已經沒有像素
                    }
                    bitmap.getPixels(block, 0, BLOCK_SIZE, i * BLOCK_SIZE, j
                            * BLOCK_SIZE, BLOCK_SIZE, mBitmapHeight - j
                            * BLOCK_SIZE);
                    flag = 2;
                } else if (i == row && j == col) {
                    length = (mBitmapWidth - i * BLOCK_SIZE)
                            * (mBitmapHeight - j * BLOCK_SIZE);
                    if (length == 0) {
                        break;// 邊界外已經沒有像素
                    }
                    bitmap.getPixels(block, 0, BLOCK_SIZE, i * BLOCK_SIZE, j
                                    * BLOCK_SIZE, mBitmapWidth - i * BLOCK_SIZE,
                            mBitmapHeight - j * BLOCK_SIZE);

                    flag = 3;
                } else
                {
                    bitmap.getPixels(block, 0, BLOCK_SIZE, i * BLOCK_SIZE, j
                            * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);//取出像素數組
                }

                int r = 0, g = 0, b = 0, a = 0;
                for (int k = 0; k < length; k++) {
                    r += Color.red(block[k]);
                    g += Color.green(block[k]);
                    b += Color.blue(block[k]);
                    a += Color.alpha(block[k]);
                }
                int color = Color.argb(a / length, r / length, g / length, b
                        / length);//求塊內所有顏色的平均值
                for (int k = 0; k < length; k++) {
                    block[k] = color;
                }
                if (flag == 1) {
                    mBitmap.setPixels(block, 0, mBitmapWidth - i * BLOCK_SIZE,
                            i * BLOCK_SIZE, j
                                    * BLOCK_SIZE, mBitmapWidth - i * BLOCK_SIZE,
                            BLOCK_SIZE);
                } else if (flag == 2) {
                    mBitmap.setPixels(block, 0, BLOCK_SIZE, i * BLOCK_SIZE, j
                            * BLOCK_SIZE, BLOCK_SIZE, mBitmapHeight - j
                            * BLOCK_SIZE);
                } else if (flag == 3) {
                    mBitmap.setPixels(block, 0, BLOCK_SIZE, i * BLOCK_SIZE, j
                                    * BLOCK_SIZE, mBitmapWidth - i * BLOCK_SIZE,
                            mBitmapHeight - j * BLOCK_SIZE);
                } else {
                    mBitmap.setPixels(block, 0, BLOCK_SIZE, i * BLOCK_SIZE, j
                            * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
                }

            }
        }
        //並沒有回收傳進來的bitmap  原因是JAVA傳值默認是引用,如果回收了之後,其他地方用到bitmap的位置可能報NULL指針異常,請根據實際情況決定是否回收.
        return mBitmap;
    }
}

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