Use UIL, don't do caching on our own.

Advantages:

* Initial setup time for icons is zero
* We don't have to deal with it ourselves
* We can use the default package icon while we load
This commit is contained in:
Daniel Martí 2013-09-23 20:21:29 +02:00
parent 0d6ec3a001
commit 017811fb92
8 changed files with 42 additions and 110 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "extern/Universal-Image-Loader"]
path = extern/Universal-Image-Loader
url = https://github.com/nostra13/Android-Universal-Image-Loader

1
extern/Universal-Image-Loader vendored Submodule

@ -0,0 +1 @@
Subproject commit 24ca7dd0dbaee8a011aad6195f33e840793e7df9

View File

@ -2,3 +2,4 @@ proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.
target=android-18
android.library.reference.1=extern/Universal-Image-Loader/library

View File

@ -70,6 +70,8 @@ import android.widget.BaseAdapter;
import org.fdroid.fdroid.compat.PackageManagerCompat;
import com.nostra13.universalimageloader.core.ImageLoader;
public class AppDetails extends ListActivity {
private static final int REQUEST_INSTALL = 0;
@ -406,12 +408,7 @@ public class AppDetails extends ListActivity {
// Set the icon...
ImageView iv = (ImageView) findViewById(R.id.icon);
File icon = new File(DB.getIconsPath(this), app.icon);
if (icon.exists()) {
iv.setImageDrawable(new BitmapDrawable(icon.getPath()));
} else {
iv.setImageResource(android.R.drawable.sym_def_app_icon);
}
ImageLoader.getInstance().displayImage(app.repoAddress+"/icons/"+app.icon, iv);
// Set the title and other header details...
TextView tv = (TextView) findViewById(R.id.title);

View File

@ -125,6 +125,7 @@ public class DB {
compatible = false;
ignoreUpdates = false;
filtered = false;
repoAddress = null;
}
// True when all the detail fields are populated, False otherwise.
@ -207,6 +208,8 @@ public class DB {
// List of apks.
public List<Apk> apks;
public String repoAddress;
// Get the current version - this will be one of the Apks from 'apks'.
// Can return null if there are no available versions.
// This should be the 'current' version, as in the most recent stable
@ -558,13 +561,6 @@ public class DB {
return ContextCompat.create(ctx).getExternalCacheDir();
}
public static File getIconsPath(Context ctx) {
File dp = getDataPath(ctx);
if (dp == null)
return null;
return new File(dp, "icons");
}
private Context mContext;
private Apk.CompatibilityChecker compatChecker = null;

View File

@ -19,7 +19,6 @@
package org.fdroid.fdroid;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;
@ -30,6 +29,13 @@ import android.util.Log;
import android.content.Context;
import android.content.SharedPreferences;
import com.nostra13.universalimageloader.utils.StorageUtils;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
public class FDroidApp extends Application {
@Override
@ -70,6 +76,21 @@ public class FDroidApp extends Application {
DB.initDB(ctx);
UpdateService.schedule(ctx);
File cacheDir = new File(StorageUtils.getCacheDirectory(ctx), "icons");
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisc(true)
.showImageOnLoading(android.R.drawable.sym_def_app_icon)
.showImageForEmptyUri(android.R.drawable.sym_def_app_icon)
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(ctx)
.discCache(new UnlimitedDiscCache(cacheDir, new FileNameGenerator() {
public String generate(String imageUri) {
return imageUri.substring(imageUri.lastIndexOf('/') + 1);
} } ))
.defaultDisplayImageOptions(defaultOptions)
.build();
ImageLoader.getInstance().init(config);
}
Context ctx;
@ -125,6 +146,11 @@ public class FDroidApp extends Application {
try {
DB db = DB.getDB();
apps = db.getApps(true);
for (DB.Repo repo : db.getRepos())
for (DB.App app : apps)
if (repo.id == app.apks.get(0).repo)
app.repoAddress = repo.address;
} finally {
DB.releaseDB();
}

View File

@ -255,38 +255,6 @@ public class UpdateService extends IntentService implements ProgressListener {
}
if (success) {
File d = DB.getIconsPath(this);
List<DB.App> toDownloadIcons = null;
if (!d.exists()) {
Log.d("FDroid", "Icons were wiped. Re-downloading all of them.");
d.mkdirs();
toDownloadIcons = ((FDroidApp) getApplication()).getApps();
} else if (changes) {
toDownloadIcons = acceptedapps;
}
if (toDownloadIcons != null) {
// Create a .nomedia file in the icons directory. For
// recent Android versions this isn't necessary, because
// they recognise the cache location. Older versions don't
// though.
File f = new File(d, ".nomedia");
if (!f.exists()) {
try {
f.createNewFile();
} catch (Exception e) {
Log.d("FDroid", "Failed to create .nomedia");
}
}
sendStatus(STATUS_INFO,
getString(R.string.status_downloading_icons));
for (DB.App app : toDownloadIcons)
getIcon(app, repos);
}
}
if (success && changes)
((FDroidApp) getApplication()).invalidateAllApps();
@ -348,52 +316,6 @@ public class UpdateService extends IntentService implements ProgressListener {
}
}
private void getIcon(final DB.App app, List<DB.Repo> repos) {
InputStream input = null;
OutputStream output = null;
try {
File f = new File(DB.getIconsPath(this), app.icon);
if (f.exists())
return;
if (app.apks.size() == 0)
return;
String server = null;
for (DB.Repo repo : repos)
if (repo.id == app.apks.get(0).repo)
server = repo.address;
if (server == null)
return;
// Get it from the server...
URL u = new URL(server + "/icons/" + app.icon);
HttpURLConnection uc = (HttpURLConnection) u.openConnection();
if (uc.getResponseCode() == 200) {
// Delete all other icons for the same app
final File[] files = DB.getIconsPath(this).listFiles(
new FilenameFilter() {
@Override
public boolean accept(final File d, final String n) {
return n.matches(app.id+"\\.[0-9]+\\.png");
}
} );
for (final File file : files) {
if (!file.delete())
Log.e("FDroid", "Cannot remove icon file " + file.getAbsolutePath());
}
input = uc.getInputStream();
output = new FileOutputStream(f);
Utils.copy(input, output);
}
} catch (Exception e) {
} finally {
Utils.closeQuietly(output);
Utils.closeQuietly(input);
}
}
/**
* Received progress event from the RepoXMLHandler. It could be progress

View File

@ -17,6 +17,8 @@ import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.compat.LayoutCompat;
import com.nostra13.universalimageloader.core.ImageLoader;
abstract public class AppListAdapter extends BaseAdapter {
private List<DB.App> items = new ArrayList<DB.App>();
@ -77,7 +79,7 @@ abstract public class AppListAdapter extends BaseAdapter {
summary.setText(app.summary);
layoutSummary(summary);
layoutIcon(icon, app);
ImageLoader.getInstance().displayImage(app.repoAddress+"/icons/"+app.icon, icon);
int visibleOnCompact = compact ? View.VISIBLE : View.GONE;
int notVisibleOnCompact = compact ? View.GONE : View.VISIBLE;
@ -118,22 +120,6 @@ abstract public class AppListAdapter extends BaseAdapter {
return convertView;
}
/**
* If an icon exists on disc, we'll use that, otherwise default to the
* plain android app icon.
*/
private void layoutIcon(ImageView iconView, DB.App app) {
File icn = new File(DB.getIconsPath(mContext), app.icon);
if (icn.exists() && icn.length() > 0) {
new Uri.Builder().build();
iconView.setImageURI(Uri.parse(icn.getPath()));
} else {
iconView.setImageResource(android.R.drawable.sym_def_app_icon);
}
}
/**
* In compact view, the summary sites next to the icon, below the name.
* In non-compact view, it sits under the icon, with some padding pushing