您的位置:首页 > 编程语言

谈谈关于编程的良好习惯以及结合ListView和AsyncTask实现异步下载歌曲 推荐

2013-08-20 20:47 543 查看
上一篇博文我给大家介绍了如何使用AsyncTask实现异步处理耗时操作,这次我讲结合前面讲到的所有内容做一个下载歌曲的小项目(小模块)。在介绍之前我想先跟大家讲讲一些良好的编程习惯,能够让我们程序员做的成员更有可读性,易修改等
1:类名要以大写字母开头,方法名要以小写字母开头,名字最好用英文表达这个类或者方法的意思。想必这是最基本的要求。
2:如果需要实现接口或者继承的类代码少且简单,建议用匿名类来写,例如按钮的监听类
3:如果需要实现接口或者继承的类代码多且复杂,建议重新写个类去继承或实现接口,例如线程,这样的好处是如果你外部需要往类里面传入什么参数,就可以用构造方法传入参数。
4:如果一个类中需要用到别的类的变量(例如通过按键监听改变文本等)。这时候就可以写个内部类或者匿名内部类,这样就可以直接使用需要的类的变量
5:我们在编程过程中如果一个数字或者字符串同时在好几个地方出现且值保持不变(例如网址,屏幕大小等),这时候我们就可以吧这个变量定义为静态常量(常量的命名最好都要大写),当我们需要这个常量的值的时候只需要将常量值改变即可,不需要费力找到所有的地方在修改
6:如果类多了最好开始用包明归类,例如安卓的Activity包专门放Activity,util包专门放工具类,app包专门放application类等
7:成员变量前面加个字母m.
以上就是我总结的一些心得。希望对大家有帮助,接下来开始做下载歌曲项目(这个项目需要电脑可以连接网络)
1:写好行布局,获得listView对象并设置适配器类优化和数据封装(listView的使用前面博文介绍过了,这里就不多说),行布局图片用来放置歌手的照片,标题显示歌曲名字,子标题显示歌手名字,进度条显示下载进度,按钮实现下载功能。行布局如下图



2:将需要数据添封装到对象中,并用容器将这些对象存储起来

//存储封装对象的容器
private ArrayList<Itemdata> mData = new ArrayList<Itemdata>();
//歌手名字数组
private String[] name = new String[]{"胡夏","周杰伦","王力宏"};
//对象歌曲名字
private String[] music = new String[]{"那些年","龙门客栈","依然爱你"};
//对应歌手名字值(由于sdcard只能导出字母所以存储歌曲名字要用拼音)
private String[] music_value = new String[]{"naxienian","longmenkezhan","yiranaini"};
//对应歌手照片
private int[] picture = new int[]{R.drawable.huxia,R.drawable.zhoujielun,R.drawable.wanglihong};
//对应的下载地址
private String[] address = new String[]{"http://zhangmenshiting.baidu.com/data2/music/46614034/138444821376874061128.mp3?xcode=0b7508b24c5c9539814d252fc8260c557a48f91107b5ffaf"
,"http://zhangmenshiting.baidu.com/data2/music/35479592/314965631376820061128.mp3?xcode=29b8efeab72ee1f188009d4d5095c7d468b2ac04a0a9b4cc"
,"http://zhangmenshiting.baidu.com/data2/music/10512583/105098561376809261128.mp3?xcode=67f6c2ca1073793a5741df3072eabfcba9740086dc7de35a"
};


for (int i = 0; i < 3; i++) {
Itemdata itemdata = new Itemdata(music[i], name[i], picture[i]);
mData.add(itemdata);
}


4:获取行布局中的所有控件对象,在按钮中设置监听事件,当按钮按下的时候启动异步任务,并把对应行布局的progressBar对象,button对象,title对象传入到异步类中(bar对象用来在下载时根据下载多少改变进度条,button是等下载完成让它恢复可以点击的状态,title对象是要在下载结束后提示哪一首歌下载完成),代码如下(这里的holder对象前面listView优化中有提到

layout = getLayoutInflater().inflate(R.layout.list, null);
holder = new ViewHolder();
holder.mImage = (ImageView) layout.findViewById(R.id.imageView1);
holder.mTitle = (TextView) layout.findViewById(R.id.textView1);
holder.mSubtitle = (TextView) layout.findViewById(R.id.textView2);
holder.bar = (ProgressBar) layout.findViewById(R.id.progressBar1);
holder.btn = (Button) layout.findViewById(R.id.button1);
final Button btn = (Button) layout.findViewById(R.id.button1);
final ProgressBar bar =(ProgressBar)layout.findViewById(R.id.progressBar1);
final TextView title = (TextView) layout.findViewById(R.id.textView1);  holder.btn.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
//将按钮设置为不可点击
btn.setEnabled(false);
//启动任务并将需要的参数传入
new MyTask(bar,title,btn,name_value[position])
.execute(address[position]);
}
});3:一步任务
5:将对应的值分别加入对象对象控件中
Itemdata itemdata = mData.get(position);
holder.mImage.setImageResource(itemdata.image);
holder.mTitle.setText(itemdata.title);              holder.mSubtitle.setText(itemdata.subtitle);
6:在继承asyncTask的异步类中的doInBackgroud方法中做下载歌曲的耗时操作,代码如下
FileOutputStream fos = null;
InputStream is = null;
try {
//获得url对象
URL url = new URL(params[0]);
//获取URLconne对象
URLConnection openConnection = url.openConnection();
//获取文件的大小(单位为字节)
int length = openConnection.getContentLength();
//将进度条最大值设为文件大小
bar.setMax(length);
//获取下载地址的输入流
is = openConnection.getInputStream();
//获取sdCard的绝对路径
File SDCardPath = Environment.getExternalStorageDirectory().getAbsoluteFile();
//创建输出流对象并将文件下载到sdCard目录中
fos = new FileOutputStream(SDCardPath+"/"+music_value+".mp3");
byte[] buffer = new byte[1024];
//获取下载每一次下载的具体字节长度
int len = is.read(buffer);
while(len != -1)
{
//调用该方法进入ononProgressUpdate()方法中设置进度条进度
publishProgress(len);
fos.write(buffer);
len = is.read(buffer);

}
fos.flush();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
if(fos != null)
{
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
if(is != null)
{
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//下载完成后将对应歌曲的歌名返回,进入onPostExecute方法进行处理
return title.getText().toString()+"下载完成";
7:onProgressUpdate(Integer... values)方法中修改进度条进度
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
bar.setProgress(bar.getProgress()+values[0]);
}
8:下载完毕后在onPostExecute(String result)方法中使用Toast方法个用户提示下载完成,并将按钮设置为可用
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
//界面调处提示下载完成
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
//按钮设为可用
btn.setEnabled(true);
}
9:设置权限(这里需要从网络下载和写入sdCard的2个权限),在清单文件中配置(AndroidManifest.xml)
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
10:大功告成,如图(下载中,大家3首歌同时点击下载却发现只有第一首歌进度条在走是因为安卓4.2版本的原因,其实异步任务已经都启动了等第一首歌下载完了会自动继续下第二首。



下载完成后跳提示



下载完成后的文件都在SDCard目录中



由于时间原因只能弄3首歌曲。到这里我就给大家介绍完了安卓线程的基本用法,我会把完整代码上传到我的下载有需要的可以去下,名字为DownLoadMusic。下次我会给大家介绍四大组件之一Activity的创建和生命周期
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐