android音乐播放器+异步加载+缓存+图片加载+listview列表显示+tomcat服务器+xml解析
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了android音乐播放器+异步加载+缓存+图片加载+listview列表显示+tomcat服务器+xml解析,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含18344字,纯文字阅读大概需要27分钟。
内容图文
最近在做一款播放器,服务器为tomcat,将音乐所有信息放在服务器端,客户端与服务器端之间的通信是同http协议进行的。首先把服务器端的数据部署完成,然后客户端
采用pull解析器将服务器端传过来的实体对象解析成music对象,再将需要显示的数据(包括文本和图片)利用自定义的适配器显示在listview上。现在,本人将文本通过异步加载的方式显示在listview上,而图片则通过线程+handler机制来加载和更新,并将图片作为缓存存到内存和文件。。。
具体实现代码如下:
实体类:Music.java
1 package com.zsw.entity; 2 3 public class Music { 4 /* 对应属性id */ 5 private int id; 6 /* 音乐名称 */ 7 private String name; 8 /* 音乐专辑 */ 9 private String album; 10 /* 歌手 */ 11 private String singer; 12 /* 作者 */ 13 private String author; 14 /* 作曲者 */ 15 private String composer; 16 /* 播放时长 */ 17 private String duration; 18 /* 相册图片路径 */ 19 private String albumPicPath; 20 /* 音乐文件路径 */ 21 private String musicPath; 22 /* 下载次数 */ 23 private int downCount; 24 /* 收藏次数 */ 25 private int favCount; 26 public int getId() { 27 return id; 28 } 29 public void setId(int id) { 30this.id = id; 31 } 32public String getName() { 33return name; 34 } 35publicvoid setName(String name) { 36this.name = name; 37 } 38public String getAlbum() { 39return album; 40 } 41publicvoid setAlbum(String album) { 42this.album = album; 43 } 44public String getSinger() { 45return singer; 46 } 47publicvoid setSinger(String singer) { 48this.singer = singer; 49 } 50public String getAuthor() { 51return author; 52 } 53publicvoid setAuthor(String author) { 54this.author = author; 55 } 56public String getComposer() { 57return composer; 58 } 59publicvoid setComposer(String composer) { 60this.composer = composer; 61 } 62public String getDuration() { 63return duration; 64 } 65publicvoid setDuration(String duration) { 66this.duration = duration; 67 } 68public String getAlbumPicPath() { 69return albumPicPath; 70 } 71publicvoid setAlbumPicPath(String albumPicPath) { 72this.albumPicPath = albumPicPath; 73 } 74public String getMusicPath() { 75return musicPath; 76 } 77publicvoid setMusicPath(String musicPath) { 78this.musicPath = musicPath; 79 } 80 81publicint getDownCount() { 82return downCount; 83 } 84publicvoid setDownCount(int downCount) { 85this.downCount = downCount; 86 } 87publicint getFavCount() { 88return favCount; 89 } 90publicvoid setFavCount(int favCount) { 91this.favCount = favCount; 92 } 93 @Override 94public String toString() { 95 StringBuilder sb=new StringBuilder("音乐信息:\n"); 96 sb.append("编号").append(id).append("\n"); 97 sb.append("歌名").append(name).append("\n"); 98 sb.append("歌手").append(singer).append("\n"); 99 sb.append("专辑").append(album).append("\n"); 100 sb.append("作词").append(author).append("\n"); 101 sb.append("作曲").append(composer).append("\n"); 102 sb.append("时长").append(duration).append("\n"); 103 sb.append("下载次数").append(downCount).append("\n"); 104 sb.append("收藏次数").append(favCount).append("\n"); 105return sb.toString(); 106 } 107 }
工具类:
HttpUtils.java
1 package com.zsw.utils; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.List; 6 import org.apache.http.HttpEntity; 7 import org.apache.http.HttpResponse; 8 import org.apache.http.HttpStatus; 9 import org.apache.http.NameValuePair; 10 import org.apache.http.client.HttpClient; 11 import org.apache.http.client.entity.UrlEncodedFormEntity; 12 import org.apache.http.client.methods.HttpGet; 13 import org.apache.http.client.methods.HttpPost; 14 import org.apache.http.client.methods.HttpUriRequest; 15 import org.apache.http.impl.client.DefaultHttpClient; 16 import org.apache.http.params.CoreConnectionPNames; 17 18 public class HttpUtils { 19 public static final int METHOD_GET = 1; 20publicstaticfinalint METHOD_POST = 2; 2122/**23 * 连接服务端指定的资源路径获取响应实体对象 24 * 25 * @param uri 26 * @param params 27 * @param method 28 * @return29 * @throws IOException 30*/31publicstatic HttpEntity getEntity(String uri, List<NameValuePair> params, 32int method) throws IOException { 33 HttpEntity entity = null; 34// 创建客户端对象35 HttpClient client = new DefaultHttpClient(); 36 client.getParams().setParameter( 37 CoreConnectionPNames.CONNECTION_TIMEOUT, 3000); 38// 创建请求对象39 HttpUriRequest request = null; 40switch (method) { 41case METHOD_GET:// get请求42 StringBuilder sb = new StringBuilder(uri); 43if (params != null && !params.isEmpty()) { 44 sb.append(‘?‘); 45for (NameValuePair pair : params) { 46 sb.append(pair.getName()).append(‘=‘) 47 .append(pair.getValue()).append(‘&‘); 48 } 49 sb.deleteCharAt(sb.length() - 1); 50 } 51 request = new HttpGet(sb.toString()); 52break; 53case METHOD_POST:// post请求54 request = new HttpPost(uri); 55if (params != null && !params.isEmpty()) { 56 UrlEncodedFormEntity reqEntity = new UrlEncodedFormEntity( 57 params); 58 ((HttpPost) request).setEntity(reqEntity); 59 } 60break; 61 } 62// 执行请求获得实体对象63 HttpResponse response = client.execute(request); 64if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 65 entity = response.getEntity(); 66 } 67// 返回响应实体68return entity; 69 } 7071/**72 * 获取指定实体对象的 长度信息 73 * 74 * @param entity 75 * @return76*/77publicstaticlong getLength(HttpEntity entity) { 78if (entity != null) 79return entity.getContentLength(); 80return 0; 81 } 8283/**84 * 获取实体输入流 85 * 86 * @param entity 87 * @return88 * @throws IOException 89 * @throws IllegalStateException 90*/91publicstatic InputStream getStream(HttpEntity entity) 92throws IllegalStateException, IOException { 93if (entity != null) { 94return entity.getContent(); 95 } 96returnnull; 97 } 98 }
BitmapUtils.java
1 package com.zsw.util; 2 3 import java.io.File; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 7 import android.graphics.Bitmap; 8 import android.graphics.Bitmap.CompressFormat; 9 import android.graphics.BitmapFactory; 10 import android.graphics.BitmapFactory.Options; 11 12 public class BitmapUtils { 13 /** 14 * 从指定文件路径加载位图对象 15 * @param path 16 * @return 17 */ 18 public static Bitmap loadBitmap(String path){ 19 return BitmapFactory.decodeFile(path); 20 } 21 public static Bitmap loadBitmap(byte[] data,int width,int height){ 22 Bitmap bm=null; 23// 创建加载选项对象(加载图片的时候进行的收缩操作,位图处理的时候用到的一个类)24 Options opts=new Options(); 25// 设置仅加载边界信息,并存储在opts中。加载第一行也即图片的格式,尺寸等信息26 opts.inJustDecodeBounds=true; 27// 加载为位图尺寸信息28 BitmapFactory.decodeByteArray(data, 0, data.length); 29//设置伸缩比例30int x=opts.outWidth/width; 31int y=opts.outHeight/height; 32//为了伸缩不超过边界,从x,y中取出较大的数作为伸缩比例33 opts.inSampleSize=x>y?x:y; 34//取消仅加载边界信息设置(不设置成false的话永远只加载边界信息,加载不上图片)35 opts.inJustDecodeBounds=false; 36//加载位图37 bm=BitmapFactory.decodeByteArray(data, 0, data.length); 38return bm; 39 } 40publicstaticvoid save(Bitmap bm,File file) throws IOException{ 41if(bm!=null&&file!=null){ 42//如果文件目录不存在,则创建新目录43if(!file.getParentFile().exists()){ 44 file.getParentFile().mkdirs(); 45 } 46if(!file.exists()){ 47 file.createNewFile(); 48 } 49//保存文件50 bm.compress(CompressFormat.JPEG, 100, new FileOutputStream(file)); 51 } 52 } 53 }
GlobalConsts.java
1 package com.zsw.util; 2 /** 3 * 全局变量 4 * @author zsw 5 * 6 */ 7 public class GlobalConsts { 8 public static final String BASE_URL = "http://192.168.1.104:8080/musiconline/"; 9// public static final String BASE_URL = "http://172.16.3.182:8080/musiconline/";10 }
业务类:
MusicXmlParse.java
1 package com.zsw.service; 2 3 import java.io.InputStream; 4 import java.io.InputStreamReader; 5 import java.util.ArrayList; 6 import org.xmlpull.v1.XmlPullParser; 7 import org.xmlpull.v1.XmlPullParserFactory; 8 import com.zsw.entity.Music; 9 10 public class MusicXmlParse { 11 public ArrayList<Music> parse(InputStream is) throws Exception { 12 ArrayList<Music> musics = null; 13 Music m = null; 14// 创建解析器对象 15// 利用解析器工厂创建解析器实例16 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 17 XmlPullParser parser = factory.newPullParser(); 18// 设置输入源19 parser.setInput(new InputStreamReader(is)); 20// 获取当前事件类型21int eventType = parser.getEventType(); 22// 当事件类型不等于END_DOCUNEMNT时 循环解析23while (eventType != XmlPullParser.END_DOCUMENT) { 24switch (eventType) { 25case XmlPullParser.START_DOCUMENT: 26 musics = new ArrayList<Music>(); 27break; 28case XmlPullParser.START_TAG: 29// 获取标签名30 String tagName = parser.getName(); 31if ("music".equals(tagName)) { 32 m = new Music(); 33 m.setId(Integer.parseInt(parser.getAttributeValue(null, 34 "id"))); 35 } elseif ("name".equals(tagName)) { 36 m.setName(parser.nextText()); 37 } elseif ("singer".equals(tagName)) { 38 m.setSinger(parser.nextText()); 39 } elseif ("album".equals(tagName)) { 40 m.setAlbum(parser.nextText()); 41 } elseif ("author".equals(tagName)) { 42 m.setAuthor(parser.nextText()); 43 } elseif ("composer".equals(tagName)) { 44 m.setComposer(parser.nextText()); 45 } elseif ("albumpic".equals(tagName)) { 46 m.setAlbumPicPath(parser.nextText()); 47 } elseif ("musicpath".equals(tagName)) { 48 m.setMusicPath(parser.nextText()); 49 } elseif ("time".equals(tagName)) { 50 m.setDuration(parser.nextText()); 51 } elseif ("downCount".equals(tagName)) { 52 m.setDownCount(Integer.parseInt(parser.nextText())); 53 } elseif ("favCount".equals(tagName)) { 54 m.setFavCount(Integer.parseInt(parser.nextText())); 55 } 56break; 57case XmlPullParser.END_TAG: 58if("music".equals(parser.getName())){ 59 musics.add(m); 60 } 61break; 62 } 63// 驱动到下一 事件64 eventType=parser.next(); 65 } 66// System.out.println("-=-=-=-=-="+musics);67return musics; 68 } 6970 }
MusicXmlparseService.java
1 package com.zsw.service; 2 3 import java.io.InputStream; 4 import java.util.ArrayList; 5 import org.apache.http.HttpEntity; 6 import com.zsw.MainActivity; 7 import com.zsw.entity.Music; 8 import com.zsw.util.HttpUtils; 9 import android.os.AsyncTask; 10 import android.widget.Toast; 11 12 public class MusicXmlParseService 13 extends AsyncTask<String, String, ArrayList<Music>>{ 14private MainActivity context; 15public MusicXmlParseService(MainActivity context){ 16this.context=context; 17 } 18/**19 * 执行异步操作并返回music集合 20*/21 @Override 22protected ArrayList<Music> doInBackground(String... params) { 23 ArrayList<Music>musics=null; 24try { 25 publishProgress("开始联网解析xml"); 26//获取实体对象27 HttpEntity entity=HttpUtils.getEntity(params[0], null, HttpUtils.METHOD_GET); 28 InputStream is=HttpUtils.getStream(entity); 29 System.out.println("=-=-+++"+entity); 30//解析xml数据流并放入到music集合中31 musics=new MusicXmlParse().parse(is); 32 System.out.println("==========+"+musics.toString()); 33 } catch (Exception e) { 34 e.printStackTrace(); 35 } 36return musics; 37 } 38/**39 * 当异步任务执行完成时 40*/41 @Override 42protectedvoid onPostExecute(ArrayList<Music> result) { 43 context.updateListView(result); 44 publishProgress("解析结束"); 45 } 4647 @Override 48protectedvoid onProgressUpdate(String... values) { 49 Toast.makeText(context, values[0], Toast.LENGTH_LONG).show(); 50 } 515253 }
适配器类:
MusicAdapter.java
1 package com.zsw.adpter; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.lang.ref.SoftReference; 6 import java.util.ArrayList; 7 import java.util.HashMap; 8 import org.apache.http.HttpEntity; 9 import org.apache.http.util.EntityUtils; 10 import com.zsw.R; 11 import com.zsw.entity.Music; 12 import com.zsw.util.BitmapUtils; 13 import com.zsw.util.GlobalConsts; 14 import com.zsw.util.HttpUtils; 15 import android.content.Context; 16 import android.graphics.Bitmap; 17 import android.os.Handler; 18 import android.os.Message; 19 import android.view.LayoutInflater; 20 import android.view.View; 21 import android.view.ViewGroup; 22 import android.widget.BaseAdapter; 23 import android.widget.ImageView; 24 import android.widget.ListView; 25 import android.widget.TextView; 26 27 public class MusicAdapter extends BaseAdapter { 28 ArrayList<Music> musics; 29// 显示listview上的数据 30private LayoutInflater inflater; 31private Context context; 32 33publicvoid setMusics(ArrayList<Music> musics) { 34if (musics != null) { 35this.musics = musics; 36 } else { 37this.musics = new ArrayList<Music>(); 38 } 39 } 40//缓存 采用软引用放位图对象 41 HashMap<String, SoftReference<Bitmap>>caches; 42// 任务集合 43private ArrayList<ImageLoadTask> tasks; 44// 开启工作线程 45private Thread workThread; 46// 利用handler更新界面 47private Handler handler; 48// 判断是否轮询 49private Boolean isLoop; 50 51public MusicAdapter(Context context, ArrayList<Music> musics, 52final ListView lvMusics) { 53 setMusics(musics); 54this.context = context; 55this.inflater = LayoutInflater.from(context); 56this.tasks = new ArrayList<MusicAdapter.ImageLoadTask>(); 57this.caches=new HashMap<String, SoftReference<Bitmap>>(); 58this.handler = new Handler() { 59 @Override 60publicvoid handleMessage(Message msg) { 61// 获取加载完成的图片 62 ImageLoadTask task = (ImageLoadTask) msg.obj; 63// 根据设置了tag的图片从listview中找到imageView 64 ImageView iv = (ImageView) lvMusics.findViewWithTag(task.path); 65// 更新图片框 66if (iv != null) { 67if (task.bitmap != null) { 68// 如果位图任务里的位图不为空,则加载到imageview中 69 iv.setImageBitmap(task.bitmap); 70 } else { 71// 若为空则设置默认图片 72 iv.setImageResource(R.drawable.ic_launcher); 73 } 74 } 75 76 } 77 }; 78 isLoop = true; 79 workThread = new Thread() { 80 @Override 81publicvoid run() { 82// 开启死循环进行轮询 83while (isLoop) { 84// 轮询任务集合...如果任务集合不为空 85while (!tasks.isEmpty()) { 86// 获取第一条任务 87 ImageLoadTask task = tasks.remove(0); 88try { 89// 从服务器端获取实对象 90 HttpEntity entity = HttpUtils.getEntity( 91 GlobalConsts.BASE_URL + task.path, null, 92 HttpUtils.METHOD_GET); 93// 将实体对象转化成字节数组 94byte[] data = EntityUtils.toByteArray(entity); 95 System.out.println("data="+data); 96// 利用位图工厂类将字节数组转化成位图 97 task.bitmap = BitmapUtils.loadBitmap(data, 48, 48); 98// task.bitmap=BitmapFactory.decodeByteArray( 99// data, 0, data.length); 100//添加缓存101 caches.put(task.path, new SoftReference<Bitmap>(task.bitmap)); 102//将缓存图片保存到指定文件中103 File file=getFile(task.path); 104 BitmapUtils.save(task.bitmap, file); 105// 利用handle转发消息到主线程106 Message.obtain(handler, 0, task).sendToTarget(); 107 } catch (IOException e) { 108 e.printStackTrace(); 109 } 110 } 111// 如果任务集合里没有任务,则线程等待112synchronized (this) { 113try { 114this.wait(); 115 } catch (InterruptedException e) { 116 e.printStackTrace(); 117 } 118 } 119 } 120 } 121 }; 122this.workThread.start(); 123 } 124125/**126 * 替换适配器中的数据集,并刷新listview 127 * 128 * @param musics 129*/130publicvoid changeData(ArrayList<Music> musics) { 131this.setMusics(musics); 132this.notifyDataSetChanged(); 133 } 134private File getFile(String path){ 135returnnew File(context.getExternalCacheDir(), path); 136 } 137 @Override 138publicint getCount() { 139return musics.size(); 140 } 141142 @Override 143public Music getItem(int position) { 144return musics.get(position); 145 } 146147 @Override 148publiclong getItemId(int position) { 149return getItem(position).getId(); 150 } 151152 @Override 153public View getView(int position, View convertView, ViewGroup parent) { 154// 加载或复用item界面155 ViewHolder holder = null; 156if (convertView == null) { 157 convertView = inflater.inflate(R.layout.item_music, null); 158 holder = new ViewHolder(); 159 holder.ivAlbum = (ImageView) convertView.findViewById(R.id.ivAlbum); 160 holder.tvName = (TextView) convertView.findViewById(R.id.tvName); 161 holder.tvDuration = (TextView) convertView 162 .findViewById(R.id.tvDuration); 163 holder.tvAlbum = (TextView) convertView.findViewById(R.id.tvAlbum); 164 holder.tvSinger = (TextView) convertView 165 .findViewById(R.id.tvArtist); 166 convertView.setTag(holder); 167 } else { 168 holder = (ViewHolder) convertView.getTag(); 169 } 170// 获取指定位置的数据171 Music m = getItem(position); 172// 将数据写入到item界面173 holder.tvName.setText(m.getName()); 174 holder.tvDuration.setText(m.getDuration()); 175 holder.tvSinger.setText(m.getSinger()); 176 holder.tvAlbum.setText(m.getAlbum()); 177// 加载专辑图片 178// 首先加载专辑图片的路径179 String path = m.getAlbumPicPath(); 180 System.out.println("path=" + path); 181//首先,在加载图片之前判断缓存中是否存在该图片路径 182//若存在,下次加载时从缓存中取图片183if(caches.containsKey(path)){ 184//获取缓存图片185 Bitmap bm=caches.get(path).get(); 186//若缓存图片不为空,则更新iamgeview,然后返回convertview187if(bm!=null){ 188 holder.ivAlbum.setImageBitmap(bm); 189return convertView; 190 } 191 } 192//其次,再判断是否存在文件缓存193 Bitmap bm=BitmapUtils.loadBitmap(getFile(path).getAbsolutePath()); 194if(bm!=null){ 195 holder.ivAlbum.setImageBitmap(bm); 196return convertView; 197 } 198// 设置图片的tag标记199 holder.ivAlbum.setTag(path); 200// 创建图片加载任务 201// holder.ivAlbum.setImageResource(R.drawable.ic_launcher);202 ImageLoadTask task = new ImageLoadTask(); 203 task.path = path; 204// 如果任务集合中不存在该任务,则添加到任务集合中205if (!tasks.contains(task)) { 206 tasks.add(task); 207// 添加任务后则消息队列(即任务集合)不为空,其通知线程启动208synchronized (workThread) { 209 workThread.notify(); 210 } 211 } 212// 返回item界面213return convertView; 214 } 215216class ViewHolder { 217private ImageView ivAlbum; 218private TextView tvName; 219private TextView tvDuration; 220private TextView tvSinger; 221private TextView tvAlbum; 222 } 223224// 加载图片任务集合225class ImageLoadTask { 226private Bitmap bitmap; 227private String path; 228229/**230 * 判断加载图片任务是否相同(以路径作为判断条件) 231*/232 @Override 233publicboolean equals(Object o) { 234 ImageLoadTask task = (ImageLoadTask) o; 235returnthis.path.equals(task.path); 236 } 237 } 238239 }
主界面:
MainActivity.java
1 package com.zsw; 2 3 import java.util.ArrayList; 4 5 import com.zsw.adpter.MusicAdapter; 6 import com.zsw.entity.Music; 7 import com.zsw.service.MusicXmlParseService; 8 import com.zsw.util.GlobalConsts; 9 10 import android.os.Bundle; 11 import android.app.Activity; 12 import android.view.Menu; 13 import android.widget.ListView; 14 15 public class MainActivity extends Activity { 16private ListView lvMusics; 17private MusicAdapter adapter; 18 @Override 19protectedvoid onCreate(Bundle savedInstanceState) { 20super.onCreate(savedInstanceState); 21 setContentView(R.layout.activity_main); 22//c初始化listview,使用空集合23 initView(); 24//启动异步任务,加载和解析xml25new MusicXmlParseService(this).execute(GlobalConsts.BASE_URL+"sounds.xml"); 26 } 27privatevoid initView(){ 28//获取listview的引用29 lvMusics=(ListView)findViewById(R.id.lvMusics); 30//创建适配器31 adapter=new MusicAdapter(this,null,lvMusics); 32//设置设配器33 lvMusics.setAdapter(adapter); 34 } 35/**36 * 刷新listView,并获取加载的数据 37*/38publicvoid updateListView(ArrayList<Music>musics){ 39 adapter.changeData(musics); 40 } 41 @Override 42publicboolean onCreateOptionsMenu(Menu menu) { 43 getMenuInflater().inflate(R.menu.main, menu); 44returntrue; 45 } 4647 }
原文:http://www.cnblogs.com/zhanshiwei/p/3577445.html
内容总结
以上是互联网集市为您收集整理的android音乐播放器+异步加载+缓存+图片加载+listview列表显示+tomcat服务器+xml解析全部内容,希望文章能够帮你解决android音乐播放器+异步加载+缓存+图片加载+listview列表显示+tomcat服务器+xml解析所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。