界面效果

线程池 ThreadPoolExecutor
    在以下介绍实现下载原理的时候。我想尝试倒着来说。这样是否好理解一点? 
    我们都知道。下载助手,比方360, 百度的 手机助手,下载APP 的时候 ,都能够同一时候下载多个。所以,下载肯定是多线程的。所以我们就须要一个线程工具类 来管理我们的线程,这个工具类的核心,就是 线程池。
 
线程池ThreadPoolExecutor ,先简单学习下这个线程池的使用
-  
 -  
 -  
 -  
 -  
 -  
 -  
 -  
 -  
 -  
 -  
 -  
 -  
 -  
 -  
 -  
 -  
 -  
 -  
 -  
 -  
 -   
 -       ThreadPoolExecutor threadpool=new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler)  
 
    上面是 ThreadPoolExecutor的參数介绍。 
    第一个參数 corePoolSize : 空暇时 存在的线程数目、 
    第二个參数 maximumPoolSize :同意同一时候存在的最大线程数、 
    第三个參数 keepAliveTime: 这个參数是 同意空暇线程存活的时间、 
    第四个參数 unit : 是 时间的单位 、 
    第五个參数 workQueue :这个是一个容器,它里面存放的是、 threadpool.execute(new Runnable()) 运行的线程.new Runnable()、 
    第六个參数 handler:当运行被堵塞时,该处理程序将被堵塞。由于线程的边界和队列容量达到了 。
工具类 ThreadManager
介绍完了 线程池參数,那我们就先创建一个线程管理的工具类 ThreadManager
- public class ThreadManager {  
 -     public static final String DEFAULT_SINGLE_POOL_NAME = "DEFAULT_SINGLE_POOL_NAME";  
 -   
 -     private static ThreadPoolProxy mLongPool = null;  
 -     private static Object mLongLock = new Object();  
 -   
 -     private static ThreadPoolProxy mShortPool = null;  
 -     private static Object mShortLock = new Object();  
 -   
 -     private static ThreadPoolProxy mDownloadPool = null;  
 -     private static Object mDownloadLock = new Object();  
 -   
 -     private static Map<String, ThreadPoolProxy> mMap = new HashMap<String, ThreadPoolProxy>();  
 -     private static Object mSingleLock = new Object();  
 -   
 -       
 -     public static ThreadPoolProxy getDownloadPool() {  
 -         synchronized (mDownloadLock) {  
 -             if (mDownloadPool == null) {  
 -                 mDownloadPool = new ThreadPoolProxy(3, 3, 5L);  
 -             }  
 -             return mDownloadPool;  
 -         }  
 -     }  
 -   
 -       
 -     public static ThreadPoolProxy getLongPool() {  
 -         synchronized (mLongLock) {  
 -             if (mLongPool == null) {  
 -                 mLongPool = new ThreadPoolProxy(5, 5, 5L);  
 -             }  
 -             return mLongPool;  
 -         }  
 -     }  
 -   
 -       
 -     public static ThreadPoolProxy getShortPool() {  
 -         synchronized (mShortLock) {  
 -             if (mShortPool == null) {  
 -                 mShortPool = new ThreadPoolProxy(2, 2, 5L);  
 -             }  
 -             return mShortPool;  
 -         }  
 -     }  
 -   
 -       
 -     public static ThreadPoolProxy getSinglePool() {  
 -         return getSinglePool(DEFAULT_SINGLE_POOL_NAME);  
 -     }  
 -   
 -       
 -     public static ThreadPoolProxy getSinglePool(String name) {  
 -         synchronized (mSingleLock) {  
 -             ThreadPoolProxy singlePool = mMap.get(name);  
 -             if (singlePool == null) {  
 -                 singlePool = new ThreadPoolProxy(1, 1, 5L);  
 -                 mMap.put(name, singlePool);  
 -             }  
 -             return singlePool;  
 -         }  
 -     }  
 -   
 -     public static class ThreadPoolProxy {  
 -         private ThreadPoolExecutor mPool;  
 -         private int mCorePoolSize;  
 -         private int mMaximumPoolSize;  
 -         private long mKeepAliveTime;  
 -   
 -         private ThreadPoolProxy(int corePoolSize, int maximumPoolSize, long keepAliveTime) {  
 -             mCorePoolSize = corePoolSize;  
 -             mMaximumPoolSize = maximumPoolSize;  
 -             mKeepAliveTime = keepAliveTime;  
 -         }  
 -   
 -           
 -         public synchronized void execute(Runnable run) {  
 -             if (run == null) {  
 -                 return;  
 -             }  
 -             if (mPool == null || mPool.isShutdown()) {  
 -                 mPool = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, mKeepAliveTime, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), Executors.defaultThreadFactory(), new AbortPolicy());  
 -             }  
 -             mPool.execute(run);  
 -         }  
 -   
 -           
 -         public synchronized void cancel(Runnable run) {  
 -             if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {  
 -                 mPool.getQueue().remove(run);  
 -             }  
 -         }  
 -   
 -           
 -         public synchronized boolean contains(Runnable run) {  
 -             if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {  
 -                 return mPool.getQueue().contains(run);  
 -             } else {  
 -                 return false;  
 -             }  
 -         }  
 -   
 -           
 -         public void stop() {  
 -             if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {  
 -                 mPool.shutdownNow();  
 -             }  
 -         }  
 -   
 -           
 -         public synchronized void shutdown() {  
 -             if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {  
 -                 mPool.shutdownNow();  
 -             }  
 -         }  
 -   
 -     }  
 - }  
 
    这个线程池工具类 主要就是 生成一个线程池。 以及 取消线程池中的任务,查询线程池中是否包括某一任务。
下载任务 DownloadTask
    我们的如今线程 DownloadTask 就 通过 ThreadManager .getDownloadPool().execute() 方法 交给线程池去管理。
    有了线程池管理我们的线程。 那我们下一步 就是 DownloadTask 这个类去下载了。
-   
 -   public class DownloadTask implements Runnable {  
 -       private DownloadInfo info;  
 -   
 -       public DownloadTask(DownloadInfo info) {  
 -           this.info = info;  
 -       }  
 -   
 -       @Override  
 -       public void run() {  
 -           info.setDownloadState(STATE_DOWNLOADING);  
 -           notifyDownloadStateChanged(info);  
 -           File file = new File(info.getPath());  
 -           HttpResult httpResult = null;  
 -           InputStream stream = null;  
 -           if (info.getCurrentSize() == 0 || !file.exists()  
 -                   || file.length() != info.getCurrentSize()) {  
 -                 
 -   
 -               info.setCurrentSize(0);  
 -               file.delete();  
 -           }  
 -           httpResult = HttpHelper.download(info.getUrl());  
 -             
 -             
 -             
 -             
 -             
 -           if (httpResult == null  
 -                   || (stream = httpResult.getInputStream()) == null) {  
 -               info.setDownloadState(STATE_ERROR);  
 -               notifyDownloadStateChanged(info);  
 -           } else {  
 -               try {  
 -                   skipBytesFromStream(stream, info.getCurrentSize());  
 -               } catch (Exception e1) {  
 -                   e1.printStackTrace();  
 -               }  
 -   
 -               FileOutputStream fos = null;  
 -               try {  
 -                   fos = new FileOutputStream(file, true);  
 -                   int count = -1;  
 -                   byte[] buffer = new byte[1024];  
 -                   while (((count = stream.read(buffer)) != -1)  
 -                           && info.getDownloadState() == STATE_DOWNLOADING) {  
 -                         
 -                       fos.write(buffer, 0, count);  
 -                       fos.flush();  
 -                       info.setCurrentSize(info.getCurrentSize() + count);  
 -                       notifyDownloadProgressed(info);  
 -                   }  
 -               } catch (Exception e) {  
 -                   info.setDownloadState(STATE_ERROR);  
 -                   notifyDownloadStateChanged(info);  
 -                   info.setCurrentSize(0);  
 -                   file.delete();  
 -               } finally {  
 -                   IOUtils.close(fos);  
 -                   if (httpResult != null) {  
 -                       httpResult.close();  
 -                   }  
 -               }  
 -   
 -                 
 -               if (info.getCurrentSize() == info.getAppSize()) {  
 -                   info.setDownloadState(STATE_DOWNLOADED);  
 -                   notifyDownloadStateChanged(info);  
 -               } else if (info.getDownloadState() == STATE_PAUSED) {  
 -                   notifyDownloadStateChanged(info);  
 -               } else {  
 -                   info.setDownloadState(STATE_ERROR);  
 -                   notifyDownloadStateChanged(info);  
 -                   info.setCurrentSize(0);  
 -                   file.delete();  
 -               }  
 -           }  
 -           mTaskMap.remove(info.getId());  
 -       }  
 -   }  
 
    下载的原理 非常easy。就是 通过 目标的URL 拿到流,然后写到本地。
 
    由于下载在 run() 里面运行,这个DownloadTask 类 我们就看run() 方法的实现,所以 关键代码 就是以下一点点
- fos = new FileOutputStream(file, true);  
 -           int count = -1;  
 -           byte[] buffer = new byte[1024];  
 -           while (((count = stream.read(buffer)) != -1)  
 -                   && info.getDownloadState() == STATE_DOWNLOADING) {  
 -                 
 -               fos.write(buffer, 0, count);  
 -               fos.flush();  
 -               info.setCurrentSize(info.getCurrentSize() + count);  
 -               notifyDownloadProgressed(info);  
 -           }  
 
   这个在我们刚接触Java 的时候 肯定都写过了。 这就是往本地写数据的代码。所以run()方法中的 前面 就是拿到 stream 输入流, 以及 把file 创建出来。
刷新进度。状态
    关于控制 button中text 显示 暂停 ,下载。还是进度,就靠 notifyDownloadProgressed(info);和 notifyDownloadStateChanged(info)两个方法, 这两个方法 实际上调用的是两个接口,仅仅要我们在我们须要改变界面的类里 实现这两个接口,就能够接收到 包括最新信息的info对象。而我们在哪个类里改变button 上面 显示的文字呢? 当然是在 我们的adapter 里面了,大家都知道 是在 adapter 的getView() 方法里面 载入的每一条数据的布局。
    那就一起看下是不是这样子呢?
- public class RecommendAdapter extends BaseAdapter implements  
 -         DownloadManager.DownloadObserver {  
 -   
 -     ArrayList<AppInfo> list;  
 -     private List<ViewHolder> mDisplayedHolders;  
 -     private FinalBitmap finalBitmap;  
 -     private Context context;  
 -   
 -     public RecommendAdapter(ArrayList<AppInfo> list, FinalBitmap finalBitmap,  
 -             Context context) {  
 -         this.list = list;  
 -         this.context = context;  
 -         this.finalBitmap = finalBitmap;  
 -         mDisplayedHolders = new ArrayList<ViewHolder>();  
 -     }  
 -   
 -   
 -   
 -     public void startObserver() {  
 -         DownloadManager.getInstance().registerObserver(this);  
 -     }  
 -   
 -     public void stopObserver() {  
 -         DownloadManager.getInstance().unRegisterObserver(this);  
 -     }  
 -   
 -     @Override  
 -     public int getCount() {  
 -         return list.size();  
 -     }  
 -   
 -     @Override  
 -     public Object getItem(int position) {  
 -         return list.get(position);  
 -     }  
 -   
 -     @Override  
 -     public long getItemId(int position) {  
 -         return position;  
 -     }  
 -   
 -     @Override  
 -     public View getView(int position, View convertView, ViewGroup parent) {  
 -         final AppInfo appInfo = list.get(position);  
 -         final ViewHolder holder;  
 -   
 -         if (convertView == null) {  
 -             holder = new ViewHolder(context);  
 -         } else {  
 -             holder = (ViewHolder) convertView.getTag();  
 -         }  
 -         holder.setData(appInfo);  
 -         mDisplayedHolders.add(holder);  
 -         return holder.getRootView();  
 -     }  
 -   
 -     @Override  
 -     public void onDownloadStateChanged(DownloadInfo info) {  
 -         refreshHolder(info);  
 -     }  
 -   
 -     @Override  
 -     public void onDownloadProgressed(DownloadInfo info) {  
 -         refreshHolder(info);  
 -   
 -     }  
 -   
 -     public List<ViewHolder> getDisplayedHolders() {  
 -         synchronized (mDisplayedHolders) {  
 -             return new ArrayList<ViewHolder>(mDisplayedHolders);  
 -         }  
 -     }  
 -   
 -     public void clearAllItem() {  
 -         if (list != null){  
 -             list.clear();  
 -         }  
 -         if (mDisplayedHolders != null) {  
 -             mDisplayedHolders.clear();  
 -         }  
 -     }  
 -   
 -     public void addItems(ArrayList<AppInfo> infos) {  
 -         list.addAll(infos);  
 -     }  
 -   
 -     private void refreshHolder(final DownloadInfo info) {  
 -         List<ViewHolder> displayedHolders = getDisplayedHolders();  
 -         for (int i = 0; i < displayedHolders.size(); i++) {  
 -             final ViewHolder holder = displayedHolders.get(i);  
 -             AppInfo appInfo = holder.getData();  
 -             if (appInfo.getId() == info.getId()) {  
 -                 AppUtil.post(new Runnable() {  
 -                     @Override  
 -                     public void run() {  
 -                         holder.refreshState(info.getDownloadState(),  
 -                                 info.getProgress());  
 -                     }  
 -                 });  
 -             }  
 -         }  
 -   
 -     }  
 -   
 -     public class ViewHolder {  
 -         public TextView textView01;  
 -         public TextView textView02;  
 -         public TextView textView03;  
 -         public TextView textView04;  
 -         public ImageView imageView_icon;  
 -         public Button button;  
 -         public LinearLayout linearLayout;  
 -   
 -         public AppInfo mData;  
 -         private DownloadManager mDownloadManager;  
 -         private int mState;  
 -         private float mProgress;  
 -         protected View mRootView;  
 -         private Context context;  
 -         private boolean hasAttached;  
 -   
 -         public ViewHolder(Context context) {  
 -             mRootView = initView();  
 -             mRootView.setTag(this);  
 -             this.context = context;  
 -   
 -   
 -         }  
 -   
 -         public View getRootView() {  
 -             return mRootView;  
 -         }  
 -   
 -         public View initView() {  
 -             View view = AppUtil.inflate(R.layout.item_recommend_award);  
 -   
 -             imageView_icon = (ImageView) view  
 -                     .findViewById(R.id.imageview_task_app_cion);  
 -   
 -             textView01 = (TextView) view  
 -                     .findViewById(R.id.textview_task_app_name);  
 -             textView02 = (TextView) view  
 -                     .findViewById(R.id.textview_task_app_size);  
 -             textView03 = (TextView) view  
 -                     .findViewById(R.id.textview_task_app_desc);  
 -             textView04 = (TextView) view  
 -                     .findViewById(R.id.textview_task_app_love);  
 -             button = (Button) view.findViewById(R.id.button_task_download);  
 -             linearLayout = (LinearLayout) view  
 -                     .findViewById(R.id.linearlayout_task);  
 -   
 -             button.setOnClickListener(new OnClickListener() {  
 -                 @Override  
 -                 public void onClick(View v) {  
 -                     System.out.println("mState:173    "+mState);  
 -                     if (mState == DownloadManager.STATE_NONE  
 -                             || mState == DownloadManager.STATE_PAUSED  
 -                             || mState == DownloadManager.STATE_ERROR) {  
 -   
 -                         mDownloadManager.download(mData);  
 -                     } else if (mState == DownloadManager.STATE_WAITING  
 -                             || mState == DownloadManager.STATE_DOWNLOADING) {  
 -                         mDownloadManager.pause(mData);  
 -                     } else if (mState == DownloadManager.STATE_DOWNLOADED) {  
 -   
 -                         mDownloadManager.install(mData);  
 -                     }  
 -                 }  
 -             });  
 -             return view;  
 -         }  
 -   
 -   
 -         public void setData(AppInfo data) {  
 -   
 -             if (mDownloadManager == null) {  
 -                 mDownloadManager = DownloadManager.getInstance();  
 -   
 -             }  
 -              String filepath= FileUtil.getDownloadDir(AppUtil.getContext()) + File.separator + data.getName() + ".apk";  
 -   
 -                 boolean existsFile = FileUtil.isExistsFile(filepath);  
 -                 if(existsFile){  
 -                     int fileSize = FileUtil.getFileSize(filepath);  
 -   
 -                     if(data.getSize()==fileSize){  
 -                         DownloadInfo downloadInfo = DownloadInfo.clone(data);  
 -                         downloadInfo.setCurrentSize(data.getSize());  
 -                         downloadInfo.setHasFinished(true);  
 -                         mDownloadManager.setDownloadInfo(data.getId(),downloadInfo );  
 -                     }  
 -   
 -   
 -   
 -   
 -   
 -   
 -   
 -                 }  
 -   
 -             DownloadInfo downloadInfo = mDownloadManager.getDownloadInfo(data  
 -                     .getId());  
 -             if (downloadInfo != null) {  
 -   
 -                 mState = downloadInfo.getDownloadState();  
 -                 mProgress = downloadInfo.getProgress();  
 -             } else {  
 -   
 -                 mState = DownloadManager.STATE_NONE;  
 -                 mProgress = 0;  
 -             }  
 -             this.mData = data;  
 -             refreshView();  
 -         }  
 -   
 -         public AppInfo getData() {  
 -             return mData;  
 -         }  
 -   
 -         public void refreshView() {  
 -             linearLayout.removeAllViews();  
 -             AppInfo info = getData();  
 -             textView01.setText(info.getName());  
 -             textView02.setText(FileUtil.FormetFileSize(info.getSize()));  
 -             textView03.setText(info.getDes());  
 -             textView04.setText(info.getDownloadNum() + "下载量);  
 -             finalBitmap.display(imageView_icon, info.getIconUrl());  
 -   
 -   
 -             if (info.getType().equals("0")) {  
 -   
 -                 textView02.setVisibility(View.GONE);  
 -             }else{  
 -                 String  path=FileUtil.getDownloadDir(AppUtil.getContext()) + File.separator + info.getName() + ".apk";  
 -                 hasAttached = FileUtil.isValidAttach(path, false);  
 -   
 -                 DownloadInfo downloadInfo = mDownloadManager.getDownloadInfo(info  
 -                         .getId());  
 -                 if (downloadInfo != null && hasAttached) {  
 -                     if(downloadInfo.isHasFinished()){  
 -   
 -                         mState = DownloadManager.STATE_DOWNLOADED;  
 -                     }else{  
 -                         mState = DownloadManager.STATE_PAUSED;  
 -   
 -                     }  
 -   
 -                 } else {  
 -                     mState = DownloadManager.STATE_NONE;  
 -                     if(downloadInfo !=null){  
 -                         downloadInfo.setDownloadState(mState);  
 -                     }  
 -                 }  
 -             }  
 -   
 -             refreshState(mState, mProgress);  
 -         }  
 -   
 -         public void refreshState(int state, float progress) {  
 -             mState = state;  
 -             mProgress = progress;  
 -             switch (mState) {  
 -             case DownloadManager.STATE_NONE:  
 -                 button.setText(R.string.app_state_download);  
 -                 break;  
 -             case DownloadManager.STATE_PAUSED:  
 -                 button.setText(R.string.app_state_paused);  
 -                 break;  
 -             case DownloadManager.STATE_ERROR:  
 -                 button.setText(R.string.app_state_error);  
 -                 break;  
 -             case DownloadManager.STATE_WAITING:  
 -                 button.setText(R.string.app_state_waiting);  
 -                 break;  
 -             case DownloadManager.STATE_DOWNLOADING:  
 -                 button.setText((int) (mProgress * 100) + "%");  
 -                 break;  
 -             case DownloadManager.STATE_DOWNLOADED:  
 -                 button.setText(R.string.app_state_downloaded);  
 -                 break;  
 -   
 -   
 -   
 -             default:  
 -                 break;  
 -             }  
 -         }  
 -     }  
 - }  
 
    里面代码有点多,那就看startObserver()方法做了什么。
- public void startObserver() {  
 -        DownloadManager.getInstance().registerObserver(this);  
 -    }  
 
这里 是 注冊了observer, Observer 是什么东西?在DownloadManager 中我们定义了 
public interface DownloadObserver {
    public void onDownloadStateChanged(DownloadInfo info);
    public void onDownloadProgressed(DownloadInfo info);
}
    一个接口,里面有两个抽象方法 一个是 进度。还有一个是下载状态。 那回过头来,屡一下。 我们在 下载的关键代码里面调用了 
    DownloadObserver onDownloadProgressed() 
    DownloadObserver.onDownloadStateChanged()
    两个抽象方法,而我们在 adapter中实现了 这两个方法 就能够轻松的控制 去 刷新 和改变 下载状态了。
- @Override  
 -   public void onDownloadStateChanged(DownloadInfo info) {  
 -       refreshHolder(info);  
 -   }  
 -   
 -   @Override  
 -   public void onDownloadProgressed(DownloadInfo info) {  
 -       refreshHolder(info);  
 -   
 -   }  
 
    细心的朋友 也许 发现问题了,对,我们还没有注冊Observer,就在 DownloadManager 中去调用了。 
这里 在看下DownloadManager 中 调用的方法
/** 当下载状态发送改变的时候回调 */
public void notifyDownloadStateChanged(DownloadInfo info) {
    synchronized (mObservers) {
        for (DownloadObserver observer : mObservers) {
            observer.onDownloadStateChanged(info);
        }
    }
}
/** 当下载进度发送改变的时候回调 */
public void notifyDownloadProgressed(DownloadInfo info) {
    synchronized (mObservers) {
        for (DownloadObserver observer : mObservers) {
            observer.onDownloadProgressed(info);
        }
    }
}    是的。这里我们遍历一个observer容器。然后去刷新 。所以我们还须要把Observer对象加入到集合mObservers中,所以肯定有这样一个方法将observer加入到集合中 。 
/* 注冊观察者 / 
public void registerObserver(DownloadObserver observer) { 
synchronized (mObservers) { 
if (!mObservers.contains(observer)) { 
mObservers.add(observer); 
} 
} 
}
/** 反注冊观察者 */
public void unRegisterObserver(DownloadObserver observer) {
    synchronized (mObservers) {
        if (mObservers.contains(observer)) {
            mObservers.remove(observer);
        }
    }
}
     所以最后一步,由于 adapter 方法中有 startObserver, 所以 我们在 主界面 MainActivity 的类中调用 adapter.startObser() 将 实现了 接口的adapter 对象 加入到 Observer 容器中 就能够了。
    OK。大功告成。
=============================================
DownloadManager 代码
    这里 贴一下DownloadManager 代码
- public class DownloadManager {  
 -     public static final int STATE_NONE = 0;  
 -       
 -     public static final int STATE_WAITING = 1;  
 -       
 -     public static final int STATE_DOWNLOADING = 2;  
 -       
 -     public static final int STATE_PAUSED = 3;  
 -       
 -     public static final int STATE_DOWNLOADED = 4;  
 -       
 -     public static final int STATE_ERROR = 5;  
 -   
 -       
 -   
 -     private static DownloadManager instance;  
 -   
 -     private DownloadManager() {  
 -     }  
 -   
 -       
 -     private Map<Long, DownloadInfo> mDownloadMap = new ConcurrentHashMap<Long, DownloadInfo>();  
 -       
 -     private List<DownloadObserver> mObservers = new ArrayList<DownloadObserver>();  
 -       
 -     private Map<Long, DownloadTask> mTaskMap = new ConcurrentHashMap<Long, DownloadTask>();  
 -   
 -     public static synchronized DownloadManager getInstance() {  
 -         if (instance == null) {  
 -             instance = new DownloadManager();  
 -         }  
 -         return instance;  
 -     }  
 -   
 -       
 -     public void registerObserver(DownloadObserver observer) {  
 -         synchronized (mObservers) {  
 -             if (!mObservers.contains(observer)) {  
 -                 mObservers.add(observer);  
 -             }  
 -         }  
 -     }  
 -   
 -       
 -     public void unRegisterObserver(DownloadObserver observer) {  
 -         synchronized (mObservers) {  
 -             if (mObservers.contains(observer)) {  
 -                 mObservers.remove(observer);  
 -             }  
 -         }  
 -     }  
 -   
 -       
 -     public void notifyDownloadStateChanged(DownloadInfo info) {  
 -         synchronized (mObservers) {  
 -             for (DownloadObserver observer : mObservers) {  
 -                 observer.onDownloadStateChanged(info);  
 -             }  
 -         }  
 -     }  
 -   
 -       
 -     public void notifyDownloadProgressed(DownloadInfo info) {  
 -         synchronized (mObservers) {  
 -             for (DownloadObserver observer : mObservers) {  
 -                 observer.onDownloadProgressed(info);  
 -             }  
 -         }  
 -     }  
 -   
 -       
 -     public synchronized void download(AppInfo appInfo) {  
 -           
 -         DownloadInfo info = mDownloadMap.get(appInfo.getId());  
 -         if (info == null) {  
 -             info = DownloadInfo.clone(appInfo);  
 -             mDownloadMap.put(appInfo.getId(), info);  
 -         }  
 -           
 -         if (info.getDownloadState() == STATE_NONE  
 -                 || info.getDownloadState() == STATE_PAUSED  
 -                 || info.getDownloadState() == STATE_ERROR) {  
 -               
 -             info.setDownloadState(STATE_WAITING);  
 -             notifyDownloadStateChanged(info);  
 -             DownloadTask task = new DownloadTask(info);  
 -             mTaskMap.put(info.getId(), task);  
 -             ThreadManager.getDownloadPool().execute(task);  
 -         }  
 -     }  
 -   
 -       
 -     public synchronized void pause(AppInfo appInfo) {  
 -         stopDownload(appInfo);  
 -         DownloadInfo info = mDownloadMap.get(appInfo.getId());  
 -         if (info != null) {  
 -             info.setDownloadState(STATE_PAUSED);  
 -             notifyDownloadStateChanged(info);  
 -         }  
 -     }  
 -   
 -       
 -     public synchronized void cancel(AppInfo appInfo) {  
 -         stopDownload(appInfo);  
 -         DownloadInfo info = mDownloadMap.get(appInfo.getId());  
 -         if (info != null) {  
 -             info.setDownloadState(STATE_NONE);  
 -             notifyDownloadStateChanged(info);  
 -             info.setCurrentSize(0);  
 -             File file = new File(info.getPath());  
 -             file.delete();  
 -         }  
 -     }  
 -   
 -       
 -     public synchronized void install(AppInfo appInfo) {  
 -         stopDownload(appInfo);  
 -         DownloadInfo info = mDownloadMap.get(appInfo.getId());  
 -         if (info != null) {  
 -             Intent installIntent = new Intent(Intent.ACTION_VIEW);  
 -             installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
 -             installIntent.setDataAndType(Uri.parse("file://" + info.getPath()),  
 -                     "application/vnd.android.package-archive");  
 -             AppUtil.getContext().startActivity(installIntent);  
 -         }  
 -         notifyDownloadStateChanged(info);  
 -     }  
 -   
 -       
 -     public synchronized void open(AppInfo appInfo) {  
 -         try {  
 -             Context context = AppUtil.getContext();  
 -               
 -             Intent intent = context.getPackageManager()  
 -                     .getLaunchIntentForPackage(appInfo.getPackageName());  
 -             context.startActivity(intent);  
 -         } catch (Exception e) {  
 -         }  
 -     }  
 -   
 -       
 -     private void stopDownload(AppInfo appInfo) {  
 -         DownloadTask task = mTaskMap.remove(appInfo.getId());  
 -         if (task != null) {  
 -             ThreadManager.getDownloadPool().cancel(task);  
 -         }  
 -     }  
 -   
 -       
 -     public synchronized DownloadInfo getDownloadInfo(long id) {  
 -         return mDownloadMap.get(id);  
 -     }  
 -   
 -     public synchronized void setDownloadInfo(long id, DownloadInfo info) {  
 -         mDownloadMap.put(id, info);  
 -     }  
 -   
 -       
 -     public class DownloadTask implements Runnable {  
 -         private DownloadInfo info;  
 -   
 -         public DownloadTask(DownloadInfo info) {  
 -             this.info = info;  
 -         }  
 -   
 -         @Override  
 -         public void run() {  
 -             info.setDownloadState(STATE_DOWNLOADING);  
 -             notifyDownloadStateChanged(info);  
 -             File file = new File(info.getPath());  
 -             HttpResult httpResult = null;  
 -             InputStream stream = null;  
 -             if (info.getCurrentSize() == 0 || !file.exists()  
 -                     || file.length() != info.getCurrentSize()) {  
 -                   
 -   
 -                 info.setCurrentSize(0);  
 -                 file.delete();  
 -             }  
 -             httpResult = HttpHelper.download(info.getUrl());  
 -               
 -               
 -               
 -               
 -               
 -             if (httpResult == null  
 -                     || (stream = httpResult.getInputStream()) == null) {  
 -                 info.setDownloadState(STATE_ERROR);  
 -                 notifyDownloadStateChanged(info);  
 -             } else {  
 -                 try {  
 -                     skipBytesFromStream(stream, info.getCurrentSize());  
 -                 } catch (Exception e1) {  
 -                     e1.printStackTrace();  
 -                 }  
 -   
 -                 FileOutputStream fos = null;  
 -                 try {  
 -                     fos = new FileOutputStream(file, true);  
 -                     int count = -1;  
 -                     byte[] buffer = new byte[1024];  
 -                     while (((count = stream.read(buffer)) != -1)  
 -                             && info.getDownloadState() == STATE_DOWNLOADING) {  
 -                           
 -                         fos.write(buffer, 0, count);  
 -                         fos.flush();  
 -                         info.setCurrentSize(info.getCurrentSize() + count);  
 -                         notifyDownloadProgressed(info);  
 -                     }  
 -                 } catch (Exception e) {  
 -                     info.setDownloadState(STATE_ERROR);  
 -                     notifyDownloadStateChanged(info);  
 -                     info.setCurrentSize(0);  
 -                     file.delete();  
 -                 } finally {  
 -                     IOUtils.close(fos);  
 -                     if (httpResult != null) {  
 -                         httpResult.close();  
 -                     }  
 -                 }  
 -   
 -                   
 -                 if (info.getCurrentSize() == info.getAppSize()) {  
 -                     info.setDownloadState(STATE_DOWNLOADED);  
 -                     notifyDownloadStateChanged(info);  
 -                 } else if (info.getDownloadState() == STATE_PAUSED) {  
 -                     notifyDownloadStateChanged(info);  
 -                 } else {  
 -                     info.setDownloadState(STATE_ERROR);  
 -                     notifyDownloadStateChanged(info);  
 -                     info.setCurrentSize(0);  
 -                     file.delete();  
 -                 }  
 -             }  
 -             mTaskMap.remove(info.getId());  
 -         }  
 -     }  
 -   
 -     public interface DownloadObserver {  
 -   
 -         public abstract void onDownloadStateChanged(DownloadInfo info);  
 -   
 -         public abstract void onDownloadProgressed(DownloadInfo info);  
 -     }  
 -   
 -       
 -     private long skipBytesFromStream(InputStream inputStream, long n) {  
 -         long remaining = n;  
 -           
 -         int SKIP_BUFFER_SIZE = 10000;  
 -           
 -         byte[] skipBuffer = null;  
 -         int nr = 0;  
 -         if (skipBuffer == null) {  
 -             skipBuffer = new byte[SKIP_BUFFER_SIZE];  
 -         }  
 -         byte[] localSkipBuffer = skipBuffer;  
 -         if (n <= 0) {  
 -             return 0;  
 -         }  
 -         while (remaining > 0) {  
 -             try {  
 -                 long skip = inputStream.skip(10000);  
 -                 nr = inputStream.read(localSkipBuffer, 0,  
 -                         (int) Math.min(SKIP_BUFFER_SIZE, remaining));  
 -             } catch (IOException e) {  
 -                 e.printStackTrace();  
 -             }  
 -             if (nr < 0) {  
 -                 break;  
 -             }  
 -             remaining -= nr;  
 -         }  
 -         return n - remaining;  
 -     }  
 - }  
 
    有两点 须要说明。关于 点击暂停后。再继续下载 有两种方式能够实现
    第一种 点击暂停的时候 记录下载了 多少,然后 再点击 继续下载 时,告诉服务器, 让服务器接着 上次的数据 往本地传递,
    代码 就是 我们 DownloadTask 下载时候,推断一下
-   
 -             httpResult = HttpHelper.download(info.getUrl() + "&range=" + info.getCurrentSize());  
 
     通过 range 来区分 当前的下载size.    服务器 处理的代码 也非常easy 就是一句话
    String range = req.getParameter(“range”); 拿到 range 推断 range 存在不存在。 
    假设不存在
- FileInputStream stream = new FileInputStream(file);  
 -           int count = -1;  
 -           byte[] buffer = new byte[1024];  
 -           while ((count = stream.read(buffer)) != -1) {  
 -               SystemClock.sleep(20);  
 -               out.write(buffer, 0, count);  
 -               out.flush();  
 -           }  
 -           stream.close();  
 -           out.close();  
 
  如果存在 那么跳过range 个字节
- RandomAccessFile raf = new RandomAccessFile(file, "r");  
 -             raf.seek(Long.valueOf(range));    
 -             int count = -1;  
 -             byte[] buffer = new byte[1024];  
 -             while ((count = raf.read(buffer)) != -1) {  
 -                 SystemClock.sleep(10);  
 -                 out.write(buffer, 0, count);  
 -                 out.flush();  
 -             }  
 -             raf.close();  
 -             out.close();  
 
    还有一种方式是本地处理,这个demo 中就是本地处理的, 可是有一个问题。 由于 Java api的原因 。inputStream.skip() 方法 并不能准确的 跳过多少个字节。
而是 小于你想要跳过的字节,所以 你要去遍历 一直到 满足你要跳过的字节 在继续写。 由于 这个方案有一个缺点。就是在下载非常大的文件,
比方文件大小20M ,当已经下载了15M 此时你去暂停。在继续下载,那么要跳过前面的15M 将会话费非常多时间。
    所以这个仅限于学习。实际中 假设要下载大的文件。不能用这个方案。
完美版 过几天 再发。
    代码下载 : 
    AndroidStudio 版 
    Eclipse 版
-------------------------------------------各级格机格机格机--------------------------------------
-------------------------------改进版 :点击打开链接------------------------