android ftp多线程多任务下载时的listview滑动列表错乱解决方法
来源:互联网 发布:2016淘宝客还能赚钱吗 编辑:程序博客网 时间:2024/05/29 06:31
最近在研究ftp的多任务、多线程、后台下载的相关功能实现,由于每个任务都是点击下载按钮后开启独立的线程进行下载,同时还需要处理各种暂停、完成、继续下载等。adapter通常都会对holder进行复用,所以当列表滑动的时候,如果上面有一个暂停或者已经完成的任务,那么下面的列表就会复用到上面的holder,从而会导致相关功能和列表显示错乱的问题,如果要解决这个问题那么必须要处理几个问题:
- 列表复用的时候必须要将前面任务(主要是正在下载和已经完成从)的状态清除掉(比如停止下载中任务的进度更新)
- 列表复用结束后必须马上恢复到原来的状态
遇到的问题主要就是以下几个:
- 如果前面有一个任务正在下载,那么列表向下滑动的时候没有开始的下载任务状态却变成了正在下载那个任务的状态;
- 如果前面有一个任务已经下载完成,那么列表向下滑动的时候没用开始的下载任务状态却变成了已完成。
- 下载按钮功能错乱的问题
解决的方法其实也很简单,不过要是没想到的话也够折腾的,就是在holder复用的时候对正在下载的任务停止进度刷新,也就是移除hanlder,同时重新设置下载按钮的监听和初始化进度和文字描述。这里每个下载任务都用一个hash键值对保存了起来,状态等信息都保存在一个文件信息类中。所以所有的文件状态都是全局保存的。
下面是adpter里面的处理
import java.util.ArrayList;import java.util.List;import org.apache.commons.net.ftp.FTPFile;import android.R.bool;import android.annotation.SuppressLint;import android.content.Context;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.drawable.BitmapDrawable;import android.os.Environment;import android.os.Handler;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.view.ViewGroup.LayoutParams;import android.widget.BaseAdapter;import android.widget.ImageButton;import android.widget.ImageView;import android.widget.ListView;import android.widget.PopupWindow;import android.widget.ProgressBar;import android.widget.TextView;import android.widget.Toast;import com.android.newnotebook.Date;import com.example.listenclass.R;import com.listenclass.common.Constant;import com.listenclass.common.FileInfo;import com.listenclass.common.IRetrieveListener;import com.listenclass.db.DownloadDBManager;import com.listenclass.ftpdown.FTPCfg;import com.listenclass.ftpdown.FTPManager;import com.listenclass.util.Util;import com.llistenclass.service.DownloadService;/** * FTP列表适配器. * * */public class RemoteAdapter extends BaseAdapter { /** * FTP文件列表. */ private List<FTPFile> list = new ArrayList<FTPFile>(); private FTPCfg cfg; private static final String LOCAL_PATH = Environment.getExternalStorageDirectory()+"/ftpdownload/"; /** * 布局. */ private LayoutInflater inflater; private Context mContext; private ListView mListView; /** * 文件夹显示图片. */ private Bitmap icon1; /** * 文件显示图片. */ private Bitmap icon2; // private boolean mispause = false; /** * 构造函数. * @param context 当前环境 * @param li FTP文件列表 */ public RemoteAdapter(Context context, List<FTPFile> li,FTPCfg fp,ListView listView) { mContext = context; cfg = fp; this.list = li; this.inflater = LayoutInflater.from(context); mListView = listView; // 文件夹显示图片// icon1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.folder);// // 文件显示图片// icon2 = BitmapFactory.decodeResource(context.getResources(), R.drawable.doc); } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View view, ViewGroup parent) { ViewHolder holder= null; if (view == null) { // 设置视图 view = this.inflater.inflate(R.layout.item_file_download, null); // 获取控件实例 holder = new ViewHolder(); // holder.icon = (ImageView) view.findViewById(R.id.image_icon); holder.tvdownloadstate = (TextView) view.findViewById(R.id.txt_download_state); holder.fileName = (TextView) view.findViewById(R.id.txt_download_filename); holder.fileSize = (TextView) view.findViewById(R.id.txt_download_filesize); holder.beginpause = (ImageButton) view.findViewById(R.id.imgbtn_filedownload_opreation); holder.mProgressBar = (ProgressBar) view.findViewById(R.id.proBar_download_peogress); // 设置标签 view.setTag(holder); } else { // 获取标签 holder = (ViewHolder) view.getTag(); } // 获取文件名 holder.fileName.setText(list.get(position).getName()); holder.tvdownloadstate.setText(""); //文件分为四种状态,在列表显示数据时分别判断再处理 if (Constant.filestates.get(list.get(position).getName()).getState() == Constant.FILE_DOWNPAUSE) { long completesize = Constant.filestates.get(list.get(position).getName()).getCompleteSize(); long totalsize = Constant.filestates.get(list.get(position).getName()).getFileSize(); String downloadpro = Util.getFormatSize(completesize) + "/"+Util.getFormatSize(totalsize); holder.setPosition(position); holder.beginpause.setBackgroundResource(R.drawable.file_download_start); holder.fileSize.setText(downloadpro); holder.mProgressBar.setProgress(Constant.filestates.get(list.get(position).getName()).getProgress()); } else if(Constant.filestates.get(list.get(position).getName()).getState() == Constant.FILE_DOWNLOADING) { holder.beginpause.setBackgroundResource(R.drawable.file_download_pause); holder.downloadingInit(position); } else if (Constant.filestates.get(list.get(position).getName()).getState() == Constant.FILE_DOWNOVER) { holder.reInit(position,false); long totalsize = Constant.filestates.get(list.get(position).getName()).getFileSize(); holder.fileSize.setText(""); holder.tvdownloadstate.setText("已完成"+Util.getFormatSize(totalsize)); holder.beginpause.setBackgroundResource(R.drawable.file_download_complete); holder.mProgressBar.setProgress(Constant.filestates.get(list.get(position).getName()).getProgress());} else if (Constant.filestates.get(list.get(position).getName()).getState() == Constant.FILE_NOT_DOWNLOAD) { System.out.println("---position " +position +"--------name--------"+list.get(position).getName()); System.out.println("---------state-------"+Constant.filestates.get(list.get(position).getName()).getState()); holder.fileSize.setText(Util.getFormatSize(list.get(position).getSize())); //holder.beginpause.setOnClickListener(); holder.reInit(position,false); holder.beginpause.setBackgroundResource(R.drawable.file_download_start); holder.mProgressBar.setProgress(0);} System.out.println("------------------>getview position "+position+ " ------>firstvisibleposition "+mListView.getFirstVisiblePosition() + "---> filename " +list.get(mListView.getFirstVisiblePosition()).getName()); return view; } @SuppressLint("NewApi")private void showToolsMenu(PopupWindow mPopupWindow,View locateview) {View view = LayoutInflater.from(mContext).inflate(R.layout.popup_menu_selector, null);float x = locateview.getX();float y = locateview.getY();System.out.println(" x :"+x +" y: "+y);//if (mPopupWindow == null) {////}mPopupWindow = new PopupWindow(view, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, true);//view.findViewById(R.id.tools_select).setOnClickListener(this);//view.findViewById(R.id.tools_notebook).setOnClickListener(this);//view.findViewById(R.id.tools_download).setOnClickListener(this);//view.findViewById(R.id.tools_record).setOnClickListener(this);mPopupWindow.setFocusable(true);mPopupWindow.setOutsideTouchable(true);mPopupWindow.setBackgroundDrawable(new BitmapDrawable());//mPopupWindow.setAnimationStyle(R.style.PopupAnimation);view.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);//mPopupWindow.showAtLocation(locateview, Gravity.LEFT, 0, 0);mPopupWindow.showAsDropDown(locateview);} /** * 获取控件. */ private class ViewHolder { //private int mpositon; private ImageView icon; private TextView fileName; private TextView fileSize; private TextView tvdownloadstate; private ImageButton beginpause; private ProgressBar mProgressBar; private int position; private long totalsize = 0; private long mnowOffset = -1; private String strfilesize ; private PopupWindow mPopupWindow; private boolean isstophander = false; //暂停状态的文件调用 public void setPosition(int position) { this.position = position; totalsize = list.get(position).getSize(); strfilesize = Util.getFormatSize(totalsize); isstophander = false; beginpause.setOnClickListener(new btnClickListener()); } //下载中的列表item解除复用时调用 public void downloadingInit(int position) { this.position = position; isstophander = false; totalsize = list.get(position).getSize(); strfilesize = Util.getFormatSize(totalsize); mHandler.sendEmptyMessage(2); } //未下载和下载完成的列表复用其他holder时调用 public void reInit(int position,boolean isstophander) { this.position = position; this.isstophander = isstophander; totalsize = list.get(position).getSize(); strfilesize = Util.getFormatSize(totalsize); mHandler.removeMessages(2); beginpause.setOnClickListener(new btnClickListener()); } public class btnClickListener implements OnClickListener {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif (Constant.filestates.get(list.get(position).getName()).getState() != Constant.FILE_DOWNOVER){download();}else{ showToolsMenu(mPopupWindow, v);}} } private void download() { //如果当前文件状态不是正在下载,则开始下载 if (Constant.filestates.get(list.get(position).getName()).getState() != Constant.FILE_DOWNLOADING){ Log.i("FILE_DOWNLOADING", "-------startdownload-------> FILE_DOWNLOADING filename "+list.get(position).getName());beginpause.setBackgroundResource(R.drawable.file_download_pause);Constant.filestates.get(list.get(position).getName()).setState(Constant.FILE_DOWNLOADING);String remotefilename = Util.convertString(list.get(position).getName(), "GBK");Intent intent = new Intent();intent.setClass(mContext, DownloadService.class);intent.putExtra("remotefilename", remotefilename);intent.putExtra("localfilename", list.get(position).getName());intent.putExtra("flag", "startDownload");mContext.startService(intent);mHandler.sendEmptyMessageDelayed(2, 200);}else {Log.i("FILE_DOWNPAUSE", "-------pausedownload-------> FILE_DOWNPAUSE filename "+list.get(position).getName());mHandler.removeMessages(2);Constant.filestates.get(list.get(position).getName()).setState(Constant.FILE_DOWNPAUSE);String remotefilename = Util.convertString(list.get(position).getName(), "GBK");//发送到服务器的文件名需要转码,否则中文文件无法下载Intent intent = new Intent();intent.setClass(mContext, DownloadService.class);intent.putExtra("remotefilename", remotefilename);intent.putExtra("localfilename", list.get(position).getName());intent.putExtra("flag", "changeState");mContext.startService(intent);beginpause.setBackgroundResource(R.drawable.file_download_start);} } private Handler mHandler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case 2: mnowOffset = Constant.filestates.get(list.get(position).getName()).getCompleteSize(); if ((mnowOffset != -1) && mnowOffset != totalsize) { // Log.i("----", "-------position "+position +" isstophander "+isstophander); if (!isstophander) { int progress = (int)((mnowOffset /(double) totalsize)*100); // Log.i("progress", "progress :" +progress +" mnowOffset: "+mnowOffset +"totalsize " +totalsize); mProgressBar.setProgress(progress); String downloadpro = Util.getFormatSize(mnowOffset) + "/"+strfilesize; fileSize.setText(downloadpro); sendEmptyMessageDelayed(2, 200);} } else { //如果复用粘合在一起的时候可能会有问题DownloadDBManager dbManager = new DownloadDBManager(mContext);FileInfo fileInfo = new FileInfo();fileInfo.setCoursename("英语");fileInfo.setFilelength(totalsize);fileInfo.setFilename(list.get(position).getName());fileInfo.setDate(new Date().getDate());dbManager.add(fileInfo);mProgressBar.setProgress(100);beginpause.setBackgroundResource(R.drawable.file_download_complete);tvdownloadstate.setText(strfilesize + " 已完成");fileSize.setText(""); Toast.makeText(mContext, "下载成功,文件保存路径: " +LOCAL_PATH+list.get(position).getName() , Toast.LENGTH_SHORT).show(); } break; default: break; } }; }; }}
0 0
- android ftp多线程多任务下载时的listview滑动列表错乱解决方法
- android优化--滑动ListView列表时背景变黑的解决方法
- Listview滑动过程中item出现数据错乱的解决方法
- android listview优化:滑动时颜色错乱问题
- Android ListView 嵌套RadioGroup 滑动时出现错乱
- android - ListView优化机制及滑动时数据时出现的数据错乱重复问题
- 解决listview嵌套checkbox滑动时状态的错乱
- Android 用HorizontalScrollView实现ListView的Item滑动删除 ,滑动错乱 冲突
- 滑动ListView时,CheckBox控件错乱
- listview中嵌套checkbox滑动时错乱
- ListView滑动时CheckBox出现数据错乱
- listview滑动数据错乱
- android ListView使用ViewHolder优化时,EditText设置TextWatcher时,滑动ListView导致内容错乱
- Android ListView滑动时出现黑屏解决方法
- SDWebImage在多线程下载图片时防止错乱的策略
- SDWebImage在多线程下载图片时防止错乱的策略
- Android ListView在有checkbox的情况下上下滑动选中状态错误以及position错乱
- Android ListView滑动会触发addTextChangedListener,导致显示错乱
- 之前写的检测mysql 从服务器延迟的脚本
- jvm优化
- (4.1.28.1)HTTP通信之HttpClinet保持登录状态问题
- 压缩文件最基本原理——map实现
- UIAlertView的一些使用
- android ftp多线程多任务下载时的listview滑动列表错乱解决方法
- 模拟Listener对button的监听过程
- jvm优化检测多线程竞争
- #第二周1000题解#
- 最大连续子段和、M子段和
- 年轻的时候需要更加的奋斗!
- Android FlowLayout
- (4.1.28.3)第二种方法HttpClient.setCookieStore(mCookieStore)实现的HTTP工具类
- java的回调函数