diff options
Diffstat (limited to 'src/github/daneren2005')
7 files changed, 195 insertions, 135 deletions
diff --git a/src/github/daneren2005/dsub/activity/SettingsActivity.java b/src/github/daneren2005/dsub/activity/SettingsActivity.java index 40ca5570..d496a201 100644 --- a/src/github/daneren2005/dsub/activity/SettingsActivity.java +++ b/src/github/daneren2005/dsub/activity/SettingsActivity.java @@ -557,7 +557,7 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer } @Override - protected void cancel() { + public void cancel() { super.cancel(); Util.setActiveServer(SettingsActivity.this, previousInstance); } diff --git a/src/github/daneren2005/dsub/util/BackgroundTask.java b/src/github/daneren2005/dsub/util/BackgroundTask.java index 547bbd1e..9f749116 100644 --- a/src/github/daneren2005/dsub/util/BackgroundTask.java +++ b/src/github/daneren2005/dsub/util/BackgroundTask.java @@ -20,10 +20,17 @@ package github.daneren2005.dsub.util; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.atomic.AtomicBoolean; import org.xmlpull.v1.XmlPullParserException; import android.app.Activity; +import android.content.Context; import android.os.Handler; import android.util.Log; import github.daneren2005.dsub.R; @@ -33,25 +40,46 @@ import github.daneren2005.dsub.view.ErrorDialog; * @author Sindre Mehus */ public abstract class BackgroundTask<T> implements ProgressListener { - private static final String TAG = BackgroundTask.class.getSimpleName(); - private final Activity activity; - private final Handler handler; - public BackgroundTask(Activity activity) { - this.activity = activity; - handler = new Handler(); + private final Context context; + protected boolean cancelled = false; + protected Task task; + + private static final int DEFAULT_CONCURRENCY = 5; + private static final Collection<Thread> threads = Collections.synchronizedCollection(new ArrayList<Thread>()); + protected static final BlockingQueue<BackgroundTask.Task> queue = new LinkedBlockingQueue<BackgroundTask.Task>(10); + private static final Handler handler = new Handler(); + + public BackgroundTask(Context context) { + this.context = context; + + if(threads.isEmpty()) { + for(int i = 0; i < DEFAULT_CONCURRENCY; i++) { + Thread thread = new Thread(new TaskRunnable(), String.format("BackgroundTask_%d", i)); + threads.add(thread); + thread.start(); + } + } } + public static void stopThreads() { + for(Thread thread: threads) { + thread.interrupt(); + } + threads.clear(); + queue.clear(); + } + protected Activity getActivity() { - return activity; + return (context instanceof Activity) ? ((Activity) context) : null; } protected Handler getHandler() { return handler; } - public abstract void execute(); + public abstract void execute(); protected abstract T doInBackground() throws Throwable; @@ -59,25 +87,28 @@ public abstract class BackgroundTask<T> implements ProgressListener { protected void error(Throwable error) { Log.w(TAG, "Got exception: " + error, error); - new ErrorDialog(activity, getErrorMessage(error), true); + Activity activity = getActivity(); + if(activity != null) { + new ErrorDialog(activity, getErrorMessage(error), true); + } } protected String getErrorMessage(Throwable error) { - if (error instanceof IOException && !Util.isNetworkConnected(activity)) { - return activity.getResources().getString(R.string.background_task_no_network); + if (error instanceof IOException && !Util.isNetworkConnected(context)) { + return context.getResources().getString(R.string.background_task_no_network); } if (error instanceof FileNotFoundException) { - return activity.getResources().getString(R.string.background_task_not_found); + return context.getResources().getString(R.string.background_task_not_found); } if (error instanceof IOException) { - return activity.getResources().getString(R.string.background_task_network_error); + return context.getResources().getString(R.string.background_task_network_error); } if (error instanceof XmlPullParserException) { - return activity.getResources().getString(R.string.background_task_parse_error); + return context.getResources().getString(R.string.background_task_parse_error); } String message = error.getMessage(); @@ -87,11 +118,104 @@ public abstract class BackgroundTask<T> implements ProgressListener { return error.getClass().getSimpleName(); } + public void cancel() { + cancelled = true; + if(task != null) { + task.cancel(); + } + } + protected boolean isCancelled() { + return cancelled; + } + @Override public abstract void updateProgress(final String message); @Override public void updateProgress(int messageId) { - updateProgress(activity.getResources().getString(messageId)); + updateProgress(context.getResources().getString(messageId)); } -}
\ No newline at end of file + + protected class Task { + private Thread thread; + private AtomicBoolean taskStart = new AtomicBoolean(true); + + private void execute() throws Exception { + if(!taskStart.get()) { + return; + } + + thread = Thread.currentThread(); + try { + final T result = doInBackground(); + if(isCancelled()) { + return; + } + + handler.post(new Runnable() { + @Override + public void run() { + onDone(result); + } + }); + } catch(InterruptedException interrupt) { + if(taskStart.get()) { + // Don't exit root thread if task cancelled + throw interrupt; + } + } catch(final Throwable t) { + if(isCancelled()) { + return; + } + + handler.post(new Runnable() { + @Override + public void run() { + try { + onError(t); + } catch(Exception e) { + // Don't care + } + } + }); + } + } + + public void cancel() { + taskStart.set(false); + if(thread != null) { + thread.interrupt(); + } + } + public void onDone(T result) { + done(result); + } + public void onError(Throwable t) { + error(t); + } + } + + private class TaskRunnable implements Runnable { + private boolean running = true; + + public TaskRunnable() { + + } + + @Override + public void run() { + while(running) { + try { + Task task = queue.take(); + task.execute(); + } catch(InterruptedException stop) { + running = false; + threads.remove(Thread.currentThread()); + } catch(Throwable t) { + Log.e(TAG, "Unexpected crash in BackgroundTask thread", t); + } + } + } + } + +} diff --git a/src/github/daneren2005/dsub/util/CacheCleaner.java b/src/github/daneren2005/dsub/util/CacheCleaner.java index 62204c76..102c1dc9 100644 --- a/src/github/daneren2005/dsub/util/CacheCleaner.java +++ b/src/github/daneren2005/dsub/util/CacheCleaner.java @@ -65,7 +65,7 @@ public class CacheCleaner { } } - private long getMinimumDelete(List<File> files) { + private long getMinimumDelete(List<File> files, List<File> pinned) { if(files.size() == 0) { return 0L; } @@ -76,6 +76,9 @@ public class CacheCleaner { for (File file : files) { bytesUsedBySubsonic += file.length(); } + for (File file : pinned) { + bytesUsedBySubsonic += file.length(); + } // Ensure that file system is not more than 95% full. StatFs stat = new StatFs(files.get(0).getPath()); @@ -118,17 +121,19 @@ public class CacheCleaner { Log.i(TAG, "Deleted : " + Util.formatBytes(bytesDeleted)); } - private void findCandidatesForDeletion(File file, List<File> files, List<File> dirs) { + private void findCandidatesForDeletion(File file, List<File> files, List<File> pinned, List<File> dirs) { if (file.isFile()) { String name = file.getName(); boolean isCacheFile = name.endsWith(".partial") || name.contains(".partial.") || name.endsWith(".complete") || name.contains(".complete."); if (isCacheFile) { files.add(file); - } + } else { + pinned.add(file); + } } else { // Depth-first for (File child : FileUtil.listFiles(file)) { - findCandidatesForDeletion(child, files, dirs); + findCandidatesForDeletion(child, files, pinned, dirs); } dirs.add(file); } @@ -171,14 +176,15 @@ public class CacheCleaner { try { List<File> files = new ArrayList<File>(); + List<File> pinned = new ArrayList<File>(); List<File> dirs = new ArrayList<File>(); - findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, dirs); + findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, pinned, dirs); sortByAscendingModificationTime(files); Set<File> undeletable = findUndeletableFiles(); - deleteFiles(files, undeletable, getMinimumDelete(files), true); + deleteFiles(files, undeletable, getMinimumDelete(files, pinned), true); deleteEmptyDirs(dirs, undeletable); } catch (RuntimeException x) { Log.e(TAG, "Error in cache cleaning.", x); @@ -198,10 +204,11 @@ public class CacheCleaner { try { List<File> files = new ArrayList<File>(); + List<File> pinned = new ArrayList<File>(); List<File> dirs = new ArrayList<File>(); - findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, dirs); + findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, pinned, dirs); - long bytesToDelete = getMinimumDelete(files); + long bytesToDelete = getMinimumDelete(files, pinned); if(bytesToDelete > 0L) { sortByAscendingModificationTime(files); Set<File> undeletable = findUndeletableFiles(); diff --git a/src/github/daneren2005/dsub/util/LoadingTask.java b/src/github/daneren2005/dsub/util/LoadingTask.java index 7faa6afe..c47931ee 100644 --- a/src/github/daneren2005/dsub/util/LoadingTask.java +++ b/src/github/daneren2005/dsub/util/LoadingTask.java @@ -14,9 +14,7 @@ public abstract class LoadingTask<T> extends BackgroundTask<T> { private final Activity tabActivity;
private ProgressDialog loading;
- private Thread thread;
private final boolean cancellable;
- private boolean cancelled = false;
public LoadingTask(Activity activity) {
super(activity);
@@ -35,56 +33,26 @@ public abstract class LoadingTask<T> extends BackgroundTask<T> { public void onCancel(DialogInterface dialog) {
cancel();
}
-
});
- thread = new Thread() {
- @Override
- public void run() {
- try {
- final T result = doInBackground();
- if (isCancelled()) {
- return;
- }
+ queue.offer(task = new Task() {
+ @Override
+ public void onDone(T result) {
+ loading.dismiss();
+ done(result);
+ }
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- loading.cancel();
- done(result);
- }
- });
- } catch (final Throwable t) {
- if (isCancelled()) {
- return;
- }
-
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- try {
- loading.cancel();
- error(t);
- } catch(Exception e) {
- // Don't care
- }
- }
- });
- }
- }
- };
- thread.start();
+ @Override
+ public void onError(Throwable t) {
+ loading.dismiss();
+ error(t);
+ }
+ });
}
- protected void cancel() {
- cancelled = true;
- if (thread != null) {
- thread.interrupt();
- }
- }
-
- private boolean isCancelled() {
- return (tabActivity instanceof SubsonicActivity && ((SubsonicActivity)tabActivity).isDestroyed()) || cancelled;
+ @Override
+ protected boolean isCancelled() {
+ return (tabActivity instanceof SubsonicActivity && tabActivity.isDestroyed()) || cancelled;
}
@Override
diff --git a/src/github/daneren2005/dsub/util/SilentBackgroundTask.java b/src/github/daneren2005/dsub/util/SilentBackgroundTask.java index 7bceb467..a0db7ca4 100644 --- a/src/github/daneren2005/dsub/util/SilentBackgroundTask.java +++ b/src/github/daneren2005/dsub/util/SilentBackgroundTask.java @@ -18,43 +18,19 @@ */ package github.daneren2005.dsub.util; -import android.app.Activity; +import android.content.Context; /** * @author Sindre Mehus */ public abstract class SilentBackgroundTask<T> extends BackgroundTask<T> { - - public SilentBackgroundTask(Activity activity) { - super(activity); + public SilentBackgroundTask(Context context) { + super(context); } @Override public void execute() { - Thread thread = new Thread() { - @Override - public void run() { - try { - final T result = doInBackground(); - - getHandler().post(new Runnable() { - @Override - public void run() { - done(result); - } - }); - - } catch (final Throwable t) { - getHandler().post(new Runnable() { - @Override - public void run() { - error(t); - } - }); - } - } - }; - thread.start(); + queue.offer(task = new Task()); } @Override diff --git a/src/github/daneren2005/dsub/util/TabBackgroundTask.java b/src/github/daneren2005/dsub/util/TabBackgroundTask.java index c345b982..bd76a2d4 100644 --- a/src/github/daneren2005/dsub/util/TabBackgroundTask.java +++ b/src/github/daneren2005/dsub/util/TabBackgroundTask.java @@ -19,40 +19,24 @@ public abstract class TabBackgroundTask<T> extends BackgroundTask<T> { public void execute() {
tabFragment.setProgressVisible(true);
- new Thread() {
- @Override
- public void run() {
- try {
- final T result = doInBackground();
- if (isCancelled()) {
- return;
- }
-
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- tabFragment.setProgressVisible(false);
- done(result);
- }
- });
- } catch (final Throwable t) {
- if (isCancelled()) {
- return;
- }
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- tabFragment.setProgressVisible(false);
- error(t);
- }
- });
- }
- }
- }.start();
+ queue.offer(task = new Task() {
+ @Override
+ public void onDone(T result) {
+ tabFragment.setProgressVisible(false);
+ done(result);
+ }
+
+ @Override
+ public void onError(Throwable t) {
+ tabFragment.setProgressVisible(false);
+ error(t);
+ }
+ });
}
- private boolean isCancelled() {
- return !tabFragment.isAdded();
+ @Override
+ protected boolean isCancelled() {
+ return !tabFragment.isAdded() || cancelled;
}
@Override
diff --git a/src/github/daneren2005/dsub/view/ErrorDialog.java b/src/github/daneren2005/dsub/view/ErrorDialog.java index 246b3756..e72b1934 100644 --- a/src/github/daneren2005/dsub/view/ErrorDialog.java +++ b/src/github/daneren2005/dsub/view/ErrorDialog.java @@ -20,6 +20,7 @@ package github.daneren2005.dsub.view; import android.app.Activity; import android.app.AlertDialog; +import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -67,9 +68,9 @@ public class ErrorDialog { } } - private void restart(Activity context) { - Intent intent = new Intent(context, SubsonicFragmentActivity.class); + private void restart(Activity activity) { + Intent intent = new Intent(activity, SubsonicFragmentActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - Util.startActivityWithoutTransition(context, intent); + Util.startActivityWithoutTransition(activity, intent); } } |