mirror of
https://github.com/nextcloud/android.git
synced 2024-11-28 02:17:43 +03:00
Creation of ThumbnailsCacheManager class, grouping all the methods needed to access the thumbnails cache
This commit is contained in:
parent
778ed30b58
commit
395ad3248e
4 changed files with 397 additions and 282 deletions
262
src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
Normal file
262
src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
Normal file
|
@ -0,0 +1,262 @@
|
|||
/* ownCloud Android client application
|
||||
* Copyright (C) 2012-2014 ownCloud Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.owncloud.android.datamodel;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Bitmap.CompressFormat;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.ThumbnailUtils;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.TypedValue;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.owncloud.android.MainApp;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.ui.adapter.DiskLruImageCache;
|
||||
import com.owncloud.android.utils.BitmapUtils;
|
||||
import com.owncloud.android.utils.DisplayUtils;
|
||||
|
||||
/**
|
||||
* Manager for concurrent access to thumbnails cache.
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* @author David A. Velasco
|
||||
*/
|
||||
public class ThumbnailsCacheManager {
|
||||
|
||||
private static final String TAG = ThumbnailsCacheManager.class.getSimpleName();
|
||||
|
||||
private static final String CACHE_FOLDER = "thumbnailCache";
|
||||
|
||||
private static final Object mThumbnailsDiskCacheLock = new Object();
|
||||
private static DiskLruImageCache mThumbnailCache;
|
||||
private static boolean mThumbnailCacheStarting = true;
|
||||
|
||||
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
|
||||
private static final CompressFormat mCompressFormat = CompressFormat.JPEG;
|
||||
private static final int mCompressQuality = 70;
|
||||
|
||||
public static Bitmap mDefaultImg =
|
||||
BitmapFactory.decodeResource(
|
||||
MainApp.getAppContext().getResources(),
|
||||
DisplayUtils.getResourceId("image/png", "default.png")
|
||||
);
|
||||
|
||||
|
||||
public static class InitDiskCacheTask extends AsyncTask<File, Void, Void> {
|
||||
@Override
|
||||
protected Void doInBackground(File... params) {
|
||||
synchronized (mThumbnailsDiskCacheLock) {
|
||||
try {
|
||||
// Check if media is mounted or storage is built-in, if so,
|
||||
// try and use external cache dir; otherwise use internal cache dir
|
||||
final String cachePath =
|
||||
MainApp.getAppContext().getExternalCacheDir().getPath() +
|
||||
File.separator + CACHE_FOLDER;
|
||||
Log_OC.d(TAG, "create dir: " + cachePath);
|
||||
final File diskCacheDir = new File(cachePath);
|
||||
mThumbnailCache = new DiskLruImageCache(
|
||||
diskCacheDir,
|
||||
DISK_CACHE_SIZE,
|
||||
mCompressFormat,
|
||||
mCompressQuality
|
||||
);
|
||||
} catch (Exception e) {
|
||||
Log_OC.d(TAG, "Thumbnail cache could not be opened ", e);
|
||||
mThumbnailCache = null;
|
||||
}
|
||||
mThumbnailCacheStarting = false; // Finished initialization
|
||||
mThumbnailsDiskCacheLock.notifyAll(); // Wake any waiting threads
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void addBitmapToCache(String key, Bitmap bitmap) {
|
||||
synchronized (mThumbnailsDiskCacheLock) {
|
||||
if (mThumbnailCache != null) {
|
||||
mThumbnailCache.put(key, bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Bitmap getBitmapFromDiskCache(String key) {
|
||||
synchronized (mThumbnailsDiskCacheLock) {
|
||||
// Wait while disk cache is started from background thread
|
||||
while (mThumbnailCacheStarting) {
|
||||
try {
|
||||
mThumbnailsDiskCacheLock.wait();
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
if (mThumbnailCache != null) {
|
||||
return (Bitmap) mThumbnailCache.getBitmap(key);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static boolean cancelPotentialWork(OCFile file, ImageView imageView) {
|
||||
final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
|
||||
|
||||
if (bitmapWorkerTask != null) {
|
||||
final OCFile bitmapData = bitmapWorkerTask.mFile;
|
||||
// If bitmapData is not yet set or it differs from the new data
|
||||
if (bitmapData == null || bitmapData != file) {
|
||||
// Cancel previous task
|
||||
bitmapWorkerTask.cancel(true);
|
||||
} else {
|
||||
// The same work is already in progress
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// No task associated with the ImageView, or an existing task was cancelled
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {
|
||||
if (imageView != null) {
|
||||
final Drawable drawable = imageView.getDrawable();
|
||||
if (drawable instanceof AsyncDrawable) {
|
||||
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
|
||||
return asyncDrawable.getBitmapWorkerTask();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class ThumbnailGenerationTask extends AsyncTask<OCFile, Void, Bitmap> {
|
||||
private final WeakReference<ImageView> mImageViewReference;
|
||||
private OCFile mFile;
|
||||
private FileDataStorageManager mStorageManager;
|
||||
|
||||
public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager) {
|
||||
// Use a WeakReference to ensure the ImageView can be garbage collected
|
||||
mImageViewReference = new WeakReference<ImageView>(imageView);
|
||||
if (storageManager == null)
|
||||
throw new IllegalArgumentException("storageManager must not be NULL");
|
||||
mStorageManager = storageManager;
|
||||
}
|
||||
|
||||
// Decode image in background.
|
||||
@Override
|
||||
protected Bitmap doInBackground(OCFile... params) {
|
||||
Bitmap thumbnail = null;
|
||||
|
||||
try {
|
||||
mFile = params[0];
|
||||
final String imageKey = String.valueOf(mFile.getRemoteId());
|
||||
|
||||
// Check disk cache in background thread
|
||||
thumbnail = getBitmapFromDiskCache(imageKey);
|
||||
|
||||
// Not found in disk cache
|
||||
if (thumbnail == null || mFile.needsUpdateThumbnail()) {
|
||||
// Converts dp to pixel
|
||||
Resources r = MainApp.getAppContext().getResources();
|
||||
int px = (int) Math.round(TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, 150, r.getDisplayMetrics()
|
||||
));
|
||||
|
||||
if (mFile.isDown()){
|
||||
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
|
||||
mFile.getStoragePath(), px, px);
|
||||
|
||||
if (bitmap != null) {
|
||||
thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
|
||||
|
||||
// Add thumbnail to cache
|
||||
addBitmapToCache(imageKey, thumbnail);
|
||||
|
||||
mFile.setNeedsUpdateThumbnail(false);
|
||||
mStorageManager.saveFile(mFile);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Throwable t) {
|
||||
// the app should never break due to a problem with thumbnails
|
||||
Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t);
|
||||
if (t instanceof OutOfMemoryError) {
|
||||
System.gc();
|
||||
}
|
||||
}
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
protected void onPostExecute(Bitmap bitmap){
|
||||
if (isCancelled()) {
|
||||
bitmap = null;
|
||||
}
|
||||
|
||||
if (mImageViewReference != null && bitmap != null) {
|
||||
final ImageView imageView = mImageViewReference.get();
|
||||
final ThumbnailGenerationTask bitmapWorkerTask =
|
||||
getBitmapWorkerTask(imageView);
|
||||
if (this == bitmapWorkerTask && imageView != null) {
|
||||
if (imageView.getTag().equals(mFile.getFileId())) {
|
||||
imageView.setImageBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class AsyncDrawable extends BitmapDrawable {
|
||||
private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;
|
||||
|
||||
public AsyncDrawable(
|
||||
Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask
|
||||
) {
|
||||
|
||||
super(res, bitmap);
|
||||
bitmapWorkerTaskReference =
|
||||
new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);
|
||||
}
|
||||
|
||||
public ThumbnailGenerationTask getBitmapWorkerTask() {
|
||||
return bitmapWorkerTaskReference.get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove from cache the remoteId passed
|
||||
* @param fileRemoteId: remote id of mFile passed
|
||||
*/
|
||||
public static void removeFileFromCache(String fileRemoteId){
|
||||
synchronized (mThumbnailsDiskCacheLock) {
|
||||
if (mThumbnailCache != null) {
|
||||
mThumbnailCache.removeKey(fileRemoteId);
|
||||
}
|
||||
mThumbnailsDiskCacheLock.notifyAll(); // Wake any waiting threads
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -22,13 +22,11 @@ import java.util.ArrayList;
|
|||
import java.util.HashMap;
|
||||
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.datamodel.ThumbnailsCacheManager;
|
||||
import com.owncloud.android.db.ProviderMeta;
|
||||
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.lib.resources.shares.ShareType;
|
||||
import com.owncloud.android.ui.adapter.DiskLruImageCache;
|
||||
|
||||
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentProviderOperation;
|
||||
|
@ -43,7 +41,6 @@ import android.database.SQLException;
|
|||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.database.sqlite.SQLiteQueryBuilder;
|
||||
import android.graphics.Bitmap.CompressFormat;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
|
@ -57,12 +54,6 @@ import android.text.TextUtils;
|
|||
public class FileContentProvider extends ContentProvider {
|
||||
|
||||
private DataBaseHelper mDbHelper;
|
||||
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
|
||||
private static final CompressFormat mCompressFormat = CompressFormat.JPEG;
|
||||
private static final int mCompressQuality = 70;
|
||||
|
||||
private final Object thumbnailDiskCacheLock = new Object();
|
||||
private DiskLruImageCache mThumbnailCache;
|
||||
|
||||
// Projection for filelist table
|
||||
private static HashMap<String, String> mFileProjectionMap;
|
||||
|
@ -177,7 +168,7 @@ public class FileContentProvider extends ContentProvider {
|
|||
String remoteId = "";
|
||||
if (c != null && c.moveToFirst()) {
|
||||
remoteId = c.getString(c.getColumnIndex(ProviderTableMeta.FILE_REMOTE_ID));
|
||||
removeFileFromCache(remoteId);
|
||||
ThumbnailsCacheManager.removeFileFromCache(remoteId);
|
||||
}
|
||||
Log_OC.d(TAG, "Removing FILE " + remoteId);
|
||||
|
||||
|
@ -210,12 +201,24 @@ public class FileContentProvider extends ContentProvider {
|
|||
//String remotePath;
|
||||
while (!children.isAfterLast()) {
|
||||
childId = children.getLong(children.getColumnIndex(ProviderTableMeta._ID));
|
||||
isDir = "DIR".equals(children.getString(children.getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
|
||||
isDir = "DIR".equals(children.getString(
|
||||
children.getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)
|
||||
));
|
||||
//remotePath = children.getString(children.getColumnIndex(ProviderTableMeta.FILE_PATH));
|
||||
if (isDir) {
|
||||
count += delete(db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, childId), null, null);
|
||||
count += delete(
|
||||
db,
|
||||
ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, childId),
|
||||
null,
|
||||
null
|
||||
);
|
||||
} else {
|
||||
count += delete(db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, childId), null, null);
|
||||
count += delete(
|
||||
db,
|
||||
ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, childId),
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
children.moveToNext();
|
||||
}
|
||||
|
@ -250,29 +253,6 @@ public class FileContentProvider extends ContentProvider {
|
|||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove from cache the remoteId passed
|
||||
* @param fileRemoteId: remote id of file passed
|
||||
*/
|
||||
private void removeFileFromCache(String fileRemoteId){
|
||||
Context context = getContext();
|
||||
if (context != null) {
|
||||
synchronized (thumbnailDiskCacheLock) {
|
||||
try {
|
||||
mThumbnailCache = new DiskLruImageCache(context, "thumbnailCache",
|
||||
DISK_CACHE_SIZE, mCompressFormat, mCompressQuality);
|
||||
|
||||
mThumbnailCache.removeKey(fileRemoteId);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log_OC.d(TAG, "Thumbnail cache could not be opened ", e);
|
||||
mThumbnailCache = null;
|
||||
}
|
||||
thumbnailDiskCacheLock.notifyAll(); // Wake any waiting threads
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType(Uri uri) {
|
||||
switch (mUriMatcher.match(uri)) {
|
||||
|
@ -288,7 +268,6 @@ public class FileContentProvider extends ContentProvider {
|
|||
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues values) {
|
||||
//Log_OC.d(TAG, "Inserting " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
|
||||
Uri newUri = null;
|
||||
SQLiteDatabase db = mDbHelper.getWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
@ -308,23 +287,31 @@ public class FileContentProvider extends ContentProvider {
|
|||
case SINGLE_FILE:
|
||||
String remotePath = values.getAsString(ProviderTableMeta.FILE_PATH);
|
||||
String accountName = values.getAsString(ProviderTableMeta.FILE_ACCOUNT_OWNER);
|
||||
String[] projection = new String[] {ProviderTableMeta._ID, ProviderTableMeta.FILE_PATH, ProviderTableMeta.FILE_ACCOUNT_OWNER };
|
||||
String where = ProviderTableMeta.FILE_PATH + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
|
||||
String[] projection = new String[] {
|
||||
ProviderTableMeta._ID, ProviderTableMeta.FILE_PATH,
|
||||
ProviderTableMeta.FILE_ACCOUNT_OWNER
|
||||
};
|
||||
String where = ProviderTableMeta.FILE_PATH + "=? AND " +
|
||||
ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
|
||||
String[] whereArgs = new String[] {remotePath, accountName};
|
||||
Cursor doubleCheck = query(db, uri, projection, where, whereArgs, null);
|
||||
if (doubleCheck == null || !doubleCheck.moveToFirst()) { // ugly patch; serious refactorization is needed to reduce work in FileDataStorageManager and bring it to FileContentProvider
|
||||
// ugly patch; serious refactorization is needed to reduce work in
|
||||
// FileDataStorageManager and bring it to FileContentProvider
|
||||
if (doubleCheck == null || !doubleCheck.moveToFirst()) {
|
||||
long rowId = db.insert(ProviderTableMeta.FILE_TABLE_NAME, null, values);
|
||||
if (rowId > 0) {
|
||||
Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId);
|
||||
//Log_OC.d(TAG, "Inserted " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
|
||||
Uri insertedFileUri =
|
||||
ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId);
|
||||
return insertedFileUri;
|
||||
} else {
|
||||
//Log_OC.d(TAG, "Error while inserting " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
|
||||
throw new SQLException("ERROR " + uri);
|
||||
}
|
||||
} else {
|
||||
// file is already inserted; race condition, let's avoid a duplicated entry
|
||||
Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, doubleCheck.getLong(doubleCheck.getColumnIndex(ProviderTableMeta._ID)));
|
||||
Uri insertedFileUri = ContentUris.withAppendedId(
|
||||
ProviderTableMeta.CONTENT_URI_FILE,
|
||||
doubleCheck.getLong(doubleCheck.getColumnIndex(ProviderTableMeta._ID))
|
||||
);
|
||||
doubleCheck.close();
|
||||
|
||||
return insertedFileUri;
|
||||
|
@ -333,22 +320,35 @@ public class FileContentProvider extends ContentProvider {
|
|||
case SHARES:
|
||||
String path = values.getAsString(ProviderTableMeta.OCSHARES_PATH);
|
||||
String accountNameShare= values.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER);
|
||||
String[] projectionShare = new String[] {ProviderTableMeta._ID, ProviderTableMeta.OCSHARES_PATH, ProviderTableMeta.OCSHARES_ACCOUNT_OWNER };
|
||||
String whereShare = ProviderTableMeta.OCSHARES_PATH + "=? AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
|
||||
String[] projectionShare = new String[] {
|
||||
ProviderTableMeta._ID, ProviderTableMeta.OCSHARES_PATH,
|
||||
ProviderTableMeta.OCSHARES_ACCOUNT_OWNER
|
||||
};
|
||||
String whereShare = ProviderTableMeta.OCSHARES_PATH + "=? AND " +
|
||||
ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
|
||||
String[] whereArgsShare = new String[] {path, accountNameShare};
|
||||
Uri insertedShareUri = null;
|
||||
Cursor doubleCheckShare = query(db, uri, projectionShare, whereShare, whereArgsShare, null);
|
||||
if (doubleCheckShare == null || !doubleCheckShare.moveToFirst()) { // ugly patch; serious refactorization is needed to reduce work in FileDataStorageManager and bring it to FileContentProvider
|
||||
Cursor doubleCheckShare =
|
||||
query(db, uri, projectionShare, whereShare, whereArgsShare, null);
|
||||
// ugly patch; serious refactorization is needed to reduce work in
|
||||
// FileDataStorageManager and bring it to FileContentProvider
|
||||
if (doubleCheckShare == null || !doubleCheckShare.moveToFirst()) {
|
||||
long rowId = db.insert(ProviderTableMeta.OCSHARES_TABLE_NAME, null, values);
|
||||
if (rowId >0) {
|
||||
insertedShareUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, rowId);
|
||||
insertedShareUri =
|
||||
ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, rowId);
|
||||
} else {
|
||||
throw new SQLException("ERROR " + uri);
|
||||
|
||||
}
|
||||
} else {
|
||||
// file is already inserted; race condition, let's avoid a duplicated entry
|
||||
insertedShareUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, doubleCheckShare.getLong(doubleCheckShare.getColumnIndex(ProviderTableMeta._ID)));
|
||||
insertedShareUri = ContentUris.withAppendedId(
|
||||
ProviderTableMeta.CONTENT_URI_SHARE,
|
||||
doubleCheckShare.getLong(
|
||||
doubleCheckShare.getColumnIndex(ProviderTableMeta._ID)
|
||||
)
|
||||
);
|
||||
doubleCheckShare.close();
|
||||
}
|
||||
updateFilesTableAccordingToShareInsertion(db, uri, values);
|
||||
|
@ -361,11 +361,17 @@ public class FileContentProvider extends ContentProvider {
|
|||
|
||||
}
|
||||
|
||||
private void updateFilesTableAccordingToShareInsertion(SQLiteDatabase db, Uri uri, ContentValues shareValues) {
|
||||
private void updateFilesTableAccordingToShareInsertion(
|
||||
SQLiteDatabase db, Uri uri, ContentValues shareValues
|
||||
) {
|
||||
ContentValues fileValues = new ContentValues();
|
||||
fileValues.put(ProviderTableMeta.FILE_SHARE_BY_LINK,
|
||||
ShareType.PUBLIC_LINK.getValue() == shareValues.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE)? 1 : 0);
|
||||
String whereShare = ProviderTableMeta.FILE_PATH + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
|
||||
fileValues.put(
|
||||
ProviderTableMeta.FILE_SHARE_BY_LINK,
|
||||
ShareType.PUBLIC_LINK.getValue() ==
|
||||
shareValues.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE)? 1 : 0
|
||||
);
|
||||
String whereShare = ProviderTableMeta.FILE_PATH + "=? AND " +
|
||||
ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
|
||||
String[] whereArgsShare = new String[] {
|
||||
shareValues.getAsString(ProviderTableMeta.OCSHARES_PATH),
|
||||
shareValues.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER)
|
||||
|
@ -393,7 +399,14 @@ public class FileContentProvider extends ContentProvider {
|
|||
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||
public Cursor query(
|
||||
Uri uri,
|
||||
String[] projection,
|
||||
String selection,
|
||||
String[] selectionArgs,
|
||||
String sortOrder
|
||||
) {
|
||||
|
||||
Cursor result = null;
|
||||
SQLiteDatabase db = mDbHelper.getReadableDatabase();
|
||||
db.beginTransaction();
|
||||
|
@ -406,7 +419,15 @@ public class FileContentProvider extends ContentProvider {
|
|||
return result;
|
||||
}
|
||||
|
||||
private Cursor query(SQLiteDatabase db, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||
private Cursor query(
|
||||
SQLiteDatabase db,
|
||||
Uri uri,
|
||||
String[] projection,
|
||||
String selection,
|
||||
String[] selectionArgs,
|
||||
String sortOrder
|
||||
) {
|
||||
|
||||
SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder();
|
||||
|
||||
sqlQuery.setTables(ProviderTableMeta.FILE_TABLE_NAME);
|
||||
|
@ -460,7 +481,6 @@ public class FileContentProvider extends ContentProvider {
|
|||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
|
||||
//Log_OC.d(TAG, "Updating " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
|
||||
int count = 0;
|
||||
SQLiteDatabase db = mDbHelper.getWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
@ -476,14 +496,24 @@ public class FileContentProvider extends ContentProvider {
|
|||
|
||||
|
||||
|
||||
private int update(SQLiteDatabase db, Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
private int update(
|
||||
SQLiteDatabase db,
|
||||
Uri uri,
|
||||
ContentValues values,
|
||||
String selection,
|
||||
String[] selectionArgs
|
||||
) {
|
||||
switch (mUriMatcher.match(uri)) {
|
||||
case DIRECTORY:
|
||||
return 0; //updateFolderSize(db, selectionArgs[0]);
|
||||
case SHARES:
|
||||
return db.update(ProviderTableMeta.OCSHARES_TABLE_NAME, values, selection, selectionArgs);
|
||||
return db.update(
|
||||
ProviderTableMeta.OCSHARES_TABLE_NAME, values, selection, selectionArgs
|
||||
);
|
||||
default:
|
||||
return db.update(ProviderTableMeta.FILE_TABLE_NAME, values, selection, selectionArgs);
|
||||
return db.update(
|
||||
ProviderTableMeta.FILE_TABLE_NAME, values, selection, selectionArgs
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,8 +571,10 @@ public class FileContentProvider extends ContentProvider {
|
|||
*/
|
||||
|
||||
@Override
|
||||
public ContentProviderResult[] applyBatch (ArrayList<ContentProviderOperation> operations) throws OperationApplicationException {
|
||||
Log_OC.d("FileContentProvider", "applying batch in provider " + this + " (temporary: " + isTemporary() + ")" );
|
||||
public ContentProviderResult[] applyBatch (ArrayList<ContentProviderOperation> operations)
|
||||
throws OperationApplicationException {
|
||||
Log_OC.d("FileContentProvider", "applying batch in provider " + this +
|
||||
" (temporary: " + isTemporary() + ")" );
|
||||
ContentProviderResult[] results = new ContentProviderResult[operations.size()];
|
||||
int i=0;
|
||||
|
||||
|
@ -631,12 +663,13 @@ public class FileContentProvider extends ContentProvider {
|
|||
db.beginTransaction();
|
||||
try {
|
||||
db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
|
||||
" ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER " +
|
||||
" DEFAULT 0");
|
||||
" ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA +
|
||||
" INTEGER " + " DEFAULT 0");
|
||||
|
||||
// assume there are not local changes pending to upload
|
||||
db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME +
|
||||
" SET " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " = " + System.currentTimeMillis() +
|
||||
" SET " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " = "
|
||||
+ System.currentTimeMillis() +
|
||||
" WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL");
|
||||
|
||||
upgraded = true;
|
||||
|
@ -650,11 +683,12 @@ public class FileContentProvider extends ContentProvider {
|
|||
db.beginTransaction();
|
||||
try {
|
||||
db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
|
||||
" ADD COLUMN " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER " +
|
||||
" DEFAULT 0");
|
||||
" ADD COLUMN " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA +
|
||||
" INTEGER " + " DEFAULT 0");
|
||||
|
||||
db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME +
|
||||
" SET " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " = " + ProviderTableMeta.FILE_MODIFIED +
|
||||
" SET " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " = " +
|
||||
ProviderTableMeta.FILE_MODIFIED +
|
||||
" WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL");
|
||||
|
||||
upgraded = true;
|
||||
|
@ -664,7 +698,8 @@ public class FileContentProvider extends ContentProvider {
|
|||
}
|
||||
}
|
||||
if (!upgraded)
|
||||
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
|
||||
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
|
||||
", newVersion == " + newVersion);
|
||||
|
||||
if (oldVersion < 5 && newVersion >= 5) {
|
||||
Log_OC.i("SQL", "Entering in the #4 ADD in onUpgrade");
|
||||
|
@ -681,7 +716,8 @@ public class FileContentProvider extends ContentProvider {
|
|||
}
|
||||
}
|
||||
if (!upgraded)
|
||||
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
|
||||
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
|
||||
", newVersion == " + newVersion);
|
||||
|
||||
if (oldVersion < 6 && newVersion >= 6) {
|
||||
Log_OC.i("SQL", "Entering in the #5 ADD in onUpgrade");
|
||||
|
@ -720,7 +756,8 @@ public class FileContentProvider extends ContentProvider {
|
|||
}
|
||||
}
|
||||
if (!upgraded)
|
||||
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
|
||||
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
|
||||
", newVersion == " + newVersion);
|
||||
|
||||
if (oldVersion < 7 && newVersion >= 7) {
|
||||
Log_OC.i("SQL", "Entering in the #7 ADD in onUpgrade");
|
||||
|
@ -741,7 +778,8 @@ public class FileContentProvider extends ContentProvider {
|
|||
}
|
||||
}
|
||||
if (!upgraded)
|
||||
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
|
||||
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
|
||||
", newVersion == " + newVersion);
|
||||
|
||||
if (oldVersion < 8 && newVersion >= 8) {
|
||||
Log_OC.i("SQL", "Entering in the #8 ADD in onUpgrade");
|
||||
|
@ -758,7 +796,8 @@ public class FileContentProvider extends ContentProvider {
|
|||
}
|
||||
}
|
||||
if (!upgraded)
|
||||
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
|
||||
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
|
||||
", newVersion == " + newVersion);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.CompressFormat;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
@ -45,9 +44,11 @@ public class DiskLruImageCache {
|
|||
|
||||
private static final String TAG = DiskLruImageCache.class.getSimpleName();
|
||||
|
||||
public DiskLruImageCache( Context context,String uniqueName, int diskCacheSize,
|
||||
CompressFormat compressFormat, int quality ) throws IOException {
|
||||
final File diskCacheDir = getDiskCacheDir(context, uniqueName );
|
||||
//public DiskLruImageCache( Context context,String uniqueName, int diskCacheSize,
|
||||
public DiskLruImageCache(
|
||||
File diskCacheDir, int diskCacheSize, CompressFormat compressFormat, int quality
|
||||
) throws IOException {
|
||||
|
||||
mDiskCache = DiskLruCache.open(
|
||||
diskCacheDir, CACHE_VERSION, VALUE_COUNT, diskCacheSize
|
||||
);
|
||||
|
@ -68,17 +69,6 @@ public class DiskLruImageCache {
|
|||
}
|
||||
}
|
||||
|
||||
private File getDiskCacheDir(Context context, String uniqueName) {
|
||||
|
||||
// Check if media is mounted or storage is built-in, if so, try and use external cache dir
|
||||
// otherwise use internal cache dir
|
||||
final String cachePath = context.getExternalCacheDir().getPath();
|
||||
|
||||
Log_OC.d(TAG, "create dir: " + cachePath + File.separator + uniqueName);
|
||||
|
||||
return new File(cachePath + File.separator + uniqueName);
|
||||
}
|
||||
|
||||
public void put( String key, Bitmap data ) {
|
||||
|
||||
DiskLruCache.Editor editor = null;
|
||||
|
|
|
@ -17,21 +17,11 @@
|
|||
*/
|
||||
package com.owncloud.android.ui.adapter;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Vector;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.CompressFormat;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.ThumbnailUtils;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -45,11 +35,11 @@ import com.owncloud.android.R;
|
|||
import com.owncloud.android.authentication.AccountUtils;
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager;
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
import com.owncloud.android.datamodel.ThumbnailsCacheManager;
|
||||
import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncDrawable;
|
||||
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
|
||||
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.ui.activity.ComponentsGetter;
|
||||
import com.owncloud.android.utils.BitmapUtils;
|
||||
import com.owncloud.android.utils.DisplayUtils;
|
||||
|
||||
|
||||
|
@ -64,8 +54,6 @@ import com.owncloud.android.utils.DisplayUtils;
|
|||
public class FileListListAdapter extends BaseAdapter implements ListAdapter {
|
||||
private final static String PERMISSION_SHARED_WITH_ME = "S";
|
||||
|
||||
private static final String TAG = FileListListAdapter.class.getSimpleName();
|
||||
|
||||
private Context mContext;
|
||||
private OCFile mFile = null;
|
||||
private Vector<OCFile> mFiles = null;
|
||||
|
@ -75,14 +63,6 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
|
|||
private Account mAccount;
|
||||
private ComponentsGetter mTransferServiceGetter;
|
||||
|
||||
private final Object thumbnailDiskCacheLock = new Object();
|
||||
private DiskLruImageCache mThumbnailCache;
|
||||
private boolean mThumbnailCacheStarting = true;
|
||||
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
|
||||
private static final CompressFormat mCompressFormat = CompressFormat.JPEG;
|
||||
private static final int mCompressQuality = 70;
|
||||
private Bitmap defaultImg;
|
||||
|
||||
public FileListListAdapter(
|
||||
boolean justFolders,
|
||||
Context context,
|
||||
|
@ -93,145 +73,11 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
|
|||
mContext = context;
|
||||
mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);
|
||||
mTransferServiceGetter = transferServiceGetter;
|
||||
defaultImg = BitmapFactory.decodeResource(mContext.getResources(),
|
||||
DisplayUtils.getResourceId("image/png", "default.png"));
|
||||
|
||||
// Initialise disk cache on background thread
|
||||
new InitDiskCacheTask().execute();
|
||||
// initialise thumbnails cache on background thread
|
||||
new ThumbnailsCacheManager.InitDiskCacheTask().execute();
|
||||
}
|
||||
|
||||
class InitDiskCacheTask extends AsyncTask<File, Void, Void> {
|
||||
@Override
|
||||
protected Void doInBackground(File... params) {
|
||||
synchronized (thumbnailDiskCacheLock) {
|
||||
try {
|
||||
mThumbnailCache = new DiskLruImageCache(mContext, "thumbnailCache",
|
||||
DISK_CACHE_SIZE, mCompressFormat, mCompressQuality);
|
||||
} catch (Exception e) {
|
||||
Log_OC.d(TAG, "Thumbnail cache could not be opened ", e);
|
||||
mThumbnailCache = null;
|
||||
}
|
||||
mThumbnailCacheStarting = false; // Finished initialization
|
||||
thumbnailDiskCacheLock.notifyAll(); // Wake any waiting threads
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static class AsyncDrawable extends BitmapDrawable {
|
||||
private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;
|
||||
|
||||
public AsyncDrawable(Resources res, Bitmap bitmap,
|
||||
ThumbnailGenerationTask bitmapWorkerTask) {
|
||||
super(res, bitmap);
|
||||
bitmapWorkerTaskReference =
|
||||
new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);
|
||||
}
|
||||
|
||||
public ThumbnailGenerationTask getBitmapWorkerTask() {
|
||||
return bitmapWorkerTaskReference.get();
|
||||
}
|
||||
}
|
||||
|
||||
class ThumbnailGenerationTask extends AsyncTask<OCFile, Void, Bitmap> {
|
||||
private final WeakReference<ImageView> imageViewReference;
|
||||
private OCFile file;
|
||||
|
||||
|
||||
public ThumbnailGenerationTask(ImageView imageView) {
|
||||
// Use a WeakReference to ensure the ImageView can be garbage collected
|
||||
imageViewReference = new WeakReference<ImageView>(imageView);
|
||||
}
|
||||
|
||||
// Decode image in background.
|
||||
@Override
|
||||
protected Bitmap doInBackground(OCFile... params) {
|
||||
Bitmap thumbnail = null;
|
||||
|
||||
try {
|
||||
file = params[0];
|
||||
final String imageKey = String.valueOf(file.getRemoteId());
|
||||
|
||||
// Check disk cache in background thread
|
||||
thumbnail = getBitmapFromDiskCache(imageKey);
|
||||
|
||||
// Not found in disk cache
|
||||
if (thumbnail == null || file.needsUpdateThumbnail()) {
|
||||
// Converts dp to pixel
|
||||
Resources r = mContext.getResources();
|
||||
int px = (int) Math.round(TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, 150, r.getDisplayMetrics()
|
||||
));
|
||||
|
||||
if (file.isDown()){
|
||||
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
|
||||
file.getStoragePath(), px, px);
|
||||
|
||||
if (bitmap != null) {
|
||||
thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
|
||||
|
||||
// Add thumbnail to cache
|
||||
addBitmapToCache(imageKey, thumbnail);
|
||||
|
||||
file.setNeedsUpdateThumbnail(false);
|
||||
mStorageManager.saveFile(file);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Throwable t) {
|
||||
// the app should never break due to a problem with thumbnails
|
||||
Log_OC.e(TAG, "Generation of thumbnail for " + file + " failed", t);
|
||||
if (t instanceof OutOfMemoryError) {
|
||||
System.gc();
|
||||
}
|
||||
}
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
protected void onPostExecute(Bitmap bitmap){
|
||||
if (isCancelled()) {
|
||||
bitmap = null;
|
||||
}
|
||||
|
||||
if (imageViewReference != null && bitmap != null) {
|
||||
final ImageView imageView = imageViewReference.get();
|
||||
final ThumbnailGenerationTask bitmapWorkerTask =
|
||||
getBitmapWorkerTask(imageView);
|
||||
if (this == bitmapWorkerTask && imageView != null) {
|
||||
if (imageView.getTag().equals(file.getFileId())) {
|
||||
imageView.setImageBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addBitmapToCache(String key, Bitmap bitmap) {
|
||||
synchronized (thumbnailDiskCacheLock) {
|
||||
if (mThumbnailCache != null) {
|
||||
mThumbnailCache.put(key, bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap getBitmapFromDiskCache(String key) {
|
||||
synchronized (thumbnailDiskCacheLock) {
|
||||
// Wait while disk cache is started from background thread
|
||||
while (mThumbnailCacheStarting) {
|
||||
try {
|
||||
thumbnailDiskCacheLock.wait();
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
if (mThumbnailCache != null) {
|
||||
return (Bitmap) mThumbnailCache.getBitmap(key);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areAllItemsEnabled() {
|
||||
return true;
|
||||
|
@ -339,16 +185,23 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
|
|||
// get Thumbnail if file is image
|
||||
if (file.isImage()){
|
||||
// Thumbnail in Cache?
|
||||
Bitmap thumbnail = getBitmapFromDiskCache(String.valueOf(file.getRemoteId()));
|
||||
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
|
||||
String.valueOf(file.getRemoteId())
|
||||
);
|
||||
if (thumbnail != null && !file.needsUpdateThumbnail()){
|
||||
fileIcon.setImageBitmap(thumbnail);
|
||||
} else {
|
||||
// generate new Thumbnail
|
||||
if (cancelPotentialWork(file, fileIcon)) {
|
||||
final ThumbnailGenerationTask task =
|
||||
new ThumbnailGenerationTask(fileIcon);
|
||||
final AsyncDrawable asyncDrawable =
|
||||
new AsyncDrawable(mContext.getResources(), defaultImg, task);
|
||||
if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {
|
||||
final ThumbnailsCacheManager.ThumbnailGenerationTask task =
|
||||
new ThumbnailsCacheManager.ThumbnailGenerationTask(
|
||||
fileIcon, mStorageManager
|
||||
);
|
||||
final AsyncDrawable asyncDrawable = new AsyncDrawable(
|
||||
mContext.getResources(),
|
||||
ThumbnailsCacheManager.mDefaultImg,
|
||||
task
|
||||
);
|
||||
fileIcon.setImageDrawable(asyncDrawable);
|
||||
task.execute(file);
|
||||
}
|
||||
|
@ -399,35 +252,6 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
|
|||
return view;
|
||||
}
|
||||
|
||||
public static boolean cancelPotentialWork(OCFile file, ImageView imageView) {
|
||||
final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
|
||||
|
||||
if (bitmapWorkerTask != null) {
|
||||
final OCFile bitmapData = bitmapWorkerTask.file;
|
||||
// If bitmapData is not yet set or it differs from the new data
|
||||
if (bitmapData == null || bitmapData != file) {
|
||||
// Cancel previous task
|
||||
bitmapWorkerTask.cancel(true);
|
||||
} else {
|
||||
// The same work is already in progress
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// No task associated with the ImageView, or an existing task was cancelled
|
||||
return true;
|
||||
}
|
||||
|
||||
private static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {
|
||||
if (imageView != null) {
|
||||
final Drawable drawable = imageView.getDrawable();
|
||||
if (drawable instanceof AsyncDrawable) {
|
||||
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
|
||||
return asyncDrawable.getBitmapWorkerTask();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewTypeCount() {
|
||||
return 1;
|
||||
|
|
Loading…
Reference in a new issue