サムネイル表示でVolleyを捨ててGlide+okhttp3にした
This commit is contained in:
parent
c17e5631a1
commit
fc45ce60b7
|
@ -53,10 +53,14 @@ dependencies {
|
|||
compile 'com.android.support:support-v4:25.3.1'
|
||||
compile 'com.android.support:design:25.3.1'
|
||||
compile 'com.android.support:customtabs:25.3.1'
|
||||
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
compile 'com.android.support:support-v4:25.3.1'
|
||||
|
||||
// compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile 'com.android.volley:volley:1.0.0'
|
||||
compile 'com.squareup.okhttp3:okhttp:3.7.0'
|
||||
// compile 'com.android.volley:volley:1.0.0'
|
||||
compile 'com.squareup.okhttp3:okhttp:3.8.0'
|
||||
// compile 'com.squareup.okhttp3:okhttp-urlconnection:3.8.0' // Vollery に使う
|
||||
compile 'commons-io:commons-io:2.4'
|
||||
compile 'uk.co.chrisjenx:calligraphy:2.2.0'
|
||||
compile 'com.github.woxthebox:draglistview:1.4.3'
|
||||
|
@ -65,4 +69,8 @@ dependencies {
|
|||
// compile 'com.astuetz:pagerslidingtabstrip:1.0.1'
|
||||
compile 'com.github.kenglxn.QRGen:android:2.2.0'
|
||||
compile project(':exif')
|
||||
|
||||
compile 'com.github.bumptech.glide:glide:3.8.0'
|
||||
// annotationProcessor 'com.github.bumptech.glide:compiler:3.8.0'
|
||||
compile 'com.github.bumptech.glide:okhttp3-integration:1.5.0'
|
||||
}
|
||||
|
|
|
@ -172,6 +172,11 @@
|
|||
android:resource="@xml/file_provider_path" />
|
||||
</provider>
|
||||
|
||||
|
||||
<!--<meta-data-->
|
||||
<!--android:name="com.bumptech.glide.integration.okhttp3.OkHttpGlideModule"-->
|
||||
<!--android:value="GlideModule" />-->
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -779,9 +779,9 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
iv.setCornerRadius( pref, 16f );
|
||||
PostAttachment a = attachment_list.get( idx );
|
||||
if( a.attachment != null && a.status == PostAttachment.ATTACHMENT_UPLOADED ){
|
||||
iv.setImageUrl( a.attachment.preview_url, App1.getImageLoader() );
|
||||
iv.setImageUrl( a.attachment.preview_url );
|
||||
}else{
|
||||
iv.setImageUrl( null, App1.getImageLoader() );
|
||||
iv.setImageUrl( null );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1469,7 +1469,7 @@ public class ActPost extends AppCompatActivity implements View.OnClickListener,
|
|||
llReply.setVisibility( View.VISIBLE );
|
||||
tvReplyTo.setText( HTMLDecoder.decodeHTML( account, in_reply_to_text ) );
|
||||
ivReply.setCornerRadius( pref, 16f );
|
||||
ivReply.setImageUrl( in_reply_to_image, App1.getImageLoader() );
|
||||
ivReply.setImageUrl( in_reply_to_image );
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,27 +2,24 @@ package jp.juggler.subwaytooter;
|
|||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Typeface;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.util.LruCache;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.volley.DefaultRetryPolicy;
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.toolbox.ImageLoader;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.GlideBuilder;
|
||||
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
|
||||
import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory;
|
||||
import com.bumptech.glide.load.model.GlideUrl;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
@ -166,94 +163,35 @@ public class App1 extends Application {
|
|||
CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, // m.sighash.info 用 デフォルトにはない
|
||||
};
|
||||
|
||||
static ImageLoader image_loader;
|
||||
|
||||
public static ImageLoader getImageLoader(){
|
||||
return image_loader;
|
||||
}
|
||||
|
||||
private static class MyImageLoader extends ImageLoader {
|
||||
|
||||
/**
|
||||
* Constructs a new ImageLoader.
|
||||
*
|
||||
* @param queue The RequestQueue to use for making image requests.
|
||||
* @param imageCache The cache to use as an L1 cache.
|
||||
*/
|
||||
MyImageLoader( RequestQueue queue, ImageCache imageCache ){
|
||||
super( queue, imageCache );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Request< Bitmap > makeImageRequest( String requestUrl, int maxWidth, int maxHeight, ImageView.ScaleType scaleType, String cacheKey ){
|
||||
Request< Bitmap > req = super.makeImageRequest( requestUrl, maxWidth, maxHeight, scaleType, cacheKey );
|
||||
req.setRetryPolicy( new DefaultRetryPolicy(
|
||||
30000 // SOCKET_TIMEOUT_MS
|
||||
, 3 // DefaultRetryPolicy.DEFAULT_MAX_RETRIES
|
||||
, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
|
||||
) );
|
||||
return req;
|
||||
}
|
||||
}
|
||||
|
||||
private static class BitmapCache implements ImageLoader.ImageCache {
|
||||
|
||||
private LruCache< String, Bitmap > mCache;
|
||||
|
||||
BitmapCache(Context context){
|
||||
|
||||
ActivityManager am = ((ActivityManager)context.getSystemService(Activity.ACTIVITY_SERVICE));
|
||||
int memory = am.getMemoryClass();
|
||||
int largeMemory = am.getLargeMemoryClass();
|
||||
// どちらも単位はMB
|
||||
log.d("MemoryClass=%d, LargeMemoryClass = %d",memory,largeMemory);
|
||||
|
||||
int maxSize;
|
||||
if( am.isLowRamDevice() ){
|
||||
maxSize = 5 * 1024; // 単位はKiB
|
||||
}else if( largeMemory >= 512 ){
|
||||
maxSize = 128 * 1024; // 単位はKiB
|
||||
}else if( largeMemory >= 256 ){
|
||||
maxSize = 64 * 1024; // 単位はKiB
|
||||
}else{
|
||||
maxSize = 10 * 1024; // 単位はKiB
|
||||
}
|
||||
|
||||
mCache = new LruCache< String, Bitmap >( maxSize ) {
|
||||
@Override
|
||||
protected int sizeOf( String key, Bitmap value ){
|
||||
int size = value.getRowBytes() * value.getHeight();
|
||||
size = ((size + 1023) >> 10); // 単位はKiB
|
||||
size = 1+(size>>10);
|
||||
return size <= 0 ? 1 : size;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override public Bitmap getBitmap( String url ){
|
||||
return mCache.get( url );
|
||||
}
|
||||
|
||||
@Override public void putBitmap( String url, Bitmap bitmap ){
|
||||
mCache.put( url, bitmap );
|
||||
}
|
||||
|
||||
}
|
||||
// private int getBitmapPoolSize( Context context ){
|
||||
// ActivityManager am = ((ActivityManager)context.getSystemService(Activity.ACTIVITY_SERVICE));
|
||||
// int memory = am.getMemoryClass();
|
||||
// int largeMemory = am.getLargeMemoryClass();
|
||||
// // どちらも単位はMB
|
||||
// log.d("MemoryClass=%d, LargeMemoryClass = %d",memory,largeMemory);
|
||||
//
|
||||
// int maxSize;
|
||||
// if( am.isLowRamDevice() ){
|
||||
// maxSize = 5 * 1024; // 単位はKiB
|
||||
// }else if( largeMemory >= 512 ){
|
||||
// maxSize = 128 * 1024; // 単位はKiB
|
||||
// }else if( largeMemory >= 256 ){
|
||||
// maxSize = 64 * 1024; // 単位はKiB
|
||||
// }else{
|
||||
// maxSize = 10 * 1024; // 単位はKiB
|
||||
// }
|
||||
// return maxSize * 1024;
|
||||
// }
|
||||
|
||||
public static OkHttpClient ok_http_client;
|
||||
|
||||
public static Typeface typeface_emoji;
|
||||
|
||||
// public static final RelationshipMap relationship_map = new RelationshipMap();
|
||||
|
||||
public static SharedPreferences pref;
|
||||
|
||||
|
||||
/**
|
||||
* An {@link Executor} that can be used to execute tasks in parallel.
|
||||
*/
|
||||
public static ThreadPoolExecutor task_executor;
|
||||
|
||||
static OkHttpUrlLoader.Factory glide_okhttp3_factory;
|
||||
|
||||
@Override
|
||||
public void onCreate(){
|
||||
|
@ -271,20 +209,21 @@ public class App1 extends Application {
|
|||
// the CPU with background work
|
||||
|
||||
int CPU_COUNT = Runtime.getRuntime().availableProcessors();
|
||||
int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
|
||||
int CORE_POOL_SIZE = Math.max( 2, Math.min( CPU_COUNT - 1, 4 ) );
|
||||
int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
|
||||
int KEEP_ALIVE_SECONDS = 30;
|
||||
|
||||
// デフォルトだとキューはmax128で、溢れることがある
|
||||
BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<>(999);
|
||||
|
||||
BlockingQueue< Runnable > sPoolWorkQueue = new LinkedBlockingQueue<>( 999 );
|
||||
|
||||
ThreadFactory sThreadFactory = new ThreadFactory() {
|
||||
private final AtomicInteger mCount = new AtomicInteger(1);
|
||||
public Thread newThread( @NonNull Runnable r) {
|
||||
return new Thread(r, "SubwayTooterTask #" + mCount.getAndIncrement());
|
||||
private final AtomicInteger mCount = new AtomicInteger( 1 );
|
||||
|
||||
public Thread newThread( @NonNull Runnable r ){
|
||||
return new Thread( r, "SubwayTooterTask #" + mCount.getAndIncrement() );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
task_executor = new ThreadPoolExecutor(
|
||||
CORE_POOL_SIZE // pool size
|
||||
, MAXIMUM_POOL_SIZE // max pool size
|
||||
|
@ -293,11 +232,10 @@ public class App1 extends Application {
|
|||
, sPoolWorkQueue
|
||||
, sThreadFactory
|
||||
);
|
||||
|
||||
task_executor.allowCoreThreadTimeOut(true);
|
||||
|
||||
task_executor.allowCoreThreadTimeOut( true );
|
||||
}
|
||||
|
||||
|
||||
if( pref == null ){
|
||||
pref = Pref.pref( getApplicationContext() );
|
||||
}
|
||||
|
@ -317,12 +255,12 @@ public class App1 extends Application {
|
|||
AcctSet.deleteOld( System.currentTimeMillis() );
|
||||
}
|
||||
|
||||
if( image_loader == null ){
|
||||
image_loader = new MyImageLoader(
|
||||
Volley.newRequestQueue( getApplicationContext() )
|
||||
, new BitmapCache( getApplicationContext() )
|
||||
);
|
||||
}
|
||||
// if( image_loader == null ){
|
||||
// image_loader = new MyImageLoader(
|
||||
// Volley.newRequestQueue( getApplicationContext() )
|
||||
// , new BitmapCache( getApplicationContext() )
|
||||
// );
|
||||
// }
|
||||
|
||||
if( ok_http_client == null ){
|
||||
|
||||
|
@ -333,17 +271,55 @@ public class App1 extends Application {
|
|||
ArrayList< ConnectionSpec > spec_list = new ArrayList<>();
|
||||
spec_list.add( spec );
|
||||
spec_list.add( ConnectionSpec.CLEARTEXT );
|
||||
|
||||
|
||||
OkHttpClient.Builder builder = new OkHttpClient.Builder()
|
||||
.connectTimeout( 30, TimeUnit.SECONDS )
|
||||
.readTimeout( 30, TimeUnit.SECONDS )
|
||||
.writeTimeout( 30, TimeUnit.SECONDS )
|
||||
.connectionSpecs( spec_list )
|
||||
;
|
||||
.connectionSpecs( spec_list );
|
||||
|
||||
ok_http_client = builder.build();
|
||||
}
|
||||
|
||||
// Glide.isSetup は Glide 4.0 で廃止になるらしいが、俺が使ってるのは3.xだ
|
||||
//noinspection deprecation
|
||||
if( ! Glide.isSetup() ){
|
||||
Context context = getApplicationContext();
|
||||
|
||||
GlideBuilder builder = new GlideBuilder( context );
|
||||
builder.setDiskCache( new InternalCacheDiskCacheFactory( context, 10 * 1024 * 1024 ) );
|
||||
|
||||
// 割とGlide任せで十分いけるっぽい
|
||||
// MemorySizeCalculator calculator = new MemorySizeCalculator(context);
|
||||
// int defaultMemoryCacheSize = calculator.getMemoryCacheSize();
|
||||
// int defaultBitmapPoolSize = calculator.getBitmapPoolSize();
|
||||
//
|
||||
// ActivityManager am = ((ActivityManager)context.getSystemService(Activity.ACTIVITY_SERVICE));
|
||||
// int class_memory = am.getMemoryClass(); // 単位はMB
|
||||
// int class_large = am.getLargeMemoryClass(); // 単位はMB
|
||||
//
|
||||
// int maxSize;
|
||||
// if( am.isLowRamDevice() ){
|
||||
// maxSize = 5 * 1024; // 単位はKiB
|
||||
// }else if( largeMemory >= 512 ){
|
||||
// maxSize = 128 * 1024; // 単位はKiB
|
||||
// }else if( largeMemory >= 256 ){
|
||||
// maxSize = 64 * 1024; // 単位はKiB
|
||||
// }else{
|
||||
// maxSize = 10 * 1024; // 単位はKiB
|
||||
// }
|
||||
// return maxSize * 1024;
|
||||
// }
|
||||
// builder.setMemoryCache(new LruResourceCache(getMemoryCacheSize(getApplicationContext())));
|
||||
// builder.setBitmapPool(new LruBitmapPool(getBitmapPoolSize(getApplicationContext())));
|
||||
|
||||
// Glide.setupはGLide 4.0 で廃止になるらしいが、俺が使ってるのは3.xだ
|
||||
//noinspection deprecation
|
||||
Glide.setup( builder );
|
||||
|
||||
glide_okhttp3_factory = new OkHttpUrlLoader.Factory( ok_http_client );
|
||||
Glide.get( getApplicationContext() ).register( GlideUrl.class, InputStream.class, glide_okhttp3_factory );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -355,7 +331,6 @@ public class App1 extends Application {
|
|||
private static AppState app_state;
|
||||
|
||||
static AppState getAppState( Context context ){
|
||||
// これは最後。loadColumnListでDBが必要になる
|
||||
if( app_state == null ){
|
||||
app_state = new AppState( context.getApplicationContext(), pref );
|
||||
}
|
||||
|
|
|
@ -102,9 +102,9 @@ class HeaderViewHolder implements View.OnClickListener, View.OnLongClickListener
|
|||
btnFollow.setImageDrawable( null );
|
||||
}else{
|
||||
tvCreated.setText( TootStatus.formatTime( who.time_created_at ) );
|
||||
ivBackground.setImageUrl( access_info.supplyBaseUrl( who.header_static ), App1.getImageLoader() );
|
||||
ivBackground.setImageUrl( access_info.supplyBaseUrl( who.header_static ) );
|
||||
ivAvatar.setCornerRadius( activity.pref,16f );
|
||||
ivAvatar.setImageUrl( access_info.supplyBaseUrl( who.avatar_static ), App1.getImageLoader() );
|
||||
ivAvatar.setImageUrl( access_info.supplyBaseUrl( who.avatar_static ) );
|
||||
tvDisplayName.setText( who.display_name );
|
||||
|
||||
String s = "@" + access_info.getFullAcct( who );
|
||||
|
|
|
@ -291,7 +291,7 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
|||
account_follow = who;
|
||||
llFollow.setVisibility( View.VISIBLE );
|
||||
ivFollow.setCornerRadius( activity.pref, 16f );
|
||||
ivFollow.setImageUrl( access_info.supplyBaseUrl( who.avatar_static ), App1.getImageLoader() );
|
||||
ivFollow.setImageUrl( access_info.supplyBaseUrl( who.avatar_static ) );
|
||||
tvFollowerName.setText( who.display_name );
|
||||
setAcct( tvFollowerAcct, access_info.getFullAcct( who ), R.attr.colorAcctSmall );
|
||||
|
||||
|
@ -309,7 +309,7 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
|||
|
||||
tvName.setText( status.account.display_name );
|
||||
ivThumbnail.setCornerRadius( activity.pref, 16f );
|
||||
ivThumbnail.setImageUrl( access_info.supplyBaseUrl( status.account.avatar_static ), App1.getImageLoader() );
|
||||
ivThumbnail.setImageUrl( access_info.supplyBaseUrl( status.account.avatar_static ) );
|
||||
tvContent.setText( status.decoded_content );
|
||||
|
||||
// if( status.decoded_tags == null ){
|
||||
|
@ -409,7 +409,7 @@ class ItemViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
|||
String url = ta.preview_url;
|
||||
if( TextUtils.isEmpty( url ) ) url = ta.remote_url;
|
||||
iv.setCornerRadius( activity.pref, 16f ); // 正方形じゃないせいか、うまく動かない activity.density * 4f );
|
||||
iv.setImageUrl( access_info.supplyBaseUrl( url ), App1.getImageLoader() );
|
||||
iv.setImageUrl( access_info.supplyBaseUrl( url ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ package jp.juggler.subwaytooter.view;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
|
||||
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
|
||||
import android.text.TextUtils;
|
||||
|
@ -9,36 +11,18 @@ import android.util.AttributeSet;
|
|||
import android.view.ViewGroup;
|
||||
import android.support.v7.widget.AppCompatImageView;
|
||||
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.ImageLoader;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.animation.GlideAnimation;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import jp.juggler.subwaytooter.Pref;
|
||||
|
||||
public class MyNetworkImageView extends AppCompatImageView {
|
||||
/**
|
||||
* The URL of the network image to load
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
/**
|
||||
* Resource ID of the image to be used as a placeholder until the network image is loaded.
|
||||
*/
|
||||
private int mDefaultImageId;
|
||||
|
||||
/**
|
||||
* Resource ID of the image to be used if the network response fails.
|
||||
*/
|
||||
private int mErrorImageId;
|
||||
|
||||
/**
|
||||
* Local copy of the ImageLoader.
|
||||
*/
|
||||
private ImageLoader mImageLoader;
|
||||
|
||||
/**
|
||||
* Current ImageContainer. (either in-flight or finished)
|
||||
*/
|
||||
private ImageLoader.ImageContainer mImageContainer;
|
||||
|
||||
public MyNetworkImageView( Context context ){
|
||||
this( context, null );
|
||||
|
@ -53,36 +37,19 @@ public class MyNetworkImageView extends AppCompatImageView {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets URL of the image that should be loaded into this view. Note that calling this will
|
||||
* immediately either set the cached image (if available) or the default image specified by
|
||||
* {@link com.android.volley.toolbox.NetworkImageView#setDefaultImageResId(int)} on the view.
|
||||
* <p>
|
||||
* NOTE: If applicable, {@link com.android.volley.toolbox.NetworkImageView#setDefaultImageResId(int)} and
|
||||
* {@link com.android.volley.toolbox.NetworkImageView#setErrorImageResId(int)} should be called prior to calling
|
||||
* this function.
|
||||
*
|
||||
* @param url The URL that should be loaded into this ImageView.
|
||||
* @param imageLoader ImageLoader that will be used to make the request.
|
||||
* Resource ID of the image to be used as a placeholder until the network image is loaded.
|
||||
*/
|
||||
public void setImageUrl( String url, ImageLoader imageLoader ){
|
||||
mUrl = url;
|
||||
mImageLoader = imageLoader;
|
||||
// The URL has potentially changed. See if we need to load it.
|
||||
loadImageIfNecessary( false );
|
||||
}
|
||||
private int mDefaultImageId;
|
||||
|
||||
/**
|
||||
* Sets the default image resource ID to be used for this view until the attempt to load it
|
||||
* completes.
|
||||
*/
|
||||
public void setDefaultImageResId( int defaultImage ){
|
||||
mDefaultImageId = defaultImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the error image resource ID to be used for this view in the event that the image
|
||||
* requested fails to load.
|
||||
* Resource ID of the image to be used if the network response fails.
|
||||
*/
|
||||
private int mErrorImageId;
|
||||
|
||||
public void setErrorImageResId( int errorImage ){
|
||||
mErrorImageId = errorImage;
|
||||
}
|
||||
|
@ -91,20 +58,49 @@ public class MyNetworkImageView extends AppCompatImageView {
|
|||
|
||||
// 元画像の短辺に対する割合を指定するらしい
|
||||
public void setCornerRadius( SharedPreferences pref, float r ){
|
||||
if( ! pref.getBoolean( Pref.KEY_DONT_ROUND,false ) ){
|
||||
if( ! pref.getBoolean( Pref.KEY_DONT_ROUND, false ) ){
|
||||
mCornerRadius = r;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL of the network image to load
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public void setImageUrl( String url ){
|
||||
mUrl = url;
|
||||
// The URL has potentially changed. See if we need to load it.
|
||||
loadImageIfNecessary(false);
|
||||
}
|
||||
|
||||
Target< ? > mTarget;
|
||||
String mTargetUrl;
|
||||
|
||||
private void cancelLoading(){
|
||||
if( mTarget != null ){
|
||||
setImageDrawable( null );
|
||||
Glide.clear( mTarget );
|
||||
mTarget = null;
|
||||
mTargetUrl = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void setDefaultImageOrNull(){
|
||||
if( mDefaultImageId != 0 ){
|
||||
setImageResource( mDefaultImageId );
|
||||
}else{
|
||||
setImageDrawable( null );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the image for the view if it isn't already loaded.
|
||||
*
|
||||
* @param isInLayoutPass True if this was invoked from a layout pass, false otherwise.
|
||||
*/
|
||||
void loadImageIfNecessary( final boolean isInLayoutPass ){
|
||||
void loadImageIfNecessary(final boolean isInLayoutPass){
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
ScaleType scaleType = getScaleType();
|
||||
|
||||
boolean wrapWidth = false, wrapHeight = false;
|
||||
if( getLayoutParams() != null ){
|
||||
|
@ -122,106 +118,82 @@ public class MyNetworkImageView extends AppCompatImageView {
|
|||
// if the URL to be loaded in this view is empty, cancel any old requests and clear the
|
||||
// currently loaded image.
|
||||
if( TextUtils.isEmpty( mUrl ) ){
|
||||
if( mImageContainer != null ){
|
||||
mImageContainer.cancelRequest();
|
||||
mImageContainer = null;
|
||||
}
|
||||
cancelLoading();
|
||||
setDefaultImageOrNull();
|
||||
return;
|
||||
}else if( mTarget != null ){
|
||||
// if there was an old request in this view, check if it needs to be canceled.
|
||||
// if the request is from the same URL, return.
|
||||
if( mUrl.equals( mTargetUrl ) ) return;
|
||||
|
||||
// if there is a pre-existing request, cancel it if it's fetching a different URL.
|
||||
cancelLoading();
|
||||
}
|
||||
|
||||
// if there was an old request in this view, check if it needs to be canceled.
|
||||
if( mImageContainer != null && mImageContainer.getRequestUrl() != null ){
|
||||
if( mImageContainer.getRequestUrl().equals( mUrl ) ){
|
||||
// if the request is from the same URL, return.
|
||||
return;
|
||||
}else{
|
||||
// if there is a pre-existing request, cancel it if it's fetching a different URL.
|
||||
mImageContainer.cancelRequest();
|
||||
setDefaultImageOrNull();
|
||||
}
|
||||
}
|
||||
setDefaultImageOrNull();
|
||||
|
||||
// Calculate the max image width / height to use while ignoring WRAP_CONTENT dimens.
|
||||
int maxWidth = wrapWidth ? 0 : width;
|
||||
int maxHeight = wrapHeight ? 0 : height;
|
||||
int desiredWidth = wrapWidth ? Target.SIZE_ORIGINAL : width;
|
||||
int desiredHeight = wrapHeight ? Target.SIZE_ORIGINAL : height;
|
||||
|
||||
// The pre-existing content of this view didn't match the current URL. Load the new image
|
||||
// from the network.
|
||||
ImageLoader.ImageContainer newContainer = mImageLoader.get( mUrl,
|
||||
new ImageLoader.ImageListener() {
|
||||
@Override
|
||||
public void onErrorResponse( VolleyError error ){
|
||||
if( mErrorImageId != 0 ){
|
||||
setImageResource( mErrorImageId );
|
||||
}
|
||||
final AtomicBoolean isImmediate = new AtomicBoolean(true);
|
||||
mTargetUrl = mUrl;
|
||||
mTarget = Glide.with( getContext() )
|
||||
.load( mUrl )
|
||||
.asBitmap()
|
||||
.into(
|
||||
new SimpleTarget< Bitmap >( desiredWidth, desiredHeight ) {
|
||||
@Override public void onLoadFailed( Exception e, Drawable errorDrawable ){
|
||||
e.printStackTrace();
|
||||
if( mErrorImageId != 0 ) setImageResource( mErrorImageId );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse( final ImageLoader.ImageContainer response, boolean isImmediate ){
|
||||
// If this was an immediate response that was delivered inside of a layout
|
||||
// pass do not set the image immediately as it will trigger a requestLayout
|
||||
// inside of a layout. Instead, defer setting the image by posting back to
|
||||
// the main thread.
|
||||
if( isImmediate && isInLayoutPass ){
|
||||
@Override public void onResourceReady(
|
||||
final Bitmap bitmap
|
||||
,final GlideAnimation< ? super Bitmap > glideAnimation
|
||||
){
|
||||
if( isImmediate.get() && isInLayoutPass ){
|
||||
post( new Runnable() {
|
||||
@Override
|
||||
public void run(){
|
||||
onResponse( response, false );
|
||||
onResourceReady( bitmap, glideAnimation );
|
||||
}
|
||||
} );
|
||||
return;
|
||||
}
|
||||
|
||||
if( response.getBitmap() != null ){
|
||||
if( mCornerRadius > 0f ){
|
||||
RoundedBitmapDrawable d = RoundedBitmapDrawableFactory
|
||||
.create( getResources(), response.getBitmap() );
|
||||
d.setCornerRadius( mCornerRadius );
|
||||
setImageDrawable( d );
|
||||
}else{
|
||||
setImageBitmap( response.getBitmap() );
|
||||
|
||||
}
|
||||
}else if( mDefaultImageId != 0 ){
|
||||
setImageResource( mDefaultImageId );
|
||||
if( bitmap == null ){
|
||||
setDefaultImageOrNull();
|
||||
}else if( mCornerRadius <= 0f ){
|
||||
setImageBitmap( bitmap );
|
||||
}else{
|
||||
RoundedBitmapDrawable d = RoundedBitmapDrawableFactory
|
||||
.create( getResources(), bitmap );
|
||||
d.setCornerRadius( mCornerRadius );
|
||||
setImageDrawable( d );
|
||||
}
|
||||
}
|
||||
}, maxWidth, maxHeight, scaleType );
|
||||
|
||||
// update the ImageContainer to be the new bitmap container.
|
||||
mImageContainer = newContainer;
|
||||
}
|
||||
);
|
||||
isImmediate.set(false);
|
||||
}
|
||||
|
||||
private void setDefaultImageOrNull(){
|
||||
if( mDefaultImageId != 0 ){
|
||||
setImageResource( mDefaultImageId );
|
||||
}else{
|
||||
setImageBitmap( null );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout( boolean changed, int left, int top, int right, int bottom ){
|
||||
|
||||
@Override protected void onLayout( boolean changed, int left, int top, int right, int bottom ){
|
||||
super.onLayout( changed, left, top, right, bottom );
|
||||
loadImageIfNecessary( true );
|
||||
loadImageIfNecessary(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow(){
|
||||
if( mImageContainer != null ){
|
||||
// If the view was bound to an image request, cancel it and clear
|
||||
// out the image from the view.
|
||||
mImageContainer.cancelRequest();
|
||||
setImageBitmap( null );
|
||||
// also clear out the container so we can reload the image if necessary.
|
||||
mImageContainer = null;
|
||||
}
|
||||
@Override protected void onDetachedFromWindow(){
|
||||
cancelLoading();
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawableStateChanged(){
|
||||
@Override protected void onAttachedToWindow(){
|
||||
super.onAttachedToWindow();
|
||||
loadImageIfNecessary(true);
|
||||
}
|
||||
|
||||
@Override protected void drawableStateChanged(){
|
||||
super.drawableStateChanged();
|
||||
invalidate();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue