一。Adapter
前面我们得到了Music类和 MusicList类,我们要想得到Music 数据 ,只用调用 MusicList的 getMusicData(Context)就可以了 ,现在我们要将数据显示至少ListView中。
List<Music> listMusic = MusicList.getMusicData(getApplicationContext());
musicAdapter= new MusicAdapter(this , listMusic);
listView.setAdapter(musicAdapter);
在Adapter 中,我们要显示三个数据 , name ,singer ,time .传递进去的变量是 listMusic、
public class MusicAdapter extends BaseAdapter {
Context context;
private List<Music> listMusic;
private LayoutInflater inflater;
private int selectedItem =-1;
private class ViewHolder{
ImageView image;
TextView name;
TextView singer;
TextView time ;
}
public MusicAdapter(Context context,
List<Music> listMusic) {
// TODO Auto-generated constructor stub
this .context=context;
this.listMusic= listMusic;
inflater = LayoutInflater.from(context);
}
public int getSelectedItem() {
return selectedItem;
}
public void setSelectedItem(int selectedItem) {
this.selectedItem = selectedItem;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return listMusic.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return listMusic.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView , ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder;
if (convertView==null){ //第一次展示convertview与内容 的结合
convertView = inflater.inflate(R.layout.musicitem, null);
holder = new ViewHolder();
holder.image = (ImageView) convertView.findViewById(R.id.music_item_image);
holder.name = (TextView)convertView.findViewById(R.id.music_item_name);
holder.singer = (TextView)convertView.findViewById(R.id.music_item_singer);
holder.time = (TextView)convertView.findViewById(R.id.music_item_time);
convertView.setTag(holder);
/*Sets the tag associated with this view. A tag can be used to mark
* a view in its hierarchy and does not have to be unique within the hierarchy.
* Tags can also be used to store data within a view without resorting to
* another data structure.
*/
}else {
holder = (ViewHolder) convertView.getTag();
//将holder 添加到动态生成的View里面
}
Music music = listMusic.get(position);
holder.name.setText(music.getName());
holder.singer.setText(music.getSinger());
holder.time.setText(toTime((int) music.getTime()));
return convertView;
}
public String toTime (int time ){
time/=1000; //原来 为ms
int minute =time /60;
int second = time%60;
return String.format("%02d:%02d", minute,second);
}
}
在这里,我们为了区分是否为被点击 的音乐 ,可以修改所对应的 List 的背景,也就是 convertView 的背景。这就是 selectedItem 的作用。
修改代码 如下:
if (getSelectedItem()==position){
convertView.setBackgroundColor(Color.GRAY); //是被点击 的音乐
}else { //没有点击 的音乐
convertView.setBackgroundColor(Color.TRANSPARENT);
convertView.getBackground().setAlpha(120);
}
return convertView;
除此外,我们还要在 MusicActivity 中,对adapter 里面 selectedItem 进行牡设置。如下。
二。监听 Adapter
当我们点击 listView 上的一个音乐 时,就将这个 position 传递给播放音乐 的界面 OnPlayActivity,然后 OnPlayActivity 可以 将 postion 传递给 Service 以进行音乐 的播放。
OnItemClickListener ItemClick=new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v, int position,
long id ) {
// TODO Auto-generated method stub
musicAdapter.setSelectedItem(position);
musicAdapter.notifyDataSetInvalidated();//让adpater不再变化
Intent i = new Intent(getBaseContext(), OnPlayActivity.class);
i.putExtra("id", position);
startActivity(i);
}
};
这里,我们补充知识
notifyDataSetChanged方法通过一个外部的方法控制如果适配器的内容改变时需要强制调用getView来刷新每个Item的内容。
public void notifyDataSetChanged ()
该方法内部实现了在每个观察者上面调用onChanged事件。每当发现数据集有改变的情况,或者读取到数据的新状态时,就会调用此方法。
public void notifyDataSetInvalidated ()
该方法内部实现了在每个观察者上面调用onInvalidated事件。每当发现数据集监控有改变的情况,比如该数据集不再有效,就会调用此方法。
今天用到Listview刷新功能,之前解决都是给Listview重新负上adapter这样listview就滚动到第一条了,但是这样会有些耗内存,程序写法也不美观。理论上是这样的,需要实验一下,重要的是一下两句话!
notifyDataSetInvalidated(),会重绘控件(还原到初始状态)
notifyDataSetChanged(),重绘当前可见区域