├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── fe │ │ └── glideloadimageprogress │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── fe │ │ │ └── glideloadimageprogress │ │ │ ├── MainActivity.java │ │ │ └── progress │ │ │ ├── ProgressDataFetcher.java │ │ │ ├── ProgressImageView.java │ │ │ ├── ProgressInterceptor.java │ │ │ ├── ProgressListener.java │ │ │ ├── ProgressModelLoader.java │ │ │ └── ProgressResponseBody.java │ └── res │ │ ├── drawable │ │ └── xg.gif │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── fe │ └── glideloadimageprogress │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | GlideLoadImageProgress -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | C:\Users\lenovo\AppData\Roaming\Subversion 48 | 49 | 50 | 51 | 52 | 53 | 1.7 54 | 55 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.fe.glideloadimageprogress" 9 | minSdkVersion 14 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.github.bumptech.glide:glide:3.7.0' 26 | compile 'com.android.support:appcompat-v7:23.3.0' 27 | compile 'com.squareup.okhttp:okhttp:2.4.0' 28 | compile 'com.squareup.okio:okio:1.5.0' 29 | } 30 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\lenovo\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/fe/glideloadimageprogress/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.fe.glideloadimageprogress; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/fe/glideloadimageprogress/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.fe.glideloadimageprogress; 2 | 3 | import android.app.Activity; 4 | import android.os.Handler; 5 | import android.os.Looper; 6 | import android.os.Message; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.os.Bundle; 9 | import android.view.View; 10 | 11 | import com.bumptech.glide.Glide; 12 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 13 | import com.fe.glideloadimageprogress.progress.ProgressImageView; 14 | import com.fe.glideloadimageprogress.progress.ProgressModelLoader; 15 | import java.lang.ref.WeakReference; 16 | 17 | public class MainActivity extends AppCompatActivity { 18 | 19 | private ProgressImageView progressImageView; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_main); 25 | progressImageView = (ProgressImageView) findViewById(R.id.progress_imageview); 26 | findViewById(R.id.start).setOnClickListener(new View.OnClickListener() { 27 | @Override 28 | public void onClick(View v) { 29 | Glide.with(MainActivity.this).using(new ProgressModelLoader(new ProgressHandler(MainActivity.this, progressImageView))). 30 | load("http://image2.sina.com.cn/dy/o/2004-11-10/1100077821_2laygS.jpg") 31 | .diskCacheStrategy(DiskCacheStrategy.NONE).into(progressImageView.getImageView()); 32 | } 33 | }); 34 | 35 | } 36 | 37 | 38 | private static class ProgressHandler extends Handler { 39 | 40 | private final WeakReference mActivity; 41 | private final ProgressImageView mProgressImageView; 42 | 43 | public ProgressHandler(Activity activity, ProgressImageView progressImageView) { 44 | super(Looper.getMainLooper()); 45 | mActivity = new WeakReference<>(activity); 46 | mProgressImageView = progressImageView; 47 | } 48 | 49 | @Override 50 | public void handleMessage(Message msg) { 51 | super.handleMessage(msg); 52 | final Activity activity = mActivity.get(); 53 | if (activity != null) { 54 | switch (msg.what) { 55 | case 1: 56 | int percent = msg.arg1*100/msg.arg2; 57 | mProgressImageView.setProgress(percent); 58 | break; 59 | default: 60 | break; 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/fe/glideloadimageprogress/progress/ProgressDataFetcher.java: -------------------------------------------------------------------------------- 1 | package com.fe.glideloadimageprogress.progress; 2 | 3 | import android.os.Handler; 4 | import android.os.Message; 5 | import com.bumptech.glide.Priority; 6 | import com.bumptech.glide.load.data.DataFetcher; 7 | import com.squareup.okhttp.Call; 8 | import com.squareup.okhttp.OkHttpClient; 9 | import com.squareup.okhttp.Request; 10 | import com.squareup.okhttp.Response; 11 | import java.io.IOException; 12 | import java.io.InputStream; 13 | 14 | /** 15 | * Created by chenpengfei on 2016/11/9. 16 | */ 17 | public class ProgressDataFetcher implements DataFetcher { 18 | 19 | private String url; 20 | private Handler handler; 21 | private Call progressCall; 22 | private InputStream stream; 23 | private boolean isCancelled; 24 | 25 | public ProgressDataFetcher(String url, Handler handler) { 26 | this.url = url; 27 | this.handler = handler; 28 | } 29 | 30 | @Override 31 | public InputStream loadData(Priority priority) throws Exception { 32 | Request request = new Request.Builder().url(url).build(); 33 | OkHttpClient client = new OkHttpClient(); 34 | client.interceptors().add(new ProgressInterceptor(getProgressListener())); 35 | try { 36 | progressCall = client.newCall(request); 37 | Response response = progressCall.execute(); 38 | if (isCancelled) { 39 | return null; 40 | } 41 | if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); 42 | stream = response.body().byteStream(); 43 | } catch (IOException e) { 44 | e.printStackTrace(); 45 | return null; 46 | } 47 | return stream; 48 | } 49 | 50 | private ProgressListener getProgressListener() { 51 | ProgressListener progressListener = new ProgressListener() { 52 | 53 | @Override 54 | public void progress(long bytesRead, long contentLength, boolean done) { 55 | if (handler != null && !done) { 56 | Message message = handler.obtainMessage(); 57 | message.what = 1; 58 | message.arg1 = (int)bytesRead; 59 | message.arg2 = (int)contentLength; 60 | handler.sendMessage(message); 61 | } 62 | } 63 | }; 64 | return progressListener; 65 | } 66 | 67 | @Override 68 | public void cleanup() { 69 | if (stream != null) { 70 | try { 71 | stream.close(); 72 | stream = null; 73 | } catch (IOException e) { 74 | stream = null; 75 | } 76 | } 77 | if (progressCall != null) { 78 | progressCall.cancel(); 79 | } 80 | } 81 | 82 | @Override 83 | public String getId() { 84 | return url; 85 | } 86 | 87 | @Override 88 | public void cancel() { 89 | isCancelled = true; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/com/fe/glideloadimageprogress/progress/ProgressImageView.java: -------------------------------------------------------------------------------- 1 | package com.fe.glideloadimageprogress.progress; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.os.Build; 8 | import android.util.AttributeSet; 9 | import android.view.ViewGroup; 10 | import android.widget.ImageView; 11 | import android.widget.RelativeLayout; 12 | import android.widget.TextView; 13 | 14 | /** 15 | * Created by chenpengfei on 2016/11/9. 16 | */ 17 | public class ProgressImageView extends RelativeLayout { 18 | 19 | private ImageView mImageView; 20 | private TextView mProgressTextView; 21 | private int mProgress; 22 | 23 | public ProgressImageView(Context context) { 24 | super(context); 25 | } 26 | 27 | public ProgressImageView(Context context, AttributeSet attrs) { 28 | super(context, attrs); 29 | mImageView = new ImageView(context); 30 | RelativeLayout.LayoutParams ivLp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT ); 31 | ivLp.addRule(CENTER_IN_PARENT); 32 | mImageView.setLayoutParams(ivLp); 33 | addView(mImageView); 34 | 35 | mProgressTextView = new TextView(context); 36 | mProgressTextView.setTextSize(50); 37 | mProgressTextView.setTextColor(Color.RED); 38 | RelativeLayout.LayoutParams tvLp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT ); 39 | tvLp.addRule(CENTER_IN_PARENT); 40 | mProgressTextView.setLayoutParams(tvLp); 41 | addView(mProgressTextView); 42 | } 43 | 44 | public ProgressImageView(Context context, AttributeSet attrs, int defStyleAttr) { 45 | super(context, attrs, defStyleAttr); 46 | } 47 | 48 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 49 | public ProgressImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 50 | super(context, attrs, defStyleAttr, defStyleRes); 51 | } 52 | 53 | public void setProgress(int progress) { 54 | this.mProgress = progress; 55 | mProgressTextView.setText(mProgress + "%"); 56 | } 57 | 58 | public ImageView getImageView() { 59 | return mImageView; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/fe/glideloadimageprogress/progress/ProgressInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.fe.glideloadimageprogress.progress; 2 | 3 | import com.squareup.okhttp.Interceptor; 4 | import com.squareup.okhttp.Response; 5 | import java.io.IOException; 6 | 7 | /** 8 | * Created by chenpengfei on 2016/11/9. 9 | */ 10 | public class ProgressInterceptor implements Interceptor { 11 | 12 | private ProgressListener progressListener; 13 | 14 | public ProgressInterceptor(ProgressListener progressListener) { 15 | this.progressListener = progressListener; 16 | } 17 | 18 | @Override 19 | public Response intercept(Chain chain) throws IOException { 20 | Response originalResponse = chain.proceed(chain.request()); 21 | return originalResponse.newBuilder().body(new ProgressResponseBody(originalResponse.body(), progressListener)).build(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/fe/glideloadimageprogress/progress/ProgressListener.java: -------------------------------------------------------------------------------- 1 | package com.fe.glideloadimageprogress.progress; 2 | 3 | public interface ProgressListener { 4 | 5 | void progress(long bytesRead, long contentLength, boolean done); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/fe/glideloadimageprogress/progress/ProgressModelLoader.java: -------------------------------------------------------------------------------- 1 | package com.fe.glideloadimageprogress.progress; 2 | 3 | import android.os.Handler; 4 | import com.bumptech.glide.load.data.DataFetcher; 5 | import com.bumptech.glide.load.model.stream.StreamModelLoader; 6 | import java.io.InputStream; 7 | 8 | public class ProgressModelLoader implements StreamModelLoader { 9 | 10 | private Handler handler; 11 | 12 | public ProgressModelLoader(Handler handler) { 13 | this.handler = handler; 14 | } 15 | 16 | @Override 17 | public DataFetcher getResourceFetcher(String model, int width, int height) { 18 | return new ProgressDataFetcher(model, handler); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/fe/glideloadimageprogress/progress/ProgressResponseBody.java: -------------------------------------------------------------------------------- 1 | package com.fe.glideloadimageprogress.progress; 2 | 3 | import com.squareup.okhttp.MediaType; 4 | import com.squareup.okhttp.ResponseBody; 5 | import java.io.IOException; 6 | import okio.Buffer; 7 | import okio.BufferedSource; 8 | import okio.ForwardingSource; 9 | import okio.Okio; 10 | import okio.Source; 11 | 12 | /** 13 | * Created by chenpengfei on 2016/11/9. 14 | */ 15 | public class ProgressResponseBody extends ResponseBody { 16 | 17 | private ResponseBody responseBody; 18 | private ProgressListener progressListener; 19 | private BufferedSource bufferedSource; 20 | 21 | public ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) { 22 | this.responseBody = responseBody; 23 | this.progressListener = progressListener; 24 | } 25 | 26 | @Override 27 | public MediaType contentType() { 28 | return responseBody.contentType(); 29 | } 30 | 31 | @Override 32 | public long contentLength() { 33 | try { 34 | return responseBody.contentLength(); 35 | } catch (IOException e) { 36 | e.printStackTrace(); 37 | } 38 | return 0; 39 | } 40 | 41 | @Override 42 | public BufferedSource source() { 43 | if (bufferedSource == null) { 44 | try { 45 | bufferedSource = Okio.buffer(source(responseBody.source())); 46 | } catch (IOException e) { 47 | e.printStackTrace(); 48 | } 49 | } 50 | return bufferedSource; 51 | } 52 | 53 | private Source source(Source source) { 54 | return new ForwardingSource(source) { 55 | 56 | long totalBytesRead = 0; 57 | 58 | @Override 59 | public long read(Buffer sink, long byteCount) throws IOException { 60 | long bytesRead = super.read(sink, byteCount); 61 | totalBytesRead += bytesRead != -1 ? bytesRead : 0; 62 | if(progressListener != null) 63 | progressListener.progress(totalBytesRead, responseBody.contentLength(), bytesRead == -1); 64 | return bytesRead; 65 | } 66 | }; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/xg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenpengfei88/GlideLoadImageProgress/ab3904d5443492a1f3ef6ff3bfe7bbe8b984cfef/app/src/main/res/drawable/xg.gif -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 |