首页 > 代码库 > 一个类的阅读,分析

一个类的阅读,分析

阅读到这么个类:

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不能正常被取消注册。

 

分析,待续。