Updated Volley

captchafix
Florens Douwes 11 years ago
parent 010a1c2cef
commit 197edd1d61
  1. 3
      Chan/src/com/android/volley/AuthFailureError.java
  2. 13
      Chan/src/com/android/volley/CacheDispatcher.java
  3. 4
      Chan/src/com/android/volley/ExecutorDelivery.java
  4. 25
      Chan/src/com/android/volley/NetworkDispatcher.java
  5. 2
      Chan/src/com/android/volley/NetworkError.java
  6. 4
      Chan/src/com/android/volley/NetworkResponse.java
  7. 2
      Chan/src/com/android/volley/ParseError.java
  8. 67
      Chan/src/com/android/volley/Request.java
  9. 33
      Chan/src/com/android/volley/RequestQueue.java
  10. 2
      Chan/src/com/android/volley/ServerError.java
  11. 6
      Chan/src/com/android/volley/VolleyLog.java
  12. 7
      Chan/src/com/android/volley/toolbox/AndroidAuthenticator.java
  13. 35
      Chan/src/com/android/volley/toolbox/BasicNetwork.java
  14. 6
      Chan/src/com/android/volley/toolbox/ClearCacheRequest.java
  15. 14
      Chan/src/com/android/volley/toolbox/DiskBasedCache.java
  16. 63
      Chan/src/com/android/volley/toolbox/HttpClientStack.java
  17. 6
      Chan/src/com/android/volley/toolbox/HttpHeaderParser.java
  18. 8
      Chan/src/com/android/volley/toolbox/HttpStack.java
  19. 41
      Chan/src/com/android/volley/toolbox/HurlStack.java
  20. 13
      Chan/src/com/android/volley/toolbox/ImageLoader.java
  21. 8
      Chan/src/com/android/volley/toolbox/ImageRequest.java
  22. 10
      Chan/src/com/android/volley/toolbox/JsonArrayRequest.java
  23. 10
      Chan/src/com/android/volley/toolbox/JsonObjectRequest.java
  24. 4
      Chan/src/com/android/volley/toolbox/JsonRequest.java
  25. 68
      Chan/src/com/android/volley/toolbox/NetworkImageView.java
  26. 8
      Chan/src/com/android/volley/toolbox/RequestFuture.java
  27. 4
      Chan/src/com/android/volley/toolbox/StringRequest.java
  28. 4
      Chan/src/com/android/volley/toolbox/Volley.java
  29. 2
      Chan/src/org/floens/chan/ChanApplication.java
  30. 6
      Chan/src/org/floens/chan/core/net/BitmapLruImageCache.java
  31. 1
      Chan/src/org/floens/chan/core/net/BoardsRequest.java
  32. 1
      Chan/src/org/floens/chan/core/net/ChanReaderRequest.java
  33. 26
      Chan/src/org/floens/chan/core/net/JsonReaderRequest.java
  34. 277
      Chan/src/org/floens/chan/ui/view/CustomNetworkImageView.java
  35. 29
      Chan/src/org/floens/chan/ui/view/NetworkPhotoView.java
  36. 4
      Chan/src/org/floens/chan/ui/view/PostView.java

@ -18,6 +18,9 @@ package com.android.volley;
import android.content.Intent; import android.content.Intent;
import com.android.volley.NetworkResponse;
import com.android.volley.VolleyError;
/** /**
* Error indicating that there was an authentication failure when performing a Request. * Error indicating that there was an authentication failure when performing a Request.
*/ */

@ -16,10 +16,10 @@
package com.android.volley; package com.android.volley;
import java.util.concurrent.BlockingQueue;
import android.os.Process; import android.os.Process;
import java.util.concurrent.BlockingQueue;
/** /**
* Provides a thread for performing cache triage on a queue of requests. * Provides a thread for performing cache triage on a queue of requests.
* *
@ -29,16 +29,15 @@ import android.os.Process;
* refresh are enqueued on the specified network queue for processing * refresh are enqueued on the specified network queue for processing
* by a {@link NetworkDispatcher}. * by a {@link NetworkDispatcher}.
*/ */
@SuppressWarnings("rawtypes")
public class CacheDispatcher extends Thread { public class CacheDispatcher extends Thread {
private static final boolean DEBUG = VolleyLog.DEBUG; private static final boolean DEBUG = VolleyLog.DEBUG;
/** The queue of requests coming in for triage. */ /** The queue of requests coming in for triage. */
private final BlockingQueue<Request> mCacheQueue; private final BlockingQueue<Request<?>> mCacheQueue;
/** The queue of requests going out to the network. */ /** The queue of requests going out to the network. */
private final BlockingQueue<Request> mNetworkQueue; private final BlockingQueue<Request<?>> mNetworkQueue;
/** The cache to read from. */ /** The cache to read from. */
private final Cache mCache; private final Cache mCache;
@ -59,7 +58,7 @@ public class CacheDispatcher extends Thread {
* @param delivery Delivery interface to use for posting responses * @param delivery Delivery interface to use for posting responses
*/ */
public CacheDispatcher( public CacheDispatcher(
BlockingQueue<Request> cacheQueue, BlockingQueue<Request> networkQueue, BlockingQueue<Request<?>> cacheQueue, BlockingQueue<Request<?>> networkQueue,
Cache cache, ResponseDelivery delivery) { Cache cache, ResponseDelivery delivery) {
mCacheQueue = cacheQueue; mCacheQueue = cacheQueue;
mNetworkQueue = networkQueue; mNetworkQueue = networkQueue;
@ -88,7 +87,7 @@ public class CacheDispatcher extends Thread {
try { try {
// Get a request from the cache triage queue, blocking until // Get a request from the cache triage queue, blocking until
// at least one is available. // at least one is available.
final Request request = mCacheQueue.take(); final Request<?> request = mCacheQueue.take();
request.addMarker("cache-queue-take"); request.addMarker("cache-queue-take");
// If the request has been canceled, don't bother dispatching it. // If the request has been canceled, don't bother dispatching it.

@ -16,10 +16,10 @@
package com.android.volley; package com.android.volley;
import java.util.concurrent.Executor;
import android.os.Handler; import android.os.Handler;
import java.util.concurrent.Executor;
/** /**
* Delivers responses and errors. * Delivers responses and errors.
*/ */

@ -16,12 +16,13 @@
package com.android.volley; package com.android.volley;
import java.util.concurrent.BlockingQueue; import android.annotation.TargetApi;
import android.net.TrafficStats; import android.net.TrafficStats;
import android.os.Build; import android.os.Build;
import android.os.Process; import android.os.Process;
import java.util.concurrent.BlockingQueue;
/** /**
* Provides a thread for performing network dispatch from a queue of requests. * Provides a thread for performing network dispatch from a queue of requests.
* *
@ -30,10 +31,9 @@ import android.os.Process;
* eligible, using a specified {@link Cache} interface. Valid responses and * eligible, using a specified {@link Cache} interface. Valid responses and
* errors are posted back to the caller via a {@link ResponseDelivery}. * errors are posted back to the caller via a {@link ResponseDelivery}.
*/ */
@SuppressWarnings("rawtypes")
public class NetworkDispatcher extends Thread { public class NetworkDispatcher extends Thread {
/** The queue of requests to service. */ /** The queue of requests to service. */
private final BlockingQueue<Request> mQueue; private final BlockingQueue<Request<?>> mQueue;
/** The network interface for processing requests. */ /** The network interface for processing requests. */
private final Network mNetwork; private final Network mNetwork;
/** The cache to write to. */ /** The cache to write to. */
@ -52,7 +52,7 @@ public class NetworkDispatcher extends Thread {
* @param cache Cache interface to use for writing responses to cache * @param cache Cache interface to use for writing responses to cache
* @param delivery Delivery interface to use for posting responses * @param delivery Delivery interface to use for posting responses
*/ */
public NetworkDispatcher(BlockingQueue<Request> queue, public NetworkDispatcher(BlockingQueue<Request<?>> queue,
Network network, Cache cache, Network network, Cache cache,
ResponseDelivery delivery) { ResponseDelivery delivery) {
mQueue = queue; mQueue = queue;
@ -70,10 +70,18 @@ public class NetworkDispatcher extends Thread {
interrupt(); interrupt();
} }
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void addTrafficStatsTag(Request<?> request) {
// Tag the request (if API >= 14)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
TrafficStats.setThreadStatsTag(request.getTrafficStatsTag());
}
}
@Override @Override
public void run() { public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Request request; Request<?> request;
while (true) { while (true) {
try { try {
// Take a request from the queue. // Take a request from the queue.
@ -96,10 +104,7 @@ public class NetworkDispatcher extends Thread {
continue; continue;
} }
// Tag the request (if API >= 14) addTrafficStatsTag(request);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
TrafficStats.setThreadStatsTag(request.getTrafficStatsTag());
}
// Perform the network request. // Perform the network request.
NetworkResponse networkResponse = mNetwork.performRequest(request); NetworkResponse networkResponse = mNetwork.performRequest(request);

@ -16,6 +16,8 @@
package com.android.volley; package com.android.volley;
import com.android.volley.NetworkResponse;
import com.android.volley.VolleyError;
/** /**
* Indicates that there was a network error when performing a Volley request. * Indicates that there was a network error when performing a Volley request.

@ -16,11 +16,11 @@
package com.android.volley; package com.android.volley;
import org.apache.http.HttpStatus;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import org.apache.http.HttpStatus;
/** /**
* Data and headers returned from {@link Network#performRequest(Request)}. * Data and headers returned from {@link Network#performRequest(Request)}.
*/ */

@ -16,6 +16,8 @@
package com.android.volley; package com.android.volley;
import com.android.volley.NetworkResponse;
import com.android.volley.VolleyError;
/** /**
* Indicates that the server's response could not be parsed. * Indicates that the server's response could not be parsed.

@ -16,11 +16,6 @@
package com.android.volley; package com.android.volley;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.Map;
import android.net.TrafficStats; import android.net.TrafficStats;
import android.net.Uri; import android.net.Uri;
import android.os.Handler; import android.os.Handler;
@ -30,6 +25,11 @@ import android.text.TextUtils;
import com.android.volley.VolleyLog.MarkerLog; import com.android.volley.VolleyLog.MarkerLog;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.Map;
/** /**
* Base class for all network requests. * Base class for all network requests.
* *
@ -51,12 +51,19 @@ public abstract class Request<T> implements Comparable<Request<T>> {
int POST = 1; int POST = 1;
int PUT = 2; int PUT = 2;
int DELETE = 3; int DELETE = 3;
int HEAD = 4;
int OPTIONS = 5;
int TRACE = 6;
int PATCH = 7;
} }
/** An event log tracing the lifetime of this request; for debugging. */ /** An event log tracing the lifetime of this request; for debugging. */
private final MarkerLog mEventLog = MarkerLog.ENABLED ? new MarkerLog() : null; private final MarkerLog mEventLog = MarkerLog.ENABLED ? new MarkerLog() : null;
/** Request method of this request. Currently supports GET, POST, PUT, and DELETE. */ /**
* Request method of this request. Currently supports GET, POST, PUT, DELETE, HEAD, OPTIONS,
* TRACE, and PATCH.
*/
private final int mMethod; private final int mMethod;
/** URL of this request. */ /** URL of this request. */
@ -127,7 +134,7 @@ public abstract class Request<T> implements Comparable<Request<T>> {
mErrorListener = listener; mErrorListener = listener;
setRetryPolicy(new DefaultRetryPolicy()); setRetryPolicy(new DefaultRetryPolicy());
mDefaultTrafficStatsTag = TextUtils.isEmpty(url) ? 0: Uri.parse(url).getHost().hashCode(); mDefaultTrafficStatsTag = findDefaultTrafficStatsTag(url);
} }
/** /**
@ -140,9 +147,12 @@ public abstract class Request<T> implements Comparable<Request<T>> {
/** /**
* Set a tag on this request. Can be used to cancel all requests with this * Set a tag on this request. Can be used to cancel all requests with this
* tag by {@link RequestQueue#cancelAll(Object)}. * tag by {@link RequestQueue#cancelAll(Object)}.
*
* @return This Request object to allow for chaining.
*/ */
public void setTag(Object tag) { public Request<?> setTag(Object tag) {
mTag = tag; mTag = tag;
return this;
} }
/** /**
@ -160,11 +170,30 @@ public abstract class Request<T> implements Comparable<Request<T>> {
return mDefaultTrafficStatsTag; return mDefaultTrafficStatsTag;
} }
/**
* @return The hashcode of the URL's host component, or 0 if there is none.
*/
private static int findDefaultTrafficStatsTag(String url) {
if (!TextUtils.isEmpty(url)) {
Uri uri = Uri.parse(url);
if (uri != null) {
String host = uri.getHost();
if (host != null) {
return host.hashCode();
}
}
}
return 0;
}
/** /**
* Sets the retry policy for this request. * Sets the retry policy for this request.
*
* @return This Request object to allow for chaining.
*/ */
public void setRetryPolicy(RetryPolicy retryPolicy) { public Request<?> setRetryPolicy(RetryPolicy retryPolicy) {
mRetryPolicy = retryPolicy; mRetryPolicy = retryPolicy;
return this;
} }
/** /**
@ -216,16 +245,22 @@ public abstract class Request<T> implements Comparable<Request<T>> {
/** /**
* Associates this request with the given queue. The request queue will be notified when this * Associates this request with the given queue. The request queue will be notified when this
* request has finished. * request has finished.
*
* @return This Request object to allow for chaining.
*/ */
public void setRequestQueue(RequestQueue requestQueue) { public Request<?> setRequestQueue(RequestQueue requestQueue) {
mRequestQueue = requestQueue; mRequestQueue = requestQueue;
return this;
} }
/** /**
* Sets the sequence number of this request. Used by {@link RequestQueue}. * Sets the sequence number of this request. Used by {@link RequestQueue}.
*
* @return This Request object to allow for chaining.
*/ */
public final void setSequence(int sequence) { public final Request<?> setSequence(int sequence) {
mSequence = sequence; mSequence = sequence;
return this;
} }
/** /**
@ -255,9 +290,12 @@ public abstract class Request<T> implements Comparable<Request<T>> {
/** /**
* Annotates this request with an entry retrieved for it from cache. * Annotates this request with an entry retrieved for it from cache.
* Used for cache coherency support. * Used for cache coherency support.
*
* @return This Request object to allow for chaining.
*/ */
public void setCacheEntry(Cache.Entry entry) { public Request<?> setCacheEntry(Cache.Entry entry) {
mCacheEntry = entry; mCacheEntry = entry;
return this;
} }
/** /**
@ -419,9 +457,12 @@ public abstract class Request<T> implements Comparable<Request<T>> {
/** /**
* Set whether or not responses to this request should be cached. * Set whether or not responses to this request should be cached.
*
* @return This Request object to allow for chaining.
*/ */
public final void setShouldCache(boolean shouldCache) { public final Request<?> setShouldCache(boolean shouldCache) {
mShouldCache = shouldCache; mShouldCache = shouldCache;
return this;
} }
/** /**

@ -16,6 +16,9 @@
package com.android.volley; package com.android.volley;
import android.os.Handler;
import android.os.Looper;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
@ -25,9 +28,6 @@ import java.util.Set;
import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import android.os.Handler;
import android.os.Looper;
/** /**
* A request dispatch queue with a thread pool of dispatchers. * A request dispatch queue with a thread pool of dispatchers.
* *
@ -35,7 +35,6 @@ import android.os.Looper;
* resolving from either cache or network on a worker thread, and then delivering * resolving from either cache or network on a worker thread, and then delivering
* a parsed response on the main thread. * a parsed response on the main thread.
*/ */
@SuppressWarnings("rawtypes")
public class RequestQueue { public class RequestQueue {
/** Used for generating monotonically-increasing sequence numbers for requests. */ /** Used for generating monotonically-increasing sequence numbers for requests. */
@ -51,28 +50,28 @@ public class RequestQueue {
* is <em>not</em> contained in that list. Is null if no requests are staged.</li> * is <em>not</em> contained in that list. Is null if no requests are staged.</li>
* </ul> * </ul>
*/ */
private final Map<String, Queue<Request>> mWaitingRequests = private final Map<String, Queue<Request<?>>> mWaitingRequests =
new HashMap<String, Queue<Request>>(); new HashMap<String, Queue<Request<?>>>();
/** /**
* The set of all requests currently being processed by this RequestQueue. A Request * The set of all requests currently being processed by this RequestQueue. A Request
* will be in this set if it is waiting in any queue or currently being processed by * will be in this set if it is waiting in any queue or currently being processed by
* any dispatcher. * any dispatcher.
*/ */
private final Set<Request> mCurrentRequests = new HashSet<Request>(); private final Set<Request<?>> mCurrentRequests = new HashSet<Request<?>>();
/** The cache triage queue. */ /** The cache triage queue. */
private final PriorityBlockingQueue<Request> mCacheQueue = private final PriorityBlockingQueue<Request<?>> mCacheQueue =
new PriorityBlockingQueue<Request>(); new PriorityBlockingQueue<Request<?>>();
/** The queue of requests that are actually going out to the network. */ /** The queue of requests that are actually going out to the network. */
private final PriorityBlockingQueue<Request> mNetworkQueue = private final PriorityBlockingQueue<Request<?>> mNetworkQueue =
new PriorityBlockingQueue<Request>(); new PriorityBlockingQueue<Request<?>>();
/** Number of network request dispatcher threads to start. */ /** Number of network request dispatcher threads to start. */
private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4; private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4;
/** Cache interface for retrieving and storing respones. */ /** Cache interface for retrieving and storing responses. */
private final Cache mCache; private final Cache mCache;
/** Network interface for performing requests. */ /** Network interface for performing requests. */
@ -214,7 +213,7 @@ public class RequestQueue {
* @param request The request to service * @param request The request to service
* @return The passed-in request * @return The passed-in request
*/ */
public Request add(Request request) { public <T> Request<T> add(Request<T> request) {
// Tag the request as belonging to this queue and add it to the set of current requests. // Tag the request as belonging to this queue and add it to the set of current requests.
request.setRequestQueue(this); request.setRequestQueue(this);
synchronized (mCurrentRequests) { synchronized (mCurrentRequests) {
@ -236,9 +235,9 @@ public class RequestQueue {
String cacheKey = request.getCacheKey(); String cacheKey = request.getCacheKey();
if (mWaitingRequests.containsKey(cacheKey)) { if (mWaitingRequests.containsKey(cacheKey)) {
// There is already a request in flight. Queue up. // There is already a request in flight. Queue up.
Queue<Request> stagedRequests = mWaitingRequests.get(cacheKey); Queue<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey);
if (stagedRequests == null) { if (stagedRequests == null) {
stagedRequests = new LinkedList<Request>(); stagedRequests = new LinkedList<Request<?>>();
} }
stagedRequests.add(request); stagedRequests.add(request);
mWaitingRequests.put(cacheKey, stagedRequests); mWaitingRequests.put(cacheKey, stagedRequests);
@ -262,7 +261,7 @@ public class RequestQueue {
* <p>Releases waiting requests for <code>request.getCacheKey()</code> if * <p>Releases waiting requests for <code>request.getCacheKey()</code> if
* <code>request.shouldCache()</code>.</p> * <code>request.shouldCache()</code>.</p>
*/ */
void finish(Request request) { void finish(Request<?> request) {
// Remove from the set of requests currently being processed. // Remove from the set of requests currently being processed.
synchronized (mCurrentRequests) { synchronized (mCurrentRequests) {
mCurrentRequests.remove(request); mCurrentRequests.remove(request);
@ -271,7 +270,7 @@ public class RequestQueue {
if (request.shouldCache()) { if (request.shouldCache()) {
synchronized (mWaitingRequests) { synchronized (mWaitingRequests) {
String cacheKey = request.getCacheKey(); String cacheKey = request.getCacheKey();
Queue<Request> waitingRequests = mWaitingRequests.remove(cacheKey); Queue<Request<?>> waitingRequests = mWaitingRequests.remove(cacheKey);
if (waitingRequests != null) { if (waitingRequests != null) {
if (VolleyLog.DEBUG) { if (VolleyLog.DEBUG) {
VolleyLog.v("Releasing %d waiting requests for cacheKey=%s.", VolleyLog.v("Releasing %d waiting requests for cacheKey=%s.",

@ -16,6 +16,8 @@
package com.android.volley; package com.android.volley;
import com.android.volley.NetworkResponse;
import com.android.volley.VolleyError;
/** /**
* Indicates that the error responded with an error response. * Indicates that the error responded with an error response.

@ -16,13 +16,13 @@
package com.android.volley; package com.android.volley;
import android.os.SystemClock;
import android.util.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import android.os.SystemClock;
import android.util.Log;
/** Logging helper class. */ /** Logging helper class. */
public class VolleyLog { public class VolleyLog {
public static String TAG = "Volley"; public static String TAG = "Volley";

@ -16,6 +16,8 @@
package com.android.volley.toolbox; package com.android.volley.toolbox;
import com.android.volley.AuthFailureError;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture; import android.accounts.AccountManagerFuture;
@ -23,8 +25,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import com.android.volley.AuthFailureError;
/** /**
* An Authenticator that uses {@link AccountManager} to get auth * An Authenticator that uses {@link AccountManager} to get auth
* tokens of a specified type for a specified account. * tokens of a specified type for a specified account.
@ -67,10 +67,11 @@ public class AndroidAuthenticator implements Authenticator {
return mAccount; return mAccount;
} }
// TODO: Figure out what to do about notifyAuthFailure
@SuppressWarnings("deprecation")
@Override @Override
public String getAuthToken() throws AuthFailureError { public String getAuthToken() throws AuthFailureError {
final AccountManager accountManager = AccountManager.get(mContext); final AccountManager accountManager = AccountManager.get(mContext);
@SuppressWarnings("deprecation")
AccountManagerFuture<Bundle> future = accountManager.getAuthToken(mAccount, AccountManagerFuture<Bundle> future = accountManager.getAuthToken(mAccount,
mAuthTokenType, mNotifyAuthFailure, null, null); mAuthTokenType, mNotifyAuthFailure, null, null);
Bundle result; Bundle result;

@ -16,22 +16,6 @@
package com.android.volley.toolbox; package com.android.volley.toolbox;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.cookie.DateUtils;
import android.os.SystemClock; import android.os.SystemClock;
import com.android.volley.AuthFailureError; import com.android.volley.AuthFailureError;
@ -47,6 +31,22 @@ import com.android.volley.TimeoutError;
import com.android.volley.VolleyError; import com.android.volley.VolleyError;
import com.android.volley.VolleyLog; import com.android.volley.VolleyLog;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.cookie.DateUtils;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/** /**
* A network performing Volley requests over an {@link HttpStack}. * A network performing Volley requests over an {@link HttpStack}.
*/ */
@ -98,7 +98,8 @@ public class BasicNetwork implements Network {
// Handle cache validation. // Handle cache validation.
if (statusCode == HttpStatus.SC_NOT_MODIFIED) { if (statusCode == HttpStatus.SC_NOT_MODIFIED) {
return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,
request.getCacheEntry().data, responseHeaders, true); request.getCacheEntry() == null ? null : request.getCacheEntry().data,
responseHeaders, true);
} }
// Some responses such as 204s do not have content. We must check. // Some responses such as 204s do not have content. We must check.

@ -16,14 +16,14 @@
package com.android.volley.toolbox; package com.android.volley.toolbox;
import android.os.Handler;
import android.os.Looper;
import com.android.volley.Cache; import com.android.volley.Cache;
import com.android.volley.NetworkResponse; import com.android.volley.NetworkResponse;
import com.android.volley.Request; import com.android.volley.Request;
import com.android.volley.Response; import com.android.volley.Response;
import android.os.Handler;
import android.os.Looper;
/** /**
* A synthetic request used for clearing the cache. * A synthetic request used for clearing the cache.
*/ */

@ -55,7 +55,7 @@ public class DiskBasedCache implements Cache {
private final int mMaxCacheSizeInBytes; private final int mMaxCacheSizeInBytes;
/** Default maximum disk usage in bytes. */ /** Default maximum disk usage in bytes. */
private static final int DEFAULT_DISK_USAGE_BYTES = 25 * 1024 * 1024; private static final int DEFAULT_DISK_USAGE_BYTES = 50 * 1024 * 1024;
/** High water mark percentage for the cache */ /** High water mark percentage for the cache */
private static final float HYSTERESIS_FACTOR = 0.9f; private static final float HYSTERESIS_FACTOR = 0.9f;
@ -361,12 +361,12 @@ public class DiskBasedCache implements Cache {
*/ */
public CacheHeader(String key, Entry entry) { public CacheHeader(String key, Entry entry) {
this.key = key; this.key = key;
this.size = entry.data.length; size = entry.data.length;
this.etag = entry.etag; etag = entry.etag;
this.serverDate = entry.serverDate; serverDate = entry.serverDate;
this.ttl = entry.ttl; ttl = entry.ttl;
this.softTtl = entry.softTtl; softTtl = entry.softTtl;
this.responseHeaders = entry.responseHeaders; responseHeaders = entry.responseHeaders;
} }
/** /**

@ -16,10 +16,9 @@
package com.android.volley.toolbox; package com.android.volley.toolbox;
import java.io.IOException; import com.android.volley.AuthFailureError;
import java.util.ArrayList; import com.android.volley.Request;
import java.util.List; import com.android.volley.Request.Method;
import java.util.Map;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
@ -28,22 +27,26 @@ import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpOptions;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpTrace;
import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.message.BasicNameValuePair; import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams; import org.apache.http.params.HttpParams;
import com.android.volley.AuthFailureError; import java.io.IOException;
import com.android.volley.Request; import java.net.URI;
import com.android.volley.Request.Method; import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/** /**
* An HttpStack that performs request over an {@link HttpClient}. * An HttpStack that performs request over an {@link HttpClient}.
*/ */
@SuppressWarnings("deprecation")
public class HttpClientStack implements HttpStack { public class HttpClientStack implements HttpStack {
protected final HttpClient mClient; protected final HttpClient mClient;
@ -87,6 +90,7 @@ public class HttpClientStack implements HttpStack {
/** /**
* Creates the appropriate subclass of HttpUriRequest for passed in request. * Creates the appropriate subclass of HttpUriRequest for passed in request.
*/ */
@SuppressWarnings("deprecation")
/* protected */ static HttpUriRequest createHttpRequest(Request<?> request, /* protected */ static HttpUriRequest createHttpRequest(Request<?> request,
Map<String, String> additionalHeaders) throws AuthFailureError { Map<String, String> additionalHeaders) throws AuthFailureError {
switch (request.getMethod()) { switch (request.getMethod()) {
@ -122,6 +126,18 @@ public class HttpClientStack implements HttpStack {
setEntityIfNonEmptyBody(putRequest, request); setEntityIfNonEmptyBody(putRequest, request);
return putRequest; return putRequest;
} }
case Method.HEAD:
return new HttpHead(request.getUrl());
case Method.OPTIONS:
return new HttpOptions(request.getUrl());
case Method.TRACE:
return new HttpTrace(request.getUrl());
case Method.PATCH: {
HttpPatch patchRequest = new HttpPatch(request.getUrl());
patchRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
setEntityIfNonEmptyBody(patchRequest, request);
return patchRequest;
}
default: default:
throw new IllegalStateException("Unknown request method."); throw new IllegalStateException("Unknown request method.");
} }
@ -144,4 +160,35 @@ public class HttpClientStack implements HttpStack {
protected void onPrepareRequest(HttpUriRequest request) throws IOException { protected void onPrepareRequest(HttpUriRequest request) throws IOException {
// Nothing. // Nothing.
} }
/**
* The HttpPatch class does not exist in the Android framework, so this has been defined here.
*/
public static final class HttpPatch extends HttpEntityEnclosingRequestBase {
public final static String METHOD_NAME = "PATCH";
public HttpPatch() {
super();
}
public HttpPatch(final URI uri) {
super();
setURI(uri);
}
/**
* @throws IllegalArgumentException if the uri is invalid.
*/
public HttpPatch(final String uri) {
super();
setURI(URI.create(uri));
}
@Override
public String getMethod() {
return METHOD_NAME;
}
}
} }

@ -16,14 +16,14 @@
package com.android.volley.toolbox; package com.android.volley.toolbox;
import java.util.Map; import com.android.volley.Cache;
import com.android.volley.NetworkResponse;
import org.apache.http.impl.cookie.DateParseException; import org.apache.http.impl.cookie.DateParseException;
import org.apache.http.impl.cookie.DateUtils; import org.apache.http.impl.cookie.DateUtils;
import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HTTP;
import com.android.volley.Cache; import java.util.Map;
import com.android.volley.NetworkResponse;
/** /**
* Utility methods for parsing HTTP headers. * Utility methods for parsing HTTP headers.

@ -16,13 +16,13 @@
package com.android.volley.toolbox; package com.android.volley.toolbox;
import java.io.IOException; import com.android.volley.AuthFailureError;
import java.util.Map; import com.android.volley.Request;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import com.android.volley.AuthFailureError; import java.io.IOException;
import com.android.volley.Request; import java.util.Map;
/** /**
* An HTTP stack abstraction. * An HTTP stack abstraction.

@ -16,6 +16,20 @@
package com.android.volley.toolbox; package com.android.volley.toolbox;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.Request.Method;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.StatusLine;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicStatusLine;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -29,20 +43,6 @@ import java.util.Map.Entry;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.StatusLine;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicStatusLine;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.Request.Method;
/** /**
* An {@link HttpStack} based on {@link HttpURLConnection}. * An {@link HttpStack} based on {@link HttpURLConnection}.
*/ */
@ -213,6 +213,19 @@ public class HurlStack implements HttpStack {
connection.setRequestMethod("PUT"); connection.setRequestMethod("PUT");
addBodyIfExists(connection, request); addBodyIfExists(connection, request);
break; break;
case Method.HEAD:
connection.setRequestMethod("HEAD");
break;
case Method.OPTIONS:
connection.setRequestMethod("OPTIONS");
break;
case Method.TRACE:
connection.setRequestMethod("TRACE");
break;
case Method.PATCH:
addBodyIfExists(connection, request);
connection.setRequestMethod("PATCH");
break;
default: default:
throw new IllegalStateException("Unknown method type."); throw new IllegalStateException("Unknown method type.");
} }

@ -15,9 +15,6 @@
*/ */
package com.android.volley.toolbox; package com.android.volley.toolbox;
import java.util.HashMap;
import java.util.LinkedList;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Bitmap.Config; import android.graphics.Bitmap.Config;
import android.os.Handler; import android.os.Handler;
@ -29,6 +26,10 @@ import com.android.volley.RequestQueue;
import com.android.volley.Response.ErrorListener; import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener; import com.android.volley.Response.Listener;
import com.android.volley.VolleyError; import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageRequest;
import java.util.HashMap;
import java.util.LinkedList;
/** /**
* Helper that handles loading and caching images from remote URLs. * Helper that handles loading and caching images from remote URLs.
@ -274,10 +275,10 @@ public class ImageLoader {
// Remove this request from the list of in-flight requests. // Remove this request from the list of in-flight requests.
BatchedImageRequest request = mInFlightRequests.remove(cacheKey); BatchedImageRequest request = mInFlightRequests.remove(cacheKey);
// Set the error for this request
request.setError(error);
if (request != null) { if (request != null) {
// Set the error for this request
request.setError(error);
// Send the batched response // Send the batched response
batchResponse(cacheKey, request); batchResponse(cacheKey, request);
} }

@ -16,10 +16,6 @@
package com.android.volley.toolbox; package com.android.volley.toolbox;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import com.android.volley.DefaultRetryPolicy; import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse; import com.android.volley.NetworkResponse;
import com.android.volley.ParseError; import com.android.volley.ParseError;
@ -27,6 +23,10 @@ import com.android.volley.Request;
import com.android.volley.Response; import com.android.volley.Response;
import com.android.volley.VolleyLog; import com.android.volley.VolleyLog;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
/** /**
* A canned request for getting an image at a given URL and calling * A canned request for getting an image at a given URL and calling
* back with a decoded Bitmap. * back with a decoded Bitmap.

@ -16,17 +16,17 @@
package com.android.volley.toolbox; package com.android.volley.toolbox;
import java.io.UnsupportedEncodingException;
import org.json.JSONArray;
import org.json.JSONException;
import com.android.volley.NetworkResponse; import com.android.volley.NetworkResponse;
import com.android.volley.ParseError; import com.android.volley.ParseError;
import com.android.volley.Response; import com.android.volley.Response;
import com.android.volley.Response.ErrorListener; import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener; import com.android.volley.Response.Listener;
import org.json.JSONArray;
import org.json.JSONException;
import java.io.UnsupportedEncodingException;
/** /**
* A request for retrieving a {@link JSONArray} response body at a given URL. * A request for retrieving a {@link JSONArray} response body at a given URL.
*/ */

@ -16,17 +16,17 @@
package com.android.volley.toolbox; package com.android.volley.toolbox;
import java.io.UnsupportedEncodingException;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.volley.NetworkResponse; import com.android.volley.NetworkResponse;
import com.android.volley.ParseError; import com.android.volley.ParseError;
import com.android.volley.Response; import com.android.volley.Response;
import com.android.volley.Response.ErrorListener; import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener; import com.android.volley.Response.Listener;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
/** /**
* A request for retrieving a {@link JSONObject} response body at a given URL, allowing for an * A request for retrieving a {@link JSONObject} response body at a given URL, allowing for an
* optional {@link JSONObject} to be passed in as part of the request body. * optional {@link JSONObject} to be passed in as part of the request body.

@ -16,8 +16,6 @@
package com.android.volley.toolbox; package com.android.volley.toolbox;
import java.io.UnsupportedEncodingException;
import com.android.volley.NetworkResponse; import com.android.volley.NetworkResponse;
import com.android.volley.Request; import com.android.volley.Request;
import com.android.volley.Response; import com.android.volley.Response;
@ -25,6 +23,8 @@ import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener; import com.android.volley.Response.Listener;
import com.android.volley.VolleyLog; import com.android.volley.VolleyLog;
import java.io.UnsupportedEncodingException;
/** /**
* A request for retrieving a T type response body at a given URL that also * A request for retrieving a T type response body at a given URL that also
* optionally sends along a JSON body in the request specified. * optionally sends along a JSON body in the request specified.

@ -48,14 +48,7 @@ public class NetworkImageView extends ImageView {
/** Current ImageContainer. (either in-flight or finished) */ /** Current ImageContainer. (either in-flight or finished) */
private ImageContainer mImageContainer; private ImageContainer mImageContainer;
/**
* Max amount to scale the image inside the view
*/
protected float mMaxScale = 1;
private int mFadeTime = -1;
public NetworkImageView(Context context) { public NetworkImageView(Context context) {
this(context, null); this(context, null);
} }
@ -67,23 +60,7 @@ public class NetworkImageView extends ImageView {
public NetworkImageView(Context context, AttributeSet attrs, int defStyle) { public NetworkImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
} }
/**
* How larger the inner bitmap is to the view size.
* @param amount
*/
public void setMaxScale(float amount) {
mMaxScale = amount;
}
/**
* Animate the image fading in.
* @param duration of the animation in milliseconds
*/
public void setFadeIn(int time) {
mFadeTime = time;
}
/** /**
* Sets URL of the image that should be loaded into this view. Note that calling this will * 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 * immediately either set the cached image (if available) or the default image specified by
@ -123,15 +100,19 @@ public class NetworkImageView extends ImageView {
* Loads the image for the view if it isn't already loaded. * 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. * @param isInLayoutPass True if this was invoked from a layout pass, false otherwise.
*/ */
private void loadImageIfNecessary(final boolean isInLayoutPass) { void loadImageIfNecessary(final boolean isInLayoutPass) {
int width = getWidth(); int width = getWidth();
int height = getHeight(); int height = getHeight();
boolean isFullyWrapContent = getLayoutParams() != null boolean wrapWidth = false, wrapHeight = false;
&& getLayoutParams().height == LayoutParams.WRAP_CONTENT if (getLayoutParams() != null) {
&& getLayoutParams().width == LayoutParams.WRAP_CONTENT; wrapWidth = getLayoutParams().width == LayoutParams.WRAP_CONTENT;
wrapHeight = getLayoutParams().height == LayoutParams.WRAP_CONTENT;
}
// if the view's bounds aren't known yet, and this is not a wrap-content/wrap-content // if the view's bounds aren't known yet, and this is not a wrap-content/wrap-content
// view, hold off on loading the image. // view, hold off on loading the image.
boolean isFullyWrapContent = wrapWidth && wrapHeight;
if (width == 0 && height == 0 && !isFullyWrapContent) { if (width == 0 && height == 0 && !isFullyWrapContent) {
return; return;
} }
@ -143,7 +124,7 @@ public class NetworkImageView extends ImageView {
mImageContainer.cancelRequest(); mImageContainer.cancelRequest();
mImageContainer = null; mImageContainer = null;
} }
setImageBitmap(null); setDefaultImageOrNull();
return; return;
} }
@ -155,10 +136,14 @@ public class NetworkImageView extends ImageView {
} else { } else {
// if there is a pre-existing request, cancel it if it's fetching a different URL. // if there is a pre-existing request, cancel it if it's fetching a different URL.
mImageContainer.cancelRequest(); mImageContainer.cancelRequest();
setImageBitmap(null); setDefaultImageOrNull();
} }
} }
// Calculate the max image width / height to use while ignoring WRAP_CONTENT dimens.
int maxWidth = wrapWidth ? 0 : width;
int maxHeight = wrapHeight ? 0 : height;
// The pre-existing content of this view didn't match the current URL. Load the new image // The pre-existing content of this view didn't match the current URL. Load the new image
// from the network. // from the network.
ImageContainer newContainer = mImageLoader.get(mUrl, ImageContainer newContainer = mImageLoader.get(mUrl,
@ -168,8 +153,6 @@ public class NetworkImageView extends ImageView {
if (mErrorImageId != 0) { if (mErrorImageId != 0) {
setImageResource(mErrorImageId); setImageResource(mErrorImageId);
} }
NetworkImageView.this.onErrorResponse(error);
} }
@Override @Override
@ -189,25 +172,26 @@ public class NetworkImageView extends ImageView {
} }
if (response.getBitmap() != null) { if (response.getBitmap() != null) {
if (mFadeTime > 0 && !isImmediate) {
setAlpha(0f);
animate().alpha(1).setDuration(mFadeTime);
}
setImageBitmap(response.getBitmap()); setImageBitmap(response.getBitmap());
} else if (mDefaultImageId != 0) { } else if (mDefaultImageId != 0) {
setImageResource(mDefaultImageId); setImageResource(mDefaultImageId);
} }
} }
}, (int)(width * mMaxScale), (int)(height * mMaxScale)); }, maxWidth, maxHeight);
// update the ImageContainer to be the new bitmap container. // update the ImageContainer to be the new bitmap container.
mImageContainer = newContainer; mImageContainer = newContainer;
} }
public void onErrorResponse(VolleyError error) { private void setDefaultImageOrNull() {
if(mDefaultImageId != 0) {
setImageResource(mDefaultImageId);
}
else {
setImageBitmap(null);
}
} }
@Override @Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) { protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom); super.onLayout(changed, left, top, right, bottom);

@ -16,15 +16,15 @@
package com.android.volley.toolbox; package com.android.volley.toolbox;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
/** /**
* A Future that represents a Volley request. * A Future that represents a Volley request.
* *

@ -16,14 +16,14 @@
package com.android.volley.toolbox; package com.android.volley.toolbox;
import java.io.UnsupportedEncodingException;
import com.android.volley.NetworkResponse; import com.android.volley.NetworkResponse;
import com.android.volley.Request; import com.android.volley.Request;
import com.android.volley.Response; import com.android.volley.Response;
import com.android.volley.Response.ErrorListener; import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener; import com.android.volley.Response.Listener;
import java.io.UnsupportedEncodingException;
/** /**
* A canned request for retrieving the response body at a given URL as a String. * A canned request for retrieving the response body at a given URL as a String.
*/ */

@ -16,8 +16,6 @@
package com.android.volley.toolbox; package com.android.volley.toolbox;
import java.io.File;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
@ -27,6 +25,8 @@ import android.os.Build;
import com.android.volley.Network; import com.android.volley.Network;
import com.android.volley.RequestQueue; import com.android.volley.RequestQueue;
import java.io.File;
public class Volley { public class Volley {
/** Default on-disk cache directory. */ /** Default on-disk cache directory. */

@ -6,6 +6,7 @@ import org.floens.chan.core.manager.BoardManager;
import org.floens.chan.core.manager.PinnedManager; import org.floens.chan.core.manager.PinnedManager;
import org.floens.chan.core.manager.PinnedManager.PinListener; import org.floens.chan.core.manager.PinnedManager.PinListener;
import org.floens.chan.core.manager.ReplyManager; import org.floens.chan.core.manager.ReplyManager;
import org.floens.chan.core.net.BitmapLruImageCache;
import org.floens.chan.database.DatabaseManager; import org.floens.chan.database.DatabaseManager;
import org.floens.chan.service.WatchService; import org.floens.chan.service.WatchService;
import org.floens.chan.utils.IconCache; import org.floens.chan.utils.IconCache;
@ -17,7 +18,6 @@ import android.preference.PreferenceManager;
import android.view.ViewConfiguration; import android.view.ViewConfiguration;
import com.android.volley.RequestQueue; import com.android.volley.RequestQueue;
import com.android.volley.extra.BitmapLruImageCache;
import com.android.volley.toolbox.ImageLoader; import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley; import com.android.volley.toolbox.Volley;

@ -1,4 +1,4 @@
package com.android.volley.extra; package org.floens.chan.core.net;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.util.LruCache; import android.util.LruCache;
@ -9,12 +9,12 @@ public class BitmapLruImageCache extends LruCache<String, Bitmap> implements Ima
public BitmapLruImageCache(int maxSize) { public BitmapLruImageCache(int maxSize) {
super(maxSize); super(maxSize);
} }
@Override @Override
protected int sizeOf(String key, Bitmap value) { protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight(); return value.getRowBytes() * value.getHeight();
} }
@Override @Override
public Bitmap getBitmap(String url) { public Bitmap getBitmap(String url) {
return get(url); return get(url);

@ -9,7 +9,6 @@ import android.util.JsonReader;
import com.android.volley.Response.ErrorListener; import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener; import com.android.volley.Response.Listener;
import com.android.volley.extra.JsonReaderRequest;
public class BoardsRequest extends JsonReaderRequest<ArrayList<Board>> { public class BoardsRequest extends JsonReaderRequest<ArrayList<Board>> {
public BoardsRequest(String url, Listener<ArrayList<Board>> listener, ErrorListener errorListener) { public BoardsRequest(String url, Listener<ArrayList<Board>> listener, ErrorListener errorListener) {

@ -14,7 +14,6 @@ import android.util.JsonReader;
import com.android.volley.ParseError; import com.android.volley.ParseError;
import com.android.volley.Response.ErrorListener; import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener; import com.android.volley.Response.Listener;
import com.android.volley.extra.JsonReaderRequest;
public class ChanReaderRequest extends JsonReaderRequest<List<Post>> { public class ChanReaderRequest extends JsonReaderRequest<List<Post>> {
private Loadable loadable; private Loadable loadable;

@ -1,4 +1,4 @@
package com.android.volley.extra; package org.floens.chan.core.net;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
@ -19,41 +19,41 @@ import com.android.volley.toolbox.HttpHeaderParser;
public abstract class JsonReaderRequest<T> extends Request<T> { public abstract class JsonReaderRequest<T> extends Request<T> {
protected final Listener<T> listener; protected final Listener<T> listener;
private VolleyError error; private VolleyError error;
public JsonReaderRequest(String url, Listener<T> listener, ErrorListener errorListener) { public JsonReaderRequest(String url, Listener<T> listener, ErrorListener errorListener) {
super(Method.GET, url, errorListener); super(Method.GET, url, errorListener);
this.listener = listener; this.listener = listener;
} }
@Override @Override
protected void deliverResponse(T response) { protected void deliverResponse(T response) {
listener.onResponse(response); listener.onResponse(response);
} }
public void setError(VolleyError error) { public void setError(VolleyError error) {
this.error = error; this.error = error;
} }
@Override @Override
protected Response<T> parseNetworkResponse(NetworkResponse response) { protected Response<T> parseNetworkResponse(NetworkResponse response) {
try { try {
ByteArrayInputStream baos = new ByteArrayInputStream(response.data); ByteArrayInputStream baos = new ByteArrayInputStream(response.data);
JsonReader reader = new JsonReader(new InputStreamReader(baos, "UTF-8")); JsonReader reader = new JsonReader(new InputStreamReader(baos, "UTF-8"));
// long start = System.currentTimeMillis(); // long start = System.currentTimeMillis();
T read = readJson(reader); T read = readJson(reader);
try { try {
reader.close(); reader.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
// Log.e("Chan", "Total time: " + (System.currentTimeMillis() - start)); // Log.e("Chan", "Total time: " + (System.currentTimeMillis() - start));
if (read == null) { if (read == null) {
return Response.error(new VolleyError()); return Response.error(new VolleyError());
} else if (error != null) { } else if (error != null) {
@ -65,7 +65,7 @@ public abstract class JsonReaderRequest<T> extends Request<T> {
return Response.error(new ParseError(e)); return Response.error(new ParseError(e));
} }
} }
public abstract T readJson(JsonReader reader); public abstract T readJson(JsonReader reader);
} }

@ -0,0 +1,277 @@
/**
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.floens.chan.ui.view;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageLoader.ImageContainer;
import com.android.volley.toolbox.ImageLoader.ImageListener;
/**
* Custom version of NetworkImageView
*
* Handles fetching an image from a URL as well as the life-cycle of the
* associated request.
*/
public class CustomNetworkImageView extends ImageView {
/** 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 ImageContainer mImageContainer;
/**
* Max amount to scale the image inside the view
*/
private float mMaxScale = 1;
private int mFadeTime;
public CustomNetworkImageView(Context context) {
this(context, null);
}
public CustomNetworkImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomNetworkImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* How larger the inner bitmap is to the defined view size.
*
* @param amount
*/
public void setMaxScale(float amount) {
mMaxScale = amount;
}
public float getMaxScale() {
return mMaxScale;
}
/**
* Animate the image fading in.
*
* @param duration
* duration of the fade animation in milliseconds
*/
public void setFadeIn(int time) {
mFadeTime = time;
}
/**
* 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 CustomNetworkImageView#setDefaultImageResId(int)} on the view.
*
* NOTE: If applicable,
* {@link CustomNetworkImageView#setDefaultImageResId(int)} and
* {@link CustomNetworkImageView#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.
*/
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);
}
/**
* 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.
*/
public void setErrorImageResId(int errorImage) {
mErrorImageId = errorImage;
}
public void onErrorResponse(VolleyError error) {
}
/**
* 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) {
int width = getWidth();
int height = getHeight();
boolean wrapWidth = false, wrapHeight = false;
if (getLayoutParams() != null) {
wrapWidth = getLayoutParams().width == LayoutParams.WRAP_CONTENT;
wrapHeight = getLayoutParams().height == LayoutParams.WRAP_CONTENT;
}
// if the view's bounds aren't known yet, and this is not a
// wrap-content/wrap-content
// view, hold off on loading the image.
boolean isFullyWrapContent = wrapWidth && wrapHeight;
if (width == 0 && height == 0 && !isFullyWrapContent) {
return;
}
// 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;
}
setDefaultImageOrNull();
return;
}
// 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();
}
}
// Calculate the max image width / height to use while ignoring
// WRAP_CONTENT dimens.
int maxWidth = wrapWidth ? 0 : width;
int maxHeight = wrapHeight ? 0 : height;
// The pre-existing content of this view didn't match the current URL.
// Load the new image
// from the network.
ImageContainer newContainer = mImageLoader.get(mUrl, new ImageListener() {
@Override
public void onErrorResponse(VolleyError error) {
if (mErrorImageId != 0) {
setImageResource(mErrorImageId);
}
CustomNetworkImageView.this.onErrorResponse(error);
}
@Override
public void onResponse(final 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) {
post(new Runnable() {
@Override
public void run() {
onResponse(response, false);
}
});
return;
}
if (response.getBitmap() != null) {
setImageBitmap(response.getBitmap());
if (mFadeTime > 0 && !isImmediate) {
setAlpha(0f);
animate().alpha(1f).setDuration(mFadeTime);
}
} else if (mDefaultImageId != 0) {
setImageResource(mDefaultImageId);
}
}
}, (int)(maxWidth * mMaxScale), (int)(maxHeight * mMaxScale));
// update the ImageContainer to be the new bitmap container.
mImageContainer = newContainer;
}
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) {
super.onLayout(changed, left, top, right, bottom);
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;
}
super.onDetachedFromWindow();
}
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
invalidate();
}
}

@ -10,62 +10,61 @@ import android.graphics.drawable.Drawable;
import android.widget.Toast; import android.widget.Toast;
import com.android.volley.VolleyError; import com.android.volley.VolleyError;
import com.android.volley.toolbox.NetworkImageView;
/** /**
* Extends NetworkImageView. * Extends NetworkImageView.
* Attaches a PhotoViewAttacher when setBitmap is called. * Attaches a PhotoViewAttacher when setBitmap is called.
* Sets the progressBar to false when a bitmap gets set. * Sets the progressBar to false when a bitmap gets set.
*/ */
public class NetworkPhotoView extends NetworkImageView { public class NetworkPhotoView extends CustomNetworkImageView {
private PhotoViewAttacher attacher; private PhotoViewAttacher attacher;
private OnLongClickListener longClickListener; private OnLongClickListener longClickListener;
private OnViewTapListener viewTapListener; private OnViewTapListener viewTapListener;
private ImageViewFragment fragment; private ImageViewFragment fragment;
public NetworkPhotoView(Context context) { public NetworkPhotoView(Context context) {
super(context); super(context);
} }
public void setImageViewFragment(ImageViewFragment fragment) { public void setImageViewFragment(ImageViewFragment fragment) {
this.fragment = fragment; this.fragment = fragment;
} }
public void setOnLongClickListenerToAttacher(OnLongClickListener listener) { public void setOnLongClickListenerToAttacher(OnLongClickListener listener) {
longClickListener = listener; longClickListener = listener;
} }
public void setOnViewTapListenerToAttacher(OnViewTapListener listener) { public void setOnViewTapListenerToAttacher(OnViewTapListener listener) {
viewTapListener = listener; viewTapListener = listener;
} }
@Override @Override
public void setImageDrawable(Drawable drawable) { public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable); super.setImageDrawable(drawable);
attacher = new PhotoViewAttacher(this); attacher = new PhotoViewAttacher(this);
attacher.setMaximumScale(mMaxScale); attacher.setMaximumScale(getMaxScale());
attacher.setOnLongClickListener(longClickListener); attacher.setOnLongClickListener(longClickListener);
attacher.setOnViewTapListener(viewTapListener); attacher.setOnViewTapListener(viewTapListener);
fragment.showProgressBar(false); fragment.showProgressBar(false);
} }
@Override @Override
public void onErrorResponse(VolleyError error) { public void onErrorResponse(VolleyError error) {
super.onErrorResponse(error); super.onErrorResponse(error);
// TODO: out of memory. We need a new image viewer for *large* images. Maybe copy the one from the gallery. // TODO: out of memory. We need a new image viewer for *large* images. Maybe copy the one from the gallery.
System.gc(); System.gc();
Toast.makeText(getContext(), R.string.image_preview_failed, Toast.LENGTH_LONG).show(); Toast.makeText(getContext(), R.string.image_preview_failed, Toast.LENGTH_LONG).show();
fragment.showProgressBar(false); fragment.showProgressBar(false);
} }
@Override @Override
protected void onDetachedFromWindow() { protected void onDetachedFromWindow() {
super.onDetachedFromWindow(); super.onDetachedFromWindow();
if (attacher != null) { if (attacher != null) {
attacher.cleanup(); attacher.cleanup();
} }

@ -46,7 +46,7 @@ public class PostView extends LinearLayout implements View.OnClickListener, View
private boolean isBuild = false; private boolean isBuild = false;
private LinearLayout full; private LinearLayout full;
private LinearLayout right; private LinearLayout right;
private NetworkImageView imageView; private CustomNetworkImageView imageView;
private TextView titleView; private TextView titleView;
private TextView commentView; private TextView commentView;
private TextView repliesCountView; private TextView repliesCountView;
@ -234,7 +234,7 @@ public class PostView extends LinearLayout implements View.OnClickListener, View
full.setOrientation(HORIZONTAL); full.setOrientation(HORIZONTAL);
// Create thumbnail // Create thumbnail
imageView = new NetworkImageView(context); imageView = new CustomNetworkImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setFadeIn(100); imageView.setFadeIn(100);

Loading…
Cancel
Save