Android Open Source - Feeder Download Manager






From Project

Back to project page Feeder.

License

The source code is released under:

GNU General Public License

If you think the Android project Feeder listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * $Id: $/*from  w w  w. j a  v  a2s . com*/
 *
 * Copyright (C) 2012 Stoyan Rachev (stoyanr@gmail.com)
 * Copyright (C) 2007 Josh Guilfoyle (jasta@devtcg.org)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * 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.
 */

package com.stoyanr.feeder.download;

import java.util.Collection;
import java.util.concurrent.ConcurrentLinkedQueue;

import android.os.Handler;

/**
 * Generic network connection manager to gracefully throttle and control
 * unpredictable download threads.
 * 
 * This class implements a strategy to gracefully satisfy the "refresh all"
 * semantics. The default behavior is to spawn a new connection {@link Thread}
 * every 8 seconds or whenever the previously queued {@link Thread} finishes
 * execution. There is no specific awareness of what action is being performed
 * by the spawned {@link Thread}, nor is it even necessary that the
 * {@link Thread} utilizes the network.
 * 
 * @see Thread
 * @see android.os.Handler
 */
public class DownloadManager {

    private static final int TIMEOUT = 4000;

    private final Handler handler;

    // @formatter:off
    private final ConcurrentLinkedQueue<DownloadThread> threads = 
        new ConcurrentLinkedQueue<DownloadThread>();
    private final ConcurrentLinkedQueue<Runnable> queue = 
        new ConcurrentLinkedQueue<Runnable>();
    // @formatter:on

    /**
     * Associate a new DownloadManager instance with a thread's message queue.
     */
    public DownloadManager(Handler handler) {
        this.handler = handler;
    }

    /**
     * Schedule a new download worker.
     */
    public boolean schedule(Runnable r) {
        queue.add(r);
        if (threads.size() == 0) {
            handler.removeCallbacks(wakeUpThread);
            wakeUpThread.run();
            return true;
        }
        return false;
    }

    private Runnable wakeUpThread = new Runnable() {
        @Override
        public void run() {
            Runnable r = queue.poll();
            if (r == null) {
                return;
            }

            // Flag all currently processing workers as being too slow, so that
            // we know not to wake up when they finish. This would cause
            // connections that take just slightly longer than TIMEOUT to add a
            // new concurrent connection every TIMEOUT msec.
            for (DownloadThread t : threads)
                t.setTooSlow();

            DownloadThread t = new DownloadThread(threads, handler, r);
            threads.add(t);
            t.start();

            // Schedule a check-up in TIMEOUT msec. This will be bumped if t
            // finishes within that window.
            handler.removeCallbacks(this);
            handler.postDelayed(this, TIMEOUT);
        }
    };

    /**
     * Wraps the invocation of queued Runnables so that we can trap their exit.
     * Normally, this would be done with a Handler, but our implementation is
     * non-invasive to the Activity's Handler.
     */
    private class DownloadThread extends Thread {

        private final Collection<DownloadThread> activeThreads;
        private final Handler handler;
        private final Runnable runnable;
        private boolean tooSlow = false;

        public DownloadThread(Collection<DownloadThread> activeThreads,
            Handler handler, Runnable runnable) {
            this.activeThreads = activeThreads;
            this.handler = handler;
            this.runnable = runnable;
        }

        public void setTooSlow() {
            tooSlow = true;
        }

        @Override
        public void run() {
            runnable.run();

            // There may be another entry waiting in the queue for this one to
            // finish. So, bump the wait callback up to run now.
            activeThreads.remove(this);

            if (!tooSlow) {
                handler.removeCallbacks(wakeUpThread);
                handler.post(wakeUpThread);
            }
        }
    }
}




Java Source Code List

com.stoyanr.feeder.activity.AddChannelActivity.java
com.stoyanr.feeder.activity.ChannelsActivity.java
com.stoyanr.feeder.activity.ChannelsAdapter.java
com.stoyanr.feeder.activity.ItemsActivity.java
com.stoyanr.feeder.activity.ItemsAdapter.java
com.stoyanr.feeder.activity.SettingsActivity.java
com.stoyanr.feeder.activity.ViewItemActivity.java
com.stoyanr.feeder.annotations.DefaultSortOrder.java
com.stoyanr.feeder.annotations.MimeType.java
com.stoyanr.feeder.annotations.UriPaths.java
com.stoyanr.feeder.content.AbstractContentProvider.java
com.stoyanr.feeder.content.ContentManager.java
com.stoyanr.feeder.content.DatabaseHelper.java
com.stoyanr.feeder.content.MainContentProvider.java
com.stoyanr.feeder.download.DownloadManager.java
com.stoyanr.feeder.model.Channel.java
com.stoyanr.feeder.model.Data.java
com.stoyanr.feeder.model.Item.java
com.stoyanr.feeder.service.MainService.java
com.stoyanr.feeder.sync.Synchronizer.java
com.stoyanr.feeder.util.BitmapCache.java
com.stoyanr.feeder.util.DateUtils.java
com.stoyanr.feeder.util.DialogUtils.java
com.stoyanr.feeder.util.IOUtils.java
com.stoyanr.feeder.util.KeyUtils.java
com.stoyanr.feeder.util.MenuUtils.java
com.stoyanr.feeder.util.ResourceUtils.java
com.stoyanr.feeder.util.UrlUtils.java
com.stoyanr.feeder.view.ChannelHeader.java
com.stoyanr.feeder.view.ChannelView.java
com.stoyanr.feeder.view.ItemView.java