編輯:關於Android編程
不管是開發android應用程序還是java應用程序,異步任務都是經常用到的,尤其是android本身做為線程不安全,只要稍微耗時的操作都要用到異步任務,而無論是java還是android通用的異步任務開發以前無非就是利用Thread和Runnable來實現, android系統本身還有屬於他自己的AsyncTask去專門處理異步任務.但其實這些都不是最高效的異步任務處理方法,尤其是任務有多個的情況下,以上幾種方法都需要後台不停的去創建新的線程,並且要求我們自己去管理好線程的生命周期,否則很容易造成內存洩露.
而從 jdk1.5以後,我們可以使用線程池去高效的創建多個異步任務的同時,還不需要自己去管理線程的生命周期了.我們只需要專注於異步任務的業務邏輯代碼和在適當的時候將線程池整體關閉,可以大大的提高整個應用的性能.
下面就來先看下線程池相關的一些經常要用到的類,這些類都包括:Executor, ExecutorService, AbstractExecutorService,ThreadPoolExecutorService,ScheduledExecutirService, Callable, Runnable等,常用到的相關類就是以上幾個.下面我們來分析一下這些類的作用.
1.Executor, 一個接口,只提供了一個方法executor(Runnable command);提供了線程池最基本的功能,執行異步任務.
2.ExecutorService,也是接口,繼承了Executor接口,並擴展了一些線程池應該具有的生命周期方法,源碼(部分)如下:
public interface ExecutorService extends Executor { /** * 作用:關閉線程池,不會停止已有的任務,但不能再向其中添加新任務. */ void shutdown(); /** * * @return list of tasks that never commenced execution * 作用:立馬關閉整個線程池,池中任務也一並停止. */ ListshutdownNow(); boolean isShutdown(); /** * 作用:向線程池中添加一個Callable任務. */ Future submit(Callable task); /** * * 作用:向線程池中添加一個Runnable任務.*/Future submit(Runnable task, T result); Futuresubmit(Runnable task); }
3.AbstractExecutorService,線程池抽象類,提供了所有線程池類的基本實現,部分代碼如下:
public abstract class AbstractExecutorService implements ExecutorService { /** * 將Runnable任務轉化為RunnableFutrue任務 * */ protectedRunnableFuture newTaskFor(Runnable runnable, T value) { return new FutureTask (runnable, value); } /** * 將Callable任務轉化為RunnableFutrue任務 * */ protectedRunnableFuture newTaskFor(Callable callable) { return new FutureTask (callable); } /** * 向線程池中添加一個Runnable任務,會在內部將任務轉化為RunnableFuture任務 * */ public Future submit(Runnable task) { if (task == null) throw new NullPointerException(); RunnableFutureftask = newTaskFor(task, null); execute(ftask); return ftask; } public Future submit(Runnable task, T result) { if (task == null) throw new NullPointerException(); RunnableFuture ftask = newTaskFor(task, result); execute(ftask); return ftask; } /** * 向線程池中添加一個Callable任務,會在內部將任務轉化為RunnableFuture任務 * */
publicFuture submit(Callable task) { if (task == null) throw new NullPointerException(); RunnableFuture ftask = newTaskFor(task); execute(ftask); return ftask; }} 通過閱讀源碼可以知道:線程中處理的任務最終都是FutureTask類型的.
3.Executors,通過提供一系列的static方法,創建不同類型的線程池.源碼不再拷貝.
以上這些類基本構成了java線程池的整個框架,利用這幾個類,可以使我們輕松的實現線程池的異步任務.下面以一個Demo來講解基本的用法.
最近有一個需求是這樣的:從服務器下載體積較大的zip包到本地客戶端中.並通過Notifycation通知用戶文件下載的進度.思路:要從服務器下載東西,啟動一個專門用來下載的Service,在Service中通過線程池開啟異步下載任務並創建下載過程中不同狀態的回調接口,用以通知用戶下載進度.本Demo中為了實現上的方便,先實現了將文件從一個路徑拷貝到另一個路徑來模擬從服務器下載文件.(原理是一樣的,下載文件即相當於從服務器拷貝一個文件到本地路徑).
下面看一下整個工程的結構:
各個類的作用:
1. CopyTask,專門用來實現文件拷貝功能的類,沒有其它任務業務.代碼如下:
package copy; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; /** * @author rzq * @functuion android SD卡文件復制任務類 */ public class CopyTask implements Runnable { /** * 要拷貝的文件路徑 */ private String sourceFilePath; private File sourceFile; /** * 目的地址文件 */ private String destationFilePath; private File destationFile; /** * 復制過程狀態回調 */ private IDownloadListener downlaodListener; private long fileContentLength; private long currentLenght = 0; public CopyTask(String sourceFilePath, String destationFilePath, IDownloadListener downloadListener) { this.sourceFilePath = sourceFilePath; this.destationFilePath = destationFilePath; this.downlaodListener = downloadListener; } private boolean prepare() { sourceFile = new File(sourceFilePath); fileContentLength = sourceFile.length(); /** * 文件長度大於0,則准備好了 */ if (fileContentLength > 0) { destationFile = new File(destationFilePath); downlaodListener.onPrepared(fileContentLength); return true; } return false; } @Override public void run() { if (prepare()) { /** * 文件准備好後開始拷貝 */ RandomAccessFile randomAccessFile = null; FileInputStream in = null; try { in = new FileInputStream(sourceFile); byte[] buffer = new byte[2048]; int length = -1; randomAccessFile = new RandomAccessFile(destationFile, rwd); while (((length = in.read(buffer)) != -1)) { randomAccessFile.write(buffer, 0, length); currentLenght += length; downlaodListener.onProgressChanged((int) (currentLenght / fileContentLength * 100)); if (currentLenght == fileContentLength) { downlaodListener.onFinished((int) currentLenght); } } } catch (FileNotFoundException e1) { downlaodListener.onFailure(); e1.printStackTrace(); } catch (IOException e2) { downlaodListener.onFailure(); e2.printStackTrace(); } finally { try { in.close(); randomAccessFile.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }2.CopyManager類,用來負責創建線程池並向其中添加任務.代碼如下:
package copy; import java.lang.ref.WeakReference; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; public class CopyManager { private static CopyManager manager; private CopyTask copyTask; private ThreadPoolExecutor threadPool; private CopyManager() { threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool(); } static { manager = new CopyManager(); } public static CopyManager getInstance() { return manager; } public void startCopyFile(String sourceFile, String destiationFile, IDownloadListener listener) { copyTask = new CopyTask(sourceFile, destiationFile, listener); Future request = threadPool.submit(copyTask); new WeakReference3.IDownloadListener,監聽不同狀態下不同的回調執行.代碼如下:>(request); } }
package copy; public interface IDownloadListener { /** * 開始請求的回調 */ public void onStarted(); /** * 請求成功,下載前的准備回調 * * @param contentLength * 文件長度 * @param downloadUrl * 下載地址 */ public void onPrepared(long contentLength); /** * 正在下載,更新進度的回調 * * @param progress * 當前下載進度 * @param completeSize * 已下載完成長度 * @param downloadUrl * 下載地址 */ public void onProgressChanged(int progress); /** * 下載過程中暫停的回調 * * @param completeSize * @param downloadUrl */ public void onPaused(int progress, int completeSize); /** * 下載完成的回調 */ public void onFinished(int completeSize); /** * 下載失敗的回調 */ public void onFailure(); }4.CopyService,文件下載服務,通過調用CopyManager去開始下載任務.不再貼源碼,稍後會將整個Demo源碼上傳.
Android圓形圖片控件效果圖如下: 代碼如下: RoundImageView.java package com.dxd.roundimageview; imp
在Android開發中;Activity之間傳遞參數是常見的事;如果我們要在Activity之間傳遞圖片;1。MainActivity中包括一個ImageView;當我們
前言在前2篇文章中,我們都說到著色器,且在第二篇中正式說到,這著色器只能用在OpenGL ES2.x等可編程管道裡面,而在OpenGL ES1.x是不能用的。但我們一直沒
什麼是AIDL以及如何使用 ①aidl是Android interface definition Language 的英文縮寫,意思Android 接口定義語言。 ②使用