一切正常,但搜索栏正在每个列表视图进行更新,但音频正在播放 正确的方式
public class AudioPLayAdapter extends BaseAdapter implements
OnCompletionListener, SeekBar.OnSeekBarChangeListener {
private Activity activity;
private ArrayList<String> al_fname = new ArrayList<String>();
private static LayoutInflater inflater = null;
private boolean flag_play;
private MediaPlayer mPlayer = null;
Handler seekHandler = new Handler();
public AudioPLayAdapter(Activity a, ArrayList<String> al_fname) {
activity = a;
mPlayer = new MediaPlayer();
this.al_fname = al_fname;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View getView(final int position, final View convertView,
final ViewGroup parent) {
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.audi_rec_lv_layout, null);
final Button play_btn = (Button) vi.findViewById(R.id.play_stop_button);
final SeekBar seekBar = (SeekBar) vi.findViewById(R.id.seekbar_play);
play_btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (!flag_play) {
play_btn.setText("Stop");
startPlaying();
flag_play = true;
} else {
play_btn.setText("Play");
mPlayer.stop();
seekBar.setProgress(0);
flag_play = false;
}
}
private void startPlaying() {
// TODO Auto-generated method stub
try {
mPlayer.reset();
FileInputStream rawFile = new FileInputStream(al_fname
.get(position));
Log.e("filename", al_fname.get(position));
mPlayer.setDataSource(rawFile.getFD());
// mPlayer.setDataSource(mFileName);
mPlayer.prepare();
mPlayer.start();
// set Progress bar values
seekBar.setProgress(0);
seekBar.setMax(100);
// seekHandler.postDelayed(updateSeek, 100);
// Updating progress bar
updateProgressBar();
} catch (IOException e) {
Log.e("preparefailed", "prepare() failed");
}
}
private void updateProgressBar() {
// TODO Auto-generated method stub
seekHandler.postDelayed(mUpdateTimeTask, 100);
}
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
long totalDuration = mPlayer.getDuration();
long currentDuration = mPlayer.getCurrentPosition();
String str1 = new String();
// holder.timer_tv.setText(str1.valueOf(currentDuration));
// Updating progress bar
int progress = (int) (getProgressPercentage(
currentDuration, totalDuration));
// Log.d("Progress", ""+progress);
// if(position==holder.seekBar.getId())
// seekBar.setTag(position);
seekBar.setProgress(progress);
// Running this thread after 100 milliseconds
seekHandler.postDelayed(this, 100);
if (!mPlayer.isPlaying()) {
play_btn.setText("Play");
flag_play = false;
}
if (!flag_play)
seekBar.setProgress(0);
}
private int getProgressPercentage(long currentDuration,
long totalDuration) {
// TODO Auto-generated method stub
Double percentage = (double) 0;
long currentSeconds = (int) (currentDuration / 1000);
long totalSeconds = (int) (totalDuration / 1000);
// calculating percentage
percentage = (((double) currentSeconds) / totalSeconds) * 100;
// return percentage
return percentage.intValue();
}
};
});
return vi;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return al_fname.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
}
}
答案 0 :(得分:4)
每次调用getView
时,都会创建一个新的OnClickListener
并添加到该行视图的play_btn
。
这些匿名OnClickListener
中的每一个都有一个字段Runnable mUpdateTimeTask
。这个runnable被发布到处理程序,然后它一次又一次地发布自己。
当一个新行开始播放时,现在有两个Runnable
张贴自己并更新可能不同的搜索栏。每次单击播放时,都会添加一个新的附加runnable。
您想要的是跟踪正在播放的项目,并在不再需要时停止发布可运行的项目。一次最多只能运行1次。甚至可能寻找更好的方式来定期更新搜索栏(如果存在)。
在getView
中如果视图被回收(即它来自convertView
参数),则必须检查视图现在是否用于其他position
,如果它是不同的位置,然后停止更新此行的seekbar
。
所以你需要这样的东西(有些细节仍然缺失,例如歌曲结束时的处理,或者如何停止播放,留作练习):( https://github.com/curobosqui/PlaybackInList/tree/StackoverfllowAnswer的完整演示项目)
public class ListWithSongsActivity extends ListActivity {
private static final int NOT_PLAYING = -1;
private static final String TAG = "SongList";
List<String> mSongs = new ArrayList<String>(50);
private ArrayAdapter<String> mAdapter = null;
private final MediaPlayer mPlayer = new MediaPlayer();
private int mPlayingPosition = NOT_PLAYING;
private Handler mHandler = new Handler();
private PlaybackUpdater mProgressUpdater = new PlaybackUpdater();
public ListWithSongsActivity() {
//add list of songs in your device for sample
mSongs.addAll(Arrays.asList(new String[]{
"/sdcard/Download/B00G2ID7FE_(disc_1)_01_-_Play_Me_(Version).mp3",
"/sdcard/Download/The Slip/10 Demon Seed.mp3"
}));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_list_with_songs);
mAdapter = new ArrayAdapter<String>(this, R.layout.list_item, android.R.id.text1, mSongs) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
ProgressBar pb = (ProgressBar) v.findViewById(R.id.progressBar1); //Cast
if (position == mPlayingPosition) {
//pb.setVisibility(View.VISIBLE);
mProgressUpdater.mBarToUpdate = pb;
mHandler.postDelayed(mProgressUpdater, 100);
} else {
//pb.setVisibility(View.GONE);
pb.setProgress(0);
if (mProgressUpdater.mBarToUpdate == pb) {
//this progress would be updated, but this is the wrong position
mProgressUpdater.mBarToUpdate = null;
}
}
return v;
}
};
setListAdapter(mAdapter);
}
private void stopPlayback()
{
mPlayingPosition = NOT_PLAYING;
mProgressUpdater.mBarToUpdate = null;
mPlayer.stop();
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
//start playing item at position
try {
mPlayer.reset();
mPlayer.setDataSource(mSongs.get(position));
mPlayer.prepare();
mPlayer.start();
mPlayingPosition = position;
mHandler.postDelayed(mProgressUpdater, 500);
//trigger list refresh, this will make progressbar start updating if visible
mAdapter.notifyDataSetChanged();
} catch (IOException e) {
Log.e(TAG, "unable to play: " + mSongs.get(position));
e.printStackTrace();
stopPlayback();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.list_with_songs, menu);
return true;
}
@Override
protected void onStop() {
super.onStop();
mPlayer.stop();
}
private class PlaybackUpdater implements Runnable {
public ProgressBar mBarToUpdate = null;
@Override
public void run() {
if ((mPlayingPosition != NOT_PLAYING) && (null != mBarToUpdate)) {
mBarToUpdate.setProgress( (100*mPlayer.getCurrentPosition() / mPlayer.getDuration()) ); //Cast
mHandler.postDelayed(this, 500);
} else {
//not playing so stop updating
}
}
}
}
使用简单的行布局list_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="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView" />
<ProgressBar
android:id="@+id/progressBar1"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>