昨天要做一个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方法中直接设置进度条的进度即可实现。
分享到:
相关推荐
总的来说,这个Demo涵盖了Android开发中的多个知识点,包括ListView的局部刷新、异步任务、进度条更新以及文件下载管理。通过实践这个Demo,开发者可以深入理解Android UI更新机制以及后台任务的处理方式。
在Android开发中,ListView是一个非常重要的组件,常用于展示大量数据列表。本教程将通过一个实例Demo来深入探讨如何在Android应用中有效地使用ListView。首先,我们来看一下ListView的基本概念和工作原理。 ...
总之,通过这个Demo,开发者可以学习到如何在Android应用中实现ListView的下拉刷新功能,以及如何与后台数据交互,提升应用的交互性和实时性。通过深入研究源码,还能了解到更多关于SwipeRefreshLayout的工作原理和...
通常,这个视图包含一个进度条、一个提示文字(如“正在加载...”)以及一个可选的取消刷新按钮。 - 在代码中,使用LayoutInflater解析此布局文件,并将其添加到ListView的Footer。 2. **设置Adapter** - 自定义...
而"选择性的item侧滑出按钮"则为用户提供了一种快速操作列表项的交互方式,常见于邮件应用、待办事项列表等场景。这个Demo整合了这三个功能,解决了开发者在实际项目中可能遇到的需求。 1. **上拉加载更多**: 上...
综上所述,"ListView 下拉刷新,上拉加载,滑动删除"是Android开发中提高用户体验的重要特性。通过集成和自定义相应的组件,开发者可以轻松实现这些功能,为用户提供更流畅、更便捷的操作方式。在实际应用中,还需要...
在布局文件中,可以创建一个包含进度条或者自定义动画的视图,然后在需要加载数据时,将这个视图设置为ListView的内容。 2. **空数据状态**:当数据源为空时,我们可以展示一个提示信息,告诉用户目前没有数据。...
这个“itemwithdel”的项目就是针对这种需求设计的一个示例,它展示了如何在ListView的每个item上添加一个删除按钮,并在点击删除后实时刷新数据。 首先,我们需要在ListView的Adapter中创建一个新的视图(View)来...
- ListView是Android中用于显示大量数据的视图组件,通常与Adapter一起使用,Adapter负责填充数据到ListView的各个Item。 - ListView通过复用View(也称为ViewHolder模式)来提高性能,避免为每个Item创建新的View...
4.6.6、ListView自定义背景颜色 83 4.6.7、List长按与短按消息映射 84 4.6.8、点击ListView改变背景色 87 4.6.9、自动滚动ListView 88 4.6.10、BaseExpandableListAdapter例 88 4.6.11、列表视图(List View) 96 ...