最近我看到一个老项目的代码,上传多个文件尽然用了让我忍无可忍的递归操作,即一个文件上传成功之后另一个文件才开始下载,而且还没有进度展示。
下面是本人整理的框架效果:
23.gif
(1)开启一个线程池,只允许同时三个线程同时进行,当一个线程执行完毕时排队等待的线程将进入线程池;
(2)图中三个线程的进度是一样的,因为代码中写死了,正常上传或者下载框架中都会有类似onLoading的方法,利用返回值计算出合理的进度;
(3)demo的代码也许没有最优化,可以根据自己的需求调整代码,使代码更加完善;
下面粘贴下代码:
MultiUploadActivity.java
package com.jiangxi.login.miltilyupload;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
public class MultiUploadActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private MultiAdapter dzAdapter;
private volatile boolean isRunning=false;//判断线程池是否运行 标志位
private UploadUtil mUploadUtil;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_multiupload);
recyclerView = findViewById(R.id.recycler_view);
//上传文件工具类
mUploadUtil=new UploadUtil();
final ArrayList<UploadBean> list = new ArrayList<>();
list.add(new UploadBean(0, (byte) 0));
list.add(new UploadBean(0, (byte) 0));
list.add(new UploadBean(0, (byte) 0));
list.add(new UploadBean(0, (byte) 0));
list.add(new UploadBean(0, (byte) 0));
list.add(new UploadBean(0, (byte) 0));
list.add(new UploadBean(0, (byte) 0));
list.add(new UploadBean(0, (byte) 0));
list.add(new UploadBean(0, (byte) 0));
list.add(new UploadBean(0, (byte) 0));
list.add(new UploadBean(0, (byte) 0));
list.add(new UploadBean(0, (byte) 0));
list.add(new UploadBean(0, (byte) 0));
dzAdapter = new MultiAdapter(this, list);
recyclerView.setLayoutManager(new GridLayoutManager(MultiUploadActivity.this, 2));
recyclerView.setHasFixedSize(false);
recyclerView.setAdapter(dzAdapter);
mUploadUtil.setOnUploadListener(new OnUploadListener() {
@Override
public void onAllSuccess() {
isRunning=false;
}
@Override
public void onAllFailed() {
isRunning=false;
}
@Override
public void onThreadProgressChange(int position, int percent) {
list.get(position).setStatus((byte) 1);
list.get(position).setUploadProgress(percent);
dzAdapter.setDatas(list);
dzAdapter.notifyItemChanged(position, list.get(position));
}
@Override
public void onThreadFinish(int position) {
list.get(position).setStatus((byte) 2);
dzAdapter.setDatas(list);
dzAdapter.notifyItemChanged(position, list.get(position));
}
@Override
public void onThreadInterrupted(int position) {
list.get(position).setStatus((byte) 3);
dzAdapter.setDatas(list);
dzAdapter.notifyItemChanged(position);
}
});
if(!isRunning){
startUpload(list);//开始上传
}else{
mUploadUtil.shutDownNow();//中断所有线程的执行
}
}
private void startUpload(ArrayList<UploadBean> list){
isRunning=true;
mUploadUtil.submitAll(MultiUploadActivity.this, list);
}
}
MultiAdapter.java
package com.jiangxi.login.miltilyupload;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
public class MultiAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<UploadBean> mData;
private Context mContext;
private OnItemClickLitener mOnItemClickLitener;
public MultiAdapter(Context context, List<UploadBean> mData) {
this.mContext = context;
this.mData = mData;
}
@Override
public int getItemViewType(int position) {
//防止滑动时图片混乱的问题
return position;
}
/**
* 设置
* @param mData
*/
public void setDatas(List<UploadBean> mData){
this.mData = mData;
}
@Override
public int getItemCount() {
return mData != null ? mData.size() : 0;
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) {
onBindViewHolder(holder, position);
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
UploadBean dataListBean = mData.get(position);
dealUploadText(((ViewHolder) holder).tv_present, dataListBean);
//如果设置了回调,则设置点击事件
holder.itemView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mOnItemClickLitener != null) {
if(mData != null && mData.size() > 0){
mOnItemClickLitener.onItemClick(holder.itemView, position);
}
}
}
});
}
/**
* 处理进度条文本
* @param tv_present
* @param dataListBean
*/
private void dealUploadText(TextView tv_present, UploadBean dataListBean){
if(dataListBean == null){
return;
}
if(dataListBean.getStatus() == 1){
//如果正在上传中
tv_present.setVisibility(View.VISIBLE);
tv_present.setText("上传进度:"+dataListBean.getUploadProgress() + "%");
}else if(dataListBean.getStatus() == 2){
tv_present.setVisibility(View.VISIBLE);
tv_present.setText("上传完成");
}else if(dataListBean.getStatus() == 3){
tv_present.setVisibility(View.VISIBLE);
tv_present.setText("上传失败");
}else {
tv_present.setVisibility(View.GONE);
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(mContext).inflate(R.layout.upload_item, parent, false);
ViewHolder holder = new ViewHolder(itemView);
return holder;
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView tv_present;
public ViewHolder(View itemView) {
super(itemView);
tv_present = itemView.findViewById(R.id.tv_present);
}
}
public interface OnItemClickLitener {
void onItemClick(View view, int position);
}
public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener) {
this.mOnItemClickLitener = mOnItemClickLitener;
}
}
UploadBean.java
package com.jiangxi.login.miltilyupload;
public class UploadBean {
private int uploadProgress;// 上传进度
private byte status;//0:默认 1:正在上传 2:上传完成 3:上传失败
public UploadBean(int uploadProgress, byte status) {
this.uploadProgress = uploadProgress;
this.status = status;
}
public int getUploadProgress() {
return uploadProgress;
}
public void setUploadProgress(int uploadProgress) {
this.uploadProgress = uploadProgress;
}
public byte getStatus() {
return status;
}
public void setStatus(byte status) {
this.status = status;
}
}
UploadUtil.java(在任何时候都要养成写工具类的习惯)
package com.jiangxi.login.miltilyupload;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class UploadUtil {
//线程进度回调
private final static int THREAD_PROGRESS_CODE=100;
//线程完成
private final static int THREAD_FINISH_CODE=101;
//线程被中断
private final static int THREAD_INTERRUPT_CODE=102;
//所有线程完成
private final static int THREAD_ALL_SUCCESS_CODE=103;
//所有线程执行失败
private final static int THREAD_ALL_FAILED_CODE=104;
//handler传递进度值
private final static String THREAD_PERCENT="THREAD_PERCENT";
//handler传递position值
private final static String THREAD_POSITION="THREAD_POSITION";
//线程池核心数
private int threadCore=3;
//线程池
private ExecutorService executor;
//成功数量
int successCount = 0;
//失败数量
int failedCount = 0;
private OnUploadListener uploadListener;
private UploadHandler handler;
public UploadUtil(){
init();
}
public UploadUtil(int threadCore){
this.threadCore=threadCore;
init();
}
public void setOnUploadListener(OnUploadListener uploadListener){
this.uploadListener=uploadListener;
}
public void init(){
handler=new UploadHandler(this);
successCount = 0;
failedCount = 0;
}
public void shutDownNow(){
//中断所有线程的执行
executor.shutdownNow();
}
public void submitAll(Activity mContext, final ArrayList<UploadBean> list){
executor = Executors.newFixedThreadPool(threadCore);
int i = 0;
//遍历文件
for (UploadBean uploadBean : list) {
final Bundle bundle=new Bundle();
bundle.putInt(THREAD_POSITION,i);
i++;
executor.submit(new UploadFile(mContext,i, list, new OnThreadResultListener(){
@Override
public void onProgressChange(final int percent) {
bundle.putInt(THREAD_PERCENT,percent);
Message.obtain(handler,THREAD_PROGRESS_CODE,bundle).sendToTarget();
}
@Override public void onFinish() {
successCount++;
if(successCount == list.size()){
successCount = 0;
failedCount = 0;
handler.sendEmptyMessage(THREAD_ALL_SUCCESS_CODE);
}
Message.obtain(handler,THREAD_FINISH_CODE,bundle).sendToTarget();
}
@Override public void onInterrupted() {
failedCount++;
if(successCount + failedCount == list.size()){
successCount = 0;
failedCount = 0;
handler.sendEmptyMessage(THREAD_ALL_FAILED_CODE);
}
Message.obtain(handler,THREAD_INTERRUPT_CODE,bundle).sendToTarget();
}
}));
}
//关闭线程池
executor.shutdown();
}
private static class UploadHandler extends Handler {//静态内部类+弱引用防止内存泄漏
private WeakReference<UploadUtil> weakReference;
private UploadHandler(UploadUtil object){
super(Looper.getMainLooper());//执行在UI线程
weakReference=new WeakReference<>(object);
}
@Override public void handleMessage(Message msg){
UploadUtil uploadUtil=weakReference.get();
if(uploadUtil!=null){
Bundle data= (Bundle) msg.obj;
int position;
int percent;
switch (msg.what){
case THREAD_PROGRESS_CODE:
position=data.getInt(THREAD_POSITION);
percent=data.getInt(THREAD_PERCENT);
uploadUtil.uploadListener.onThreadProgressChange(position,percent);
break;
case THREAD_FINISH_CODE:
position=data.getInt(THREAD_POSITION);
uploadUtil.uploadListener.onThreadFinish(position);
break;
case THREAD_INTERRUPT_CODE:
position=data.getInt(THREAD_POSITION);
uploadUtil.uploadListener.onThreadInterrupted(position);
break;
case THREAD_ALL_SUCCESS_CODE:
uploadUtil.uploadListener.onAllSuccess();
break;
case THREAD_ALL_FAILED_CODE:
uploadUtil.uploadListener.onAllFailed(); break;
}
}
}
}
}
UploadFile.java
package com.jiangxi.login.miltilyupload;
import android.app.Activity;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CountDownLatch;
public class UploadFile implements Runnable {
private String fileName;//本地文件的参数:// 文件名
private OnThreadResultListener listener;//任务线程回调接口
private int percent=0;//进度
private Activity mContext;
private ArrayList<UploadBean> list;
int index = 0;
private CountDownLatch countDownLatch = new CountDownLatch(1);
public UploadFile(Activity mContext, int index, ArrayList<UploadBean> list, OnThreadResultListener listener){
this.list = list;
this.listener=listener;
this.mContext = mContext;
this.index = index;
}
@Override
public void run() {
//上传线程
final TimerTask task = new TimerTask() {
@Override
public void run() {
if(percent < 0){
listener.onInterrupted();
}else if(percent < 100){
percent += 1;
listener.onProgressChange(percent);
}else if(percent >= 100){
percent = 0;
this.cancel();
//继续执行线程
countDownLatch.countDown();
listener.onFinish();
}
}
};
Timer timer = new Timer();
timer.schedule(task, 1000, 100);
try {
//等待
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
OnThreadResultListener.java
package com.jiangxi.login.miltilyupload;
public interface OnThreadResultListener {
void onProgressChange(int percent);//进度变化回调
void onFinish();//线程完成时回调
void onInterrupted();//线程被中断回调
}
OnUploadListener.java
package com.jiangxi.login.miltilyupload;
public interface OnUploadListener {//主线程回调
void onAllSuccess();
void onAllFailed();
void onThreadProgressChange(int position,int percent);
void onThreadFinish(int position);
void onThreadInterrupted(int position);
}
upload_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp">
<TextView
android:id="@+id/tv_present"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="20sp"
android:visibility="visible"
android:text="准备开始"/>
</RelativeLayout>
以上就是全部代码了。
网友评论