Android Code : Glide Progressive ทำให้ระหว่างโหลดรูปแสดงเปอร์เซ็น
บทคามนี้มาแชร์ code ครับ ผมมีโอกาสได้ทำ Glide ให้โหลดรูปแล้วแสดงเปอร์เซ็น แฮ่ไม่เคยทำ กว่าจะหาในอินเตอร์เน็ตได้ก็นานเลย โชคดีมีพี่ๆมาแนะนำ เลยมาเขียนบันทึก สรุปสักหน่อย
เพิ่ม permission ใช้ internet (เผื่อจะลืม) ใน AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
กำหนด dependencies ไลบรารี่ มี 3 ตัวดังนี้
compile 'com.squareup.okhttp3:okhttp:3.3.1' compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar' compile 'com.github.bumptech.glide:glide:3.7.0'
ต่อมาสร้าง layout ซึ่งตัวอย่างนี้ผมจะมี
ProgressBar ตัวนึงไว้บอกความคืบหน้า
TextView ไว้แสดงเปอรเซ็น
ImageView ไว้แสดงรูป เมื่อโหลดเสร็จ
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.benzneststudios.library.glideprogressive.MainActivity"> <ImageView android:id="@+id/imgV" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> <ProgressBar android:id="@+id/progress_bar" android:layout_width="300dp" android:layout_height="40dp" android:layout_marginTop="40dp" style="@android:style/Widget.ProgressBar.Horizontal" android:layout_centerHorizontal="true"/> <TextView android:id="@+id/tv_progress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="0%" android:textSize="32sp" android:layout_below="@id/progress_bar" android:layout_centerHorizontal="true" android:layout_marginTop="8dp"/> </RelativeLayout>
ต่อมาคือใช้ OkHttpCient ใส่ไปกับ register ของ Glide
ซึ่ง okHttpClient ก็ใส่ interceptor เอาไว้ เกี่ยวกับการ listener update ขณะโหลด
GlideProgressive.java
public class GlideProgressive { Context context; OkHttpClient.Builder okClient; ProgressListener progressListener; private GlideProgressive() { } public GlideProgressive(Context context) { this.context = context; } public interface ProgressListener { void update(long bytesRead, long contentLength, boolean done); } public void setProgressListener(final ProgressListener progressListener) { this.progressListener = progressListener; okClient = new OkHttpClient.Builder() .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Response originalResponse = chain.proceed(chain.request()); return originalResponse.newBuilder() .body(new ProgressResponseBody(originalResponse.body(), progressListener)) .build(); } }); Glide.get(context) .register(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(okClient.build())); } public void startDownload(String url, ImageView img) { Glide.with(context) .load(url) .diskCacheStrategy(DiskCacheStrategy.ALL) .into(img); } private static class ProgressResponseBody extends ResponseBody { private final ResponseBody responseBody; private final ProgressListener progressListener; private BufferedSource bufferedSource; public ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) { this.responseBody = responseBody; this.progressListener = progressListener; } @Override public MediaType contentType() { return responseBody.contentType(); } @Override public long contentLength() { return responseBody.contentLength(); } @Override public BufferedSource source() { if (bufferedSource == null) { bufferedSource = Okio.buffer(source(responseBody.source())); } return bufferedSource; } private Source source(Source source) { return new ForwardingSource(source) { long totalBytesRead = 0L; @Override public long read(Buffer sink, long byteCount) throws IOException { long bytesRead = super.read(sink, byteCount); // read() returns the number of bytes read, or -1 if this source is exhausted. totalBytesRead += bytesRead != -1 ? bytesRead : 0; progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1); return bytesRead; } }; } } }
ทีนี้เราก็สามารถกำหนดว่าขณะโหลดให้ update อะไร โดยการสร้าง object GlideProgressive แล้วเพิ่ม listener ให้มัน เป็นอันเรียบร้อย
GlideProgressive progressive = new GlideProgressive(context); progressive.setProgressListener(new GlideProgressive.ProgressListener() { @Override public void update(long bytesRead, long contentLength, boolean done) { // do something. } });
ถ้ามีการอัพเดท UI ต้องใช้คำสั่ง runOnUiThread เพราะ Glide มันรันบน Background thread
GlideProgressive progressive = new GlideProgressive(MainActivity.this); progressive.setProgressListener(new GlideProgressive.ProgressListener() { @Override public void update(long bytesRead, long contentLength, boolean done) { MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { // Update UI. } }); } });
เสร็จแล้วเรียกคำสั่ง
progressive.startDownload(url, imgView);
สรุป
MainActivity.java
public class MainActivity extends AppCompatActivity { ImageView img; TextView tvProgress; ProgressBar progressBarLoading; String url = "https://static.pexels.com/photos/4164/landscape-mountains-nature-mountain.jpeg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); img = (ImageView) findViewById(R.id.imgV); progressBarLoading = (ProgressBar) findViewById(R.id.progress_bar); tvProgress = (TextView) findViewById(R.id.tv_progress); GlideProgressive progressive = new GlideProgressive(MainActivity.this); progressive.setProgressListener(new GlideProgressive.ProgressListener() { @Override public void update(long bytesRead, long contentLength, boolean done) { final int progress = (int) ((100 * bytesRead) / contentLength); MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { progressBarLoading.setProgress(progress); tvProgress.setText(progress+"%"); if (progress >= 100) { progressBarLoading.setVisibility(View.GONE); tvProgress.setVisibility(View.GONE); } } }); } }); progressive.startDownload(url, img); } }
ผลลัพธ์
ก็จะได้ progress bar โหลดรูปมาแล้ว
เสร็จแล้ว ยังไงก็ลองเอาไปประยุกต์ใช้ดูนะครับ
(:
Reference
https://gist.github.com/fbis251/cfa169fd9e1e142e042c
ขอบคุณพี่แบงค์ที่ให้คำแนะนำครับ