Android ListView 自定义ITEM 为 进度条 按钮,进度条实时刷新

昨天要做一个MP3多任务下载的下载管理功能,要把每个下载任务放到一个ITEM中,下载所以就会有进度条,为了可以手动开始暂停等操作,又在进度条下面增加了一个按钮,默认下载任务全部从数据库中读取,点击一个按钮,就开始一个下载任务,进度条实时更新。

download.xml

?xmlversion="1.0"encoding="utf-8"?>

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

<ListView

android:id="@android:id/list"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:descendantFocusability="blocksDescendants"

android:divider="#330066"

android:dividerheight="1px">

</ListView>

</LinearLayout>

download_item.xml

<?xmlversion="1.0"encoding="utf-8"?>

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

<TextView

android:id="@+id/title_down"

android:layout_width="match_parent"

android:layout_height="30dp"

android:text="TextView"/>

<ProgressBar

android:id="@+id/pb_down"

style="?android:attr/progressBarStyleHorizontal"

android:layout_width="match_parent"

android:layout_height="30dp"

/>

<Button

android:id="@+id/bt_down"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="开始下载"/>

</LinearLayout>

看到很多实现的方法都是开一个线程,然后handle发送消息,handle接受到消息后,调用adapter的notifyDataSetChanged()方法来刷新LISTVIEW这里总觉得有些麻烦,操作性太差了,自己试了一天都没搞定。

要注意的是为了实现LISTVIEW里面的按钮事件,所以必须从BASEADAPTER派生一个类,重写GETVIEW方法,如下:

classLvButtonAdapterextendsBaseAdapter{

privateList<Map<String,Object>>mAppList;

privateLayoutInflatermInflater;

privateContextmContext;

privateString[]keyString;

privateint[]valueViewID;

publicLvButtonAdapter(Contextc,List<Map<String,Object>>appList,intresource,

String[]from,int[]to){

mAppList=appList;

mContext=c;

mInflater=(LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

keyString=newString[from.length];

valueViewID=newint[to.length];

System.arraycopy(from,0,keyString,0,from.length);

System.arraycopy(to,0,valueViewID,0,to.length);

}

@Override

publicintgetCount(){

returnmAppList.size();

}

@Override

publicObjectgetItem(intposition){

returnmAppList.get(position);

}

@Override

publiclonggetItemId(intposition){

returnposition;

}

@Override

publicViewgetView(finalintpos,ViewconvertView,ViewGroupparent){

buttonViewHolderholder;

if(convertView!=null){

holder=(buttonViewHolder)convertView.getTag();

}else{

convertView=mInflater.inflate(R.layout.download_item,null);

holder=newbuttonViewHolder();

holder.muiscName=(TextView)convertView.findViewById(valueViewID[0]);

holder.pb=(ProgressBar)convertView.findViewById(valueViewID[1]);

holder.button=(Button)convertView.findViewById(valueViewID[2]);

convertView.setTag(holder);

}

System.out.println("current_pos:"+pos);

pb_list.add(holder.pb);

bt_list.add(holder.button);

Map<String,Object>appInfo=mAppList.get(pos);

if(appInfo!=null){

Stringaname=(String)appInfo.get(keyString[0]);

holder.muiscName.setText(aname);

holder.button.setOnClickListener(newOnClickListener()

{

@Override

publicvoidonClick(Viewv){

//TODOAuto-generatedmethodstub

System.out.println("currentpb:"+pos);

ProgressBarpb=pb_list.get(pos);

Buttonbt=bt_list.get(pos);

if(bt.getText().toString().equals("开始下载")

||bt.getText().toString()=="开始下载"){

bt.setText("正在下载");

Object[]obj=queryItem(dbHelper,pos+1);

pb.setMax(Integer.parseInt(String.valueOf(obj[1])));

intsize=Integer.parseInt(String.valueOf(obj[1]));

Stringpath=String.valueOf(obj[0]);

Stringname=String.valueOf(obj[2]);

download(bt,pb,pos,path+".mp3",name);

}

});

}

returnconvertView;

}

}

注意在getView中测试输出ITEM位置,发现在加载LISTVIEW的时候所有ITEM所在的位置

是按顺序一次性显示出来的,这意味着GETVIEW方法里面的任何一个控件都不是你点击按钮所得到的那个ITEM,所以我用了

privateList<ProgressBar>pb_list=newArrayList<ProgressBar>();

privateList<Button>bt_list=newArrayList<Button>();

把进度条和按钮按照LISTVIEW的顺序全部添加进来。

在点击按钮的时候判断一下根据ITEM的位置查出所对应的进度条,后面按钮也一样。

下面说到重点了,SERVICE有两种启动方式START和BIND,而BINDserviceSERVICE是能直接和ACTIVITY交互的,所以在按钮点击事件中直接调用SERVICE的下载方法,把进度条作为参数传递到SERVICE中,在SERVICE中会为每个按钮事件开启一条线程来处理一个下载任务。

下面是downloadservice中的部分代码

publicvoiddownloader(Buttonbt,ProgressBarpb,intindex,Stringurl,Stringsavepath,Stringfilename){

try{

URLur=newURL(url);

System.out.println(ur);

HttpURLConnectionconn=(HttpURLConnection)ur.openConnection();

conn.connect();

fileSize=conn.getContentLength();

Log.e("length",String.valueOf(fileSize));

Filefile=newFile(savepath+"/"+filename+".mp3");

DownLoadThreadthread=newDownLoadThread(bt,pb,index,fileSize,file,conn,filename);

thread.start();

}catch(Exceptione){

e.printStackTrace();

}

}

classDownLoadThreadextendsThread{

publicDownLoadThread(){

}

privateintfileSize;

privateFilefile;

privateHttpURLConnectionconn;

privateDownloadInfoinfo;

privateProgressBarpb;

privateButtonbt;

privateintindex;

privateStringfilename;

publicDownLoadThread(Buttonbt,ProgressBarpb,intindex,intfileSize,Filefile,HttpURLConnectionconn,Stringfilename){

this.fileSize=fileSize;

this.file=file;

this.conn=conn;

this.index=index;

this.pb=pb;

this.bt=bt;

this.filename=filename;

}

inti=0;

@Override

publicvoidrun(){

//TODOAuto-generatedmethodstub

BufferedReaderbr=null;

BufferedWriterbw=null;

MyMapcache=MyMap.getInstance();

try{

InputStreamins=conn.getInputStream();

FileOutputStreamfos=newFileOutputStream(file);

br=newBufferedReader(newInputStreamReader(ins));

bw=newBufferedWriter(newOutputStreamWriter(fos));

byte[]buffer=newbyte[64];

intj=0;

while((j=ins.read(buffer))!=-1){

i+=j;

fos.write(buffer,0,j);

pb.setProgress(i);

if(i==fileSize){

Intentintent=newIntent("com.download.service");

intent.putExtra("index",index);

intent.putExtra("name",filename);

intent.putExtra("current_pos",i);

sendBroadcast(intent);

}

}

}catch(IOExceptione){

//TODOAuto-generatedcatchblock

e.printStackTrace();

}

}

}

在RUN方法中直接设置进度条的进度即可实现。

相关推荐