废话不多,直接上源码
自定义一个Adapter
public class MyAdapter extends BaseAdapter {
private Context context;
private List<Progress> list;
private Object lockobj = new Object();//对象锁
private int complteTask = 0;//当前完成下载任务的数量
private DownloadCompleteCall mCallback;//所有下载任务完成的回调方法
public interface DownloadCompleteCall {
void downloadComplete();
}
public MyAdapter(Context context, List<Progress> list, DownloadCompleteCall mCallback) {
this.context = context;
this.list = list;
this.mCallback = mCallback;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.progress_layout, null);
viewHolder = new ViewHolder();
viewHolder.progressBar = (ProgressBar) convertView.findViewById(R.id.progress);
viewHolder.textView = (TextView) convertView.findViewById(R.id.progress_text);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
Progress curProgress = (Progress) getItem(position);
viewHolder.textView.setText("任务" + position + ":" + curProgress.getProgress() + "%");
viewHolder.progressBar.setProgress(curProgress.getProgress());
return convertView;
}
public void update(int proBarIndex, int result) {
if (proBarIndex < 0 || proBarIndex >= list.size()) {
return;
}
Progress curPro = list.get(proBarIndex);
curPro.setProgress(result);
if (result == 100) {
complteTask++;
}
if (complteTask == list.size()) {
mCallback.downloadComplete();//如果完成的任务数等于总数,说明下载完成,回调
}
notifyDataSetChanged();
}
//获取任务列表中第一个没有在运行的任务
public int getProBarIndex() {
synchronized (lockobj) {
for (int i = 0; i < list.size(); i++) {
if (!list.get(i).isRunning()) {
list.get(i).setRunning(true);
return i;
}
}
}
return -1;
}
class ViewHolder {
TextView textView;
ProgressBar progressBar;
}
}
帮助类:
public class Progress {
private int index;
private int progress;
private boolean running;
public Progress(int index, int progress, boolean running) {
this.index = index;
this.progress = progress;
this.running = running;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
this.progress = progress;
}
public boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
}
主界面:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="模拟同时下载线程数:"/>
<EditText
android:hint="默认3个"
android:id="@+id/countEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
<Button
android:id="@+id/start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="应用"/>
<ListView
android:id="@+id/listview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
</ListView>
</LinearLayout>
MainActivity代码
public class MainActivity extends Activity implements MyAdapter.DownloadCompleteCall {
private final static int DEFAULT_DOWNLOAD_CONTHREAD = 3;//默认并发线程为3
private final static int DEFAULT_DOWNLOAD_SUM = 20;//下载任务总数
private final static int ACTION_UPDATE_PROGRESS = 0;
private final static int ACTION_START_DOWNLOAD = 1;
@Bind(R.id.countEditText)
EditText countEditText;
@Bind(R.id.listview)
ListView listview;
private MyAdapter myAdapter;
private int conThread;
private boolean hasRunning = false;
ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "DownloadTask#" + mCount.getAndIncrement());//线程的名称
}
};
BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128);//队列最多接收128个任务的缓存
private ExecutorService threadPool;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == ACTION_START_DOWNLOAD) {
startDownload(conThread);//开始模拟下载
} else if (msg.what == ACTION_UPDATE_PROGRESS) {
myAdapter.update(msg.arg1, msg.arg2);//更新adapter
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initListView();
}
private void initListView() {
List<Progress> progresses = new ArrayList<Progress>();
for (int i = 0; i < DEFAULT_DOWNLOAD_SUM; i++) {
Progress progress = new Progress(i, 0, false);
progresses.add(progress);
}
myAdapter = new MyAdapter(this, progresses, this);
listview.setAdapter(myAdapter);
}
@OnClick(R.id.start)
void setThread() {
if (hasRunning) {
return;
}
conThread = DEFAULT_DOWNLOAD_CONTHREAD;
try {
conThread = Integer.parseInt(countEditText.getText().toString());
if (conThread > DEFAULT_DOWNLOAD_SUM) {
conThread = DEFAULT_DOWNLOAD_SUM;
} else if (conThread < 0) {
conThread = DEFAULT_DOWNLOAD_CONTHREAD;
}
} catch (Exception e) {
e.printStackTrace();
}
hasRunning = true;
handler.sendEmptyMessage(ACTION_START_DOWNLOAD);
}
private void startDownload(int conThread) {
if (threadPool != null) {
threadPool.shutdown();
threadPool = null;
}
//此时conThread个线程并发,如果还有任务进来,就放入sPoolWorkQueue队列中等待运行
threadPool = new ThreadPoolExecutor(conThread, conThread, 0, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
for (int i = 0; i < DEFAULT_DOWNLOAD_SUM; i++) {
threadPool.execute(new Runnable() {
@Override
public void run() {
int result = 0;
int proBarIndex = myAdapter.getProBarIndex();
while (true) {
try {
//result等于100的时候,结束该下载任务
if (result == 100) {
break;
}
int sleepTime = (int) (Math.random() * 1000);
Thread.sleep(sleepTime);
result += 10;
Message msg = new Message();
msg.what = ACTION_UPDATE_PROGRESS;
msg.arg1 = proBarIndex;
msg.arg2 = result;
handler.sendMessage(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
//shutDownThreadPool();如果想要back键退出应用,仍后台下载,注释该行
}
return super.onKeyDown(keyCode, event);
}
@Override
public void downloadComplete() {
shutDownThreadPool();//下载完成之后,关闭线程池,可以看到所有下载任务完成之后,并行的线程DownloadTask#1到3,就结束了
}
private void shutDownThreadPool(){
if (threadPool != null) {
threadPool.shutdown();
}
}
}
实际运行效果: 此时设置了并行下载线程为10个。。。
分析:见代码注释
更多线程池的知识 Android AsyncTask原理以及线程池概念
源码下载:/PoolSimulateDownloadTask