美文网首页Android
android多文件上传或者下载框架

android多文件上传或者下载框架

作者: NoBugException | 来源:发表于2018-12-10 20:41 被阅读44次

    最近我看到一个老项目的代码,上传多个文件尽然用了让我忍无可忍的递归操作,即一个文件上传成功之后另一个文件才开始下载,而且还没有进度展示。
    下面是本人整理的框架效果:


    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>
    

    以上就是全部代码了。

    相关文章

      网友评论

        本文标题:android多文件上传或者下载框架

        本文链接:https://www.haomeiwen.com/subject/rxgdhqtx.html