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

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

download.xml
?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns: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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns: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方法,如下:
class LvButtonAdapter extends BaseAdapter{
    private List<Map<String ,Object>> mAppList;
    private LayoutInflater mInflater;
    private Context mContext;
    private String [ ] keyString;
    private int [ ] valueViewID; 
    public LvButtonAdapter( Context c, List <Map<String,Object>> appList, int resource,
            String[ ] from , int[ ] to) {
        mAppList = appList;
        mContext = c;
        mInflater = ( LayoutInflater) mContext. getSystemService(Context.LAYOUT_INFLATER_SERVICE) ;
        keyString = new String [ from . length ] ;
        valueViewID = new int [ to. length ] ;
        System.arraycopy ( from , 0, keyString, 0, from . length ) ;
        System.arraycopy ( to, 0, valueViewID, 0, to. length ) ;
    }
    @Override
    public int getCount ( ) {
        return mAppList. size ( ) ;
    }
    @Override
    public Object getItem ( int position ) {
        return mAppList. get ( position ) ;
    }
    @Override
    public long getItemId( int position ) {
        return position ;
    }
    @Override
    public View getView(final int pos , View convertView, ViewGroup parent ) {
    buttonViewHolder holder;
    if ( convertView!= null ) {
            holder = (buttonViewHolder)convertView.getTag ( ) ;
        }else{
            convertView = mInflater. inflate (R.layout.download_item, null ) ;
            holder = new buttonViewHolder( ) ;
            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 ) {
            String aname = (String)appInfo.get(keyString[0]) ;
            holder.muiscName.setText(aname);
            holder.button.setOnClickListener(new OnClickListener()
               {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub

System.out.println("current pb:"+pos);
ProgressBar pb  = pb_list.get(pos);
Button bt  = 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])));
int size = Integer.parseInt(String.valueOf(obj[1]));
String path = String.valueOf(obj[0]);
String name =  String.valueOf(obj[2]);
download(bt,pb,pos,path+".mp3",name);
}
        }); 
        }
        return convertView;
    }
}


注意在getView中测试 输出ITEM 位置,发现在加载LISTVIEW的时候所有ITEM所在的位置
是按顺序一次性显示出来的,这意味着GETVIEW方法里面的任何一个控件都不是你点击按钮所得到的那个ITEM,所以我用了
private List<ProgressBar> pb_list = new ArrayList<ProgressBar>();
private List<Button> bt_list = new ArrayList<Button>();
把 进度条和按钮按照LISTVIEW的顺序全部添加进来。

在点击按钮的时候判断一下 根据ITEM的位置查出所对应的进度条,后面按钮也一样。
下面说到重点了,SERVICE 有两种启动方式 START 和 BIND ,而BINDservice SERVICE 是能直接和ACTIVITY交互的,所以在按钮点击事件中直接调用SERVICE 的下载方法,把进度条作为参数传递到SERVICE中,在SERVICE中会为每个按钮事件开启一条线程来处理一个下载任务。
下面是downloadservice 中的部分代码
public void downloader(Button bt,ProgressBar pb,int index,String url,String savepath,String filename){
    try{
    URL ur = new URL(url);
    System.out.println(ur);
    HttpURLConnection  conn = (HttpURLConnection) ur.openConnection();
    conn.connect();
    fileSize =  conn.getContentLength();
    Log.e("length",String.valueOf(fileSize));
    File  file  = new File(savepath+"/"+filename+".mp3");
    DownLoadThread thread  = new DownLoadThread(bt,pb,index,fileSize,file,conn,filename);
    thread.start();
    }catch(Exception e){
    e.printStackTrace();
    }
    }
   
    class DownLoadThread extends Thread{
        public DownLoadThread(){
       
        }
        private int fileSize;
        private File file;
        private HttpURLConnection conn;
        private DownloadInfo info;
        private ProgressBar pb;
        private Button bt;
        private int index;
        private String filename;
        public DownLoadThread(Button bt,ProgressBar pb,int index,int fileSize,File file,HttpURLConnection conn,String filename){
        this.fileSize =fileSize;
        this.file = file;
        this.conn = conn;
        this.index = index;
        this.pb = pb;
        this.bt = bt;
        this.filename  = filename;
        }
        int  i = 0;
       
@Override
public void run() {
// TODO Auto-generated method stub
BufferedReader br =null;
BufferedWriter bw  = null;
MyMap cache = MyMap.getInstance();
try {
InputStream ins  = conn.getInputStream();
FileOutputStream fos  = new FileOutputStream(file);
br  = new BufferedReader(new InputStreamReader(ins));
bw  = new BufferedWriter(new OutputStreamWriter(fos));
  byte[] buffer=new byte[64];
  int j  = 0;
   while((j=ins.read(buffer))!=-1){
i+=j;
    fos.write(buffer,0,j);
    pb.setProgress(i);
    if(i==fileSize){
    Intent  intent = new Intent("com.download.service");
    intent.putExtra("index",index);
    intent.putExtra("name",filename);
    intent.putExtra("current_pos",i);
    sendBroadcast(intent);
    }
   }
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
    }

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

猜你喜欢

转载自f303153041.iteye.com/blog/1838092