• 一个类的阅读,分析


    阅读到这么个类:

    public class FileDownloadList {
    
        
        /**上下文*/
        private Context mContext;
        /**请求对象*/
        private BaseRequestLims fileRequest = null;
        /**进度条对话框*/
        private AlertDialog progressDialog = null;
        /**进度条控件变量*/
        private ProgressBar mProgress;
        /**百分比显示控件*/
        private TextView mProgressPercent;
        
        private File localFile = null;
        /**接收HttpHelper中获取到文件大小后发送的广播,确定文件大小*/
        private DownLoadReceiver receiver;
        /**文件大小*/
        private long fileLength = -1L;
        /**是否已注册广播标志*/
        private boolean castFlag = false;
        /**是否显示进度条标志*/
        private boolean showDialog = false;
        /**文件下载完的回调接口*/
        private Runnable mCallback = null;
        
      
        
        private Handler mHandler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                int tempSize = (int)localFile.length();
                if(tempSize < fileLength){                                            
                       //文件下载中
                    if(showDialog){                                                            
                      //显示了进度条的情况下,更新进度条
                        int progress = (int)((Double.valueOf(tempSize) / Double.valueOf(fileLength)) * 100);
                        mProgress.setProgress(tempSize);
                        mProgressPercent.setText(progress + "%");
                    }
                }else{                                                                                
                            //下载文件完毕
                    if(castFlag){//如已注册广播,注销广播
                            mContext.unregisterReceiver(receiver);
                            castFlag = false;
                    
                    }
                    if(showDialog){
                        mProgress.setProgress((int)fileLength);
                        mProgressPercent.setText("100%");
                        progressDialog.dismiss();
                    }
                    
                                  
                    if(mCallback != null){
                        try{
                            Thread.sleep(500);
                            mCallback.run();
                        }catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };
        
        /**
         * 构造器
         * @param activity
         */
    
        
        /**
         * 构造器
         * @param activity
         * @param showDialog  显示进度条标志
         */
        public FileDownloadList(Context context, boolean showDialog){
            mContext = context;
            this.showDialog = showDialog;
            fileRequest = new BaseRequestLims(context,ClientServiceType.FILE_DOWN);
            fileRequest.setMethodType(BaseRequestLims.METHOD_TYPE_POST);
            fileRequest.setContext(mContext);
            
            
        }
        
        
        
        public BaseRequestLims getFileRequest(){
            return fileRequest;
        }
        
        /**
         * 通过关联类型来下载文件
         * @param fileName 文件名称或文件在服务器上的相对路径加名称
         * @param saveDir 保存在本地的文件目录
         * @param saveName 保存在本地的文件名称
         * @param gllx 关联类型
         * @param callback 下载后的处理线程
         */
        public void downloadFile(String fileName, String saveDir, String saveName, Runnable callback){
            if(callback != null){
                mCallback = callback;
            }
            
            File saveDirFile = new File(saveDir);
            
            //judge the save dir path exist or not 
            if(!saveDirFile.exists()){
                saveDirFile.mkdirs();
            }
            localFile = new File(saveDir,saveName);
            
            if(localFile.isDirectory()){
                new AlertDialog.Builder(mContext).setTitle("提示").setMessage("the save file is directory").show();
                return;
            }
            if(fileRequest.getServiceType()==null){
                fileRequest.setServiceType(ClientServiceType.FILE_DOWN);
            }
            fileRequest.addParameter("fpath", fileName);
            fileRequest.addParameter("fname", saveName);
            fileRequest.setStreamPath(localFile.getAbsolutePath());
            fileRequest.setStream(true);
            if(localFile.exists()){
                if(localFile.length() == 0){
                    invokeFile(fileRequest);
                }else{
                    //文件存在直接打开
                    if(showDialog)
                        buildProgressDialog().show();
                    mHandler.sendMessage(mHandler.obtainMessage());
                }
            }else{
                invokeFile(fileRequest);
            }
        }
        
        /**
         * 进入文件下载子线程
         * @param request
         */
        private void invokeFile(final BaseRequestLims request){
            try{
                if(showDialog){
                    buildProgressDialog().show();
                }
                receiver = new DownLoadReceiver();
                IntentFilter filter = new IntentFilter();
                filter.addAction("SAVE_DOWNLOAD_FILE");
                mContext.registerReceiver(receiver, filter);
                castFlag = true;
                //下载的子线程
                new Thread(){
                    @Override
                    public void run() {
                        super.run();
                        HttpHelper.invoke(request);
                    }
                }.start();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        /**
         * 创建进度对话框
         * @return
         */
        private AlertDialog buildProgressDialog(){
            AlertDialog.Builder builder = new Builder(mContext);
            builder.setTitle("正在下载文件,请稍候...");
            RelativeLayout container = new RelativeLayout(mContext);
            mProgress = new ProgressBar(mContext);
            mProgress.setId("progress".hashCode());
            BeanUtils.setFieldValue(mProgress, "mOnlyIndeterminate", Boolean.valueOf(false));
            mProgress.setIndeterminate(false);
            LayerDrawable layerDrawable = (LayerDrawable)mContext.getResources().getDrawable(android.R.drawable.progress_horizontal);
            ClipDrawable clipDrawable = (ClipDrawable)layerDrawable.getDrawable(2);
            clipDrawable.setColorFilter(Color.parseColor("#32B5E5"), Mode.SRC_IN);
            mProgress.setProgressDrawable(layerDrawable);
            mProgress.setPadding(0, 0, 0, 0);
            mProgress.setIndeterminateDrawable(
                    mContext.getResources().getDrawable(android.R.drawable.progress_indeterminate_horizontal));
            mProgressPercent = new TextView(mContext);
            mProgressPercent.setId("percent".hashCode());
            mProgressPercent.setText("0%");
            mProgressPercent.setTextSize(18);
            
            int containerPadding = DimensionUtils.dip2Px(mContext, 10);
            container.setPadding(containerPadding, containerPadding, containerPadding, containerPadding);
            
            LayoutParams progressLayoutParams = new LayoutParams(
                    LayoutParams.MATCH_PARENT, DimensionUtils.dip2Px(mContext, 4));
            progressLayoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
            progressLayoutParams.addRule(RelativeLayout.LEFT_OF, mProgressPercent.getId());
            mProgress.setLayoutParams(progressLayoutParams);
            
            LayoutParams percentLayoutParams = new LayoutParams(
                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            percentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
            percentLayoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
            mProgressPercent.setLayoutParams(percentLayoutParams);
            
            container.addView(mProgressPercent);
            container.addView(mProgress);
            builder.setView(container);
            builder.setNegativeButton("取消", new OnClickListener() {    
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                }
            });
            
            progressDialog = builder.create();
            return progressDialog;
        }
        
        class DownLoadReceiver extends BroadcastReceiver{
            @Override
            public void onReceive(Context context, Intent intent) {
                //显示进度条
                fileLength = intent.getLongExtra("FILE_LENGTH", -1);
                if(showDialog){
                    mProgress.setMax((int)fileLength);
                }
                //更新进度条的线程
                new Thread(){
                    @Override
                    public void run() {
                        super.run();
                        while(true){
                            try{
                                Thread.sleep(500);
                            }catch (Exception e) {
                                e.printStackTrace();
                            }
                            mHandler.sendMessage(mHandler.obtainMessage());
                            //获取下载文件的大小
                            int loadedSize = (int)localFile.length();
                            if(loadedSize >= fileLength){
                                break;
                            }
                        }
                    }
                }.start();
            }
        }
        
        public DownLoadReceiver getReciver()
        {
            return receiver;
        }
    }

    它的逻辑:

    创建一个FileDownloadList对象后,就可以直接使用该下述方法来实现下载功能。

    downloadFile(String fileName, String saveDir, String saveName, Runnable callback)

    在实现上是这么个意思:

    1.在当前上下文,开启下载线程。当获取到要下载的文件的大小时,发送一个广播过来(这部分没有展示在上述代码中)。

    2.在当前上下文中,注册一个广播监听器,监听广播标识为SAVE_DOWNLOAD_FILE的广播。首次监听到发出来的广播后,首次发送过来的广播,包含了要下载的文件的大小信息,然后就每隔5毫秒检测本地文件的大小,直到本地文件的大小(loadedSize)大于等于要下载的文件(fileLength)大小时,退出该循环。

          在不断检测的过程中,通过mHandler.sendMessage(mHandler.obtainMessage()); ,让UI线程更新进度条。

          下载线程,会不断将服务器返回的数据流,写到本地文件中,所以,本地文件的大小会不断变化,直到,它的大小跟要下载的文件的大小相等时,就退出这个不断检测本地文件大小的线程。

    其它没有在上述代码中表现出来的内容(在其它部分的代码中):

    1.在invokeFile(final BaseRequestLims request)方法中,开了一个如下的下载线程.该下载线程,会将服务器返回的文件流,写到本地文件(localFile)中;然后,它还会发送一个标识为SAVE_DOWNLOAD广播,包含的信息有要下载文件的文件大小fileLength。

    //下载的子线程
                new Thread(){
                    @Override
                    public void run() {
                        super.run();
                        HttpHelper.invoke(request);
                    }
                }.start();

    上述代码存在的问题:

    1.上下文,使用的是某个Activity,如果发生系统调用了该Activity的onDestroy()时,下载线程还没有完成,也就意味着,loadedSize的大小还是小于fileLength。从而,那个不断检测本地文件大小的线程就一直在执行着。

    即是检测本地文件大小的线程和下载线程还在执行着:

    检测本地文件大小的线程:

    new Thread(){
                    @Override
                    public void run() {
                        super.run();
                        while(true){
                            try{
                                Thread.sleep(500);
                            }catch (Exception e) {
                                e.printStackTrace();
                            }
                            mHandler.sendMessage(mHandler.obtainMessage());
                            //获取下载文件的大小
                            int loadedSize = (int)localFile.length();
                            if(loadedSize >= fileLength){
                                break;
                            }
                        }
                    }
                }.start();

    下载线程:

                new Thread(){
                    @Override
                    public void run() {
                        super.run();
                        HttpHelper.invoke(request);
                    }
                }.start();

    那么,会出现什么问题呢?

    1).我可以确定的就是,mContext会出现泄漏。

    2). DownLoadReceiver不能正常被取消注册。

    分析,待续。

  • 相关阅读:
    1003 我要通过! (20 分)
    安装ANSYS19.0的正确方法(附下载)
    多项式最小二乘法拟合
    递归循环嵌套排列组合
    对二维数组使用指针进行操作的探索(C语言)
    统计C语言关键字出现次数
    三次样条插值matlab实现
    绩点换算小程序
    B1020 月饼(25 分)
    问题 B: 分组统计
  • 原文地址:https://www.cnblogs.com/ttylinux/p/3863835.html
Copyright © 2020-2023  润新知