我的app recyclerview将audio,imageview,textview作为项目。滚动Recyclerview时,如果项目未更新,则滚动正确,没有任何问题。但是在播放recyclerview的音频项目时滚动recyclelerview并不流畅,它的行为与下面附加的gif图像相同。在播放音频时,我正在更新textview中的音频当前播放时间。我不确定这里有什么问题。请帮助我。感谢。
这是我的代码。
public class MessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
ArrayList<SessionHistoryMesssage> messageArrayList;
MediaPlayer mPlayer = null;
LocalService mService;
boolean mBound = false;
private RelativeLayout.LayoutParams params;
int currentlyPlayingPosition = -1;
public String mBasePath = "", imageDirectory = "", mSessionId = "", audioDirectory = "";
private ProgressDialog progressDialog;
public RetrofitRestAdapter retrofitRestAdapter;
private MessageAdapter messageListAdapter;
private SessionHistoryResponse sessionHistoryResponse;
public Context mContext;
private int mSelectionPosition = -1;
private int num = 0;
public boolean isSessionStarted=false;
public static Handler mHandler;
public int playposition = -1, sessionstartPosition = -1, alreadystartPosition = -1, sessionendPosition = -1;
public MessageAdapter(Context mContext
, ArrayList<SessionHistoryMesssage> messageArrayList, String mBasePath) {
this.mContext = mContext;
this.messageArrayList = messageArrayList;
this.mBasePath = mBasePath;
mHandler = new Handler();
Intent intent = new Intent(mContext, LocalService.class);
this.mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
// 1. Type a) SEND b) RECEIVE
// 2. Message a) AUDIO b) IMAGE
@Override
public int getItemViewType(int position) {
// Just as an example, return 0 or 2 depending on position
// Note that unlike in ListView adapters, types don't have to be contiguous
Log.i("ViewType", messageArrayList.get(position).getmMediaType() + "");
Log.i("sent by", messageArrayList.get(position).getmSentBy() + "");
return Integer.parseInt(messageArrayList.get(position).getmSentBy());
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
VHItemAudio dataObjectHolder = null;
if (Integer.parseInt(Utility.readPatientId(mContext)) == viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout_a_conversation_item, parent, false);
dataObjectHolder = new VHItemAudio(view);
return dataObjectHolder;
} else {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout_b_conversation_item, parent, false);
dataObjectHolder = new VHItemAudio(view);
return dataObjectHolder;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
final VHItemAudio vhItemHolder = (VHItemAudio) holder;
vhItemHolder.bind(messageArrayList.get(position), position);
}
public class VHItemAudio extends RecyclerView.ViewHolder {
ImageView playPauseImageView, imgDownloadAudio, imgDownloadImage;
TextView txtImageSendTime, runningTimerTextView, txtAudioSendTime, txtSessionStart;
SeekBar seekBar;
ImageView imageView;
RelativeLayout layoutAudio, layoutImage, layoutdownloadImage, layoutSessionStart;
ProgressBar progressImageDownload, progressAudioDownload;
private ImageView imageShareImageView,recordAudioImageView,imgEndSession;
public VHItemAudio(View itemView) {
super(itemView);
playPauseImageView = (ImageView) itemView.findViewById(R.id.playPauseImageView);
txtImageSendTime = (TextView) itemView.findViewById(R.id.txtImageSendTime);
runningTimerTextView = (TextView) itemView.findViewById(R.id.runningTimerTextView);
seekBar = (SeekBar) itemView.findViewById(R.id.seekBar);
imgDownloadAudio = (ImageView) itemView.findViewById(R.id.imgDownloadAudio);
imgDownloadImage = (ImageView) itemView.findViewById(R.id.imgDownloadImage);
imageView = (ImageView) itemView.findViewById(R.id.imageView);
txtAudioSendTime = (TextView) itemView.findViewById(R.id.txtAudioSendTime);
layoutAudio = (RelativeLayout) itemView.findViewById(R.id.layoutAudio);
layoutImage = (RelativeLayout) itemView.findViewById(R.id.layoutImage);
layoutdownloadImage = (RelativeLayout) itemView.findViewById(R.id.layoutdownloadImage);
progressImageDownload = (ProgressBar) itemView.findViewById(R.id.progressImageDownload);
progressAudioDownload = (ProgressBar) itemView.findViewById(R.id.progressAudioDownload);
layoutSessionStart = (RelativeLayout) itemView.findViewById(R.id.layoutSessionStart);
txtSessionStart = (TextView) itemView.findViewById(R.id.txtSessionStart);
Log.i("", "Adding Listener");
imageShareImageView= (ImageView) ((PatientActivity)PatientActivity.patientContext).findViewById(R.id.imageShareImageView);
recordAudioImageView= (ImageView) ((PatientActivity) PatientActivity.patientContext).findViewById(R.id.recordAudioImageView);
imgEndSession= (ImageView) ((PatientActivity) PatientActivity.patientContext).findViewById(R.id.imgEndSession);
}
public void bind(final SessionHistoryMesssage sessionHistoryMesssage, final int position) {
if (sessionHistoryMesssage.getmSessionStart().equalsIgnoreCase("yes")
&& Integer.parseInt(sessionHistoryMesssage.getmTransToId())
== Integer.parseInt(Utility.readPatientId(mContext))) {
sessionstartPosition = position;
isSessionStarted=true;
} else if (sessionHistoryMesssage.getmSessionStart().equalsIgnoreCase("already started")) {
alreadystartPosition = position;
} else if (sessionHistoryMesssage.getmSessionStart().equalsIgnoreCase("end")) {
sessionendPosition = position;
} else {
}
if (sessionHistoryMesssage.getmMediaType().equalsIgnoreCase("audio")) {
layoutAudio.setVisibility(View.VISIBLE);
layoutImage.setVisibility(View.GONE);
seekBar.setFocusable(false);
txtAudioSendTime.setText(Utility.convertDateTime(sessionHistoryMesssage.getmSentTime()));
audioDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/A/Audio/";
File file = new File(Environment.getExternalStorageDirectory()
+ "/A/Audio/" + messageArrayList.get(position).getmMediaValue());
if (file.exists()) {
imgDownloadAudio.setVisibility(View.GONE);
playPauseImageView.setVisibility(View.VISIBLE);
playPauseImageView.setImageResource(R.drawable.play_icon);
} else {
imgDownloadAudio.setVisibility(View.VISIBLE);
playPauseImageView.setVisibility(View.GONE);
imgDownloadAudio.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
imgDownloadAudio.setVisibility(View.GONE);
Log.v("basepath", mBasePath);
new DownloadFile(mBasePath + messageArrayList.get(position).getmMediaPath() +
messageArrayList.get(position).getmMediaValue(),
audioDirectory + messageArrayList.get(position).getmMediaValue()
, imgDownloadAudio, progressAudioDownload).execute();
}
});
}
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (playposition == position) {
int seekBarPosition = seekBar.getProgress();
mPlayer.seekTo(seekBarPosition);
}
}
});
playPauseImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!mService.isPlaying()) {
playposition = position;
mService.playAudio(audioDirectory + messageArrayList.get(position).getmMediaValue());
notifyDataSetChanged();
} else {
if (playposition == position) {
playposition = -1;
mHandler.removeCallbacks(null);
mService.stopAudio();
notifyDataSetChanged();
} else {
playposition = position;
mService.playAudio(audioDirectory + messageArrayList.get(position).getmMediaValue());
notifyDataSetChanged();
}
}
}
});
} else if (messageArrayList.get(position).getmMediaType().equalsIgnoreCase("photo")) {
layoutImage.setVisibility(View.VISIBLE);
layoutAudio.setVisibility(View.GONE);
txtImageSendTime.setText(Utility.convertDateTime(messageArrayList.get(position).getmSentTime()));
imageDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/A/Image/";
Log.v("image path123", mBasePath + messageArrayList.get(position).getmMediaPath()
+ messageArrayList.get(position).getmMediaValue());
try {
File file = new File(Environment.getExternalStorageDirectory()
+ "/A/Image/" + messageArrayList.get(position).getmMediaValue());
if (!file.exists()) {
layoutdownloadImage.setVisibility(View.VISIBLE);
imageView.setVisibility(View.GONE);
} else {
layoutdownloadImage.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
imageView.setImageBitmap(BitmapFactory.decodeFile(file.getAbsolutePath()));
}
layoutdownloadImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mSessionId = messageArrayList.get(position).getmSessionId();
imgDownloadImage.setVisibility(View.GONE);
new DownloadImage(mBasePath + messageArrayList.get(position).getmMediaPath()
+ sessionHistoryMesssage.getmMediaValue(),
sessionHistoryMesssage.getmMediaValue(),
imgDownloadImage, progressImageDownload
).execute();
}
});
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showImageDialog(position);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
if (sessionstartPosition == position) {
layoutSessionStart.setVisibility(View.VISIBLE);
layoutAudio.setVisibility(View.GONE);
layoutImage.setVisibility(View.GONE);
txtSessionStart.setText("Start session");
if (sessionHistoryMesssage.getmMediaType().equalsIgnoreCase("audio")) {
params = (RelativeLayout.LayoutParams) layoutSessionStart.getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.layoutAudio);
} else if (sessionHistoryMesssage.getmMediaType().equalsIgnoreCase("photo")) {
params = (RelativeLayout.LayoutParams) layoutSessionStart.getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.layoutImage);
} else {
}
if(!isSessionStarted) {
imageShareImageView.setVisibility(View.GONE);
recordAudioImageView.setVisibility(View.GONE);
imgEndSession.setVisibility(View.GONE);
isSessionStarted=true;
}
txtSessionStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
retrofitRestAdapter = new RetrofitRestAdapter();
Map<String, String> sessionstartParams = new HashMap<String, String>();
sessionstartParams.put("session_id", sessionHistoryMesssage.getmSessionId());
final ProgressDialog progressDialog = new ProgressDialog(mContext);
progressDialog.setTitle("Please wait...");
progressDialog.show();
retrofitRestAdapter.sessionStart(sessionstartParams, new Callback<SessionHistoryResponse>() {
@Override
public void onResponse(Call<SessionHistoryResponse> call, Response<SessionHistoryResponse> response) {
Log.v("session start response", new Gson().toJson(response.body()));
progressDialog.dismiss();
txtSessionStart.setEnabled(false);
txtSessionStart.setClickable(false);
imageShareImageView.setVisibility(View.VISIBLE);
recordAudioImageView.setVisibility(View.VISIBLE);
imgEndSession.setVisibility(View.VISIBLE);
}
@Override
public void onFailure(Call<SessionHistoryResponse> call, Throwable t) {
t.printStackTrace();
progressDialog.dismiss();
imageShareImageView.setVisibility(View.GONE);
recordAudioImageView.setVisibility(View.GONE);
imgEndSession.setVisibility(View.GONE);
}
});
}
});
} else {
}
if (position == alreadystartPosition) {
layoutSessionStart.setClickable(false);
txtSessionStart.setClickable(false);
imageShareImageView.setVisibility(View.VISIBLE);
recordAudioImageView.setVisibility(View.VISIBLE);
imgEndSession.setVisibility(View.VISIBLE);
} else {
}
if (position == sessionendPosition) {
layoutSessionStart.setClickable(false);
txtSessionStart.setClickable(false);
// layoutSessionStart.setVisibility(View.VISIBLE);
txtSessionStart.setText("End session");
if (sessionHistoryMesssage.getmMediaType().equalsIgnoreCase("audio")) {
params = (RelativeLayout.LayoutParams) layoutSessionStart.getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.layoutAudio);
} else if (sessionHistoryMesssage.getmMediaType().equalsIgnoreCase("photo")) {
params = (RelativeLayout.LayoutParams) layoutSessionStart.getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.layoutImage);
} else {
}
imageShareImageView.setVisibility(View.GONE);
recordAudioImageView.setVisibility(View.GONE);
imgEndSession.setVisibility(View.GONE);
} else {
}
if (position == playposition) {
if (mBound) {
Log.v("service", "bound");
mHandler.removeCallbacks(null);
seekBar.setMax(mService.getrunningTime() / 1000);
Log.v("duration", mService.getrunningTime() + "");
playPauseImageView.setImageResource(R.drawable.stop_icon);
((PatientActivity) mContext).runOnUiThread(new Runnable() {
@Override
public void run() {
if (mService.isPlaying()) {
num = mService.getDuration();
seekBar.setProgress(num / 1000);
runningTimerTextView.setText(convertMilliToMinutes(num));
// vhItemHolder.seekBar.setFocusable(false);
mHandler.postDelayed(this, 50);
} else {
playposition = -1;
mHandler.removeCallbacks(null);
seekBar.setProgress(0);
seekBar.setFocusable(false);
runningTimerTextView.setText("00:00");
playPauseImageView.setImageResource(R.drawable.play_icon);
}
}
});
} else {
Log.v("service", "not bound");
}
} else {
mHandler.removeCallbacks(null);
playPauseImageView.setImageResource(R.drawable.play_icon);
runningTimerTextView.setText("00:00");
seekBar.setMax(0);
}
}
}
服务类
public class LocalService extends Service {
boolean mBound = false;
private final IBinder mBinder = new LocalBinder();
private int timer;
private MediaPlayer mediaPlayer = new MediaPlayer();
private boolean isStopped = true;
// Random number generator
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
public LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public int getrunningTime() {
return mediaPlayer.getDuration();
}
public int getDuration() {
// Log.v("player duration",timer+"");
if (mediaPlayer != null) {
if (!isStopped) {
Log.v("playing", (mediaPlayer.getCurrentPosition()) + "");
return mediaPlayer.getCurrentPosition();
} else {
// mediaPlayer.reset();
mHandler.removeCallbacks(null);
return 0;
}
} else {
Log.v("not playing", (mediaPlayer.getCurrentPosition()) + "");
mHandler.removeCallbacks(null);
return 0;
}
}
@Override
public void onCreate() {
super.onCreate();
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
isStopped = false;
//playAudio();
Log.v("max duration", timer + "");
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
//mediaPlayer.stop();
isStopped = true;
mediaPlayer.reset();
//mediaPlayer.release();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean isPlaying() {
if (mediaPlayer != null) {
try {
if (mediaPlayer.isPlaying()) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
} else {
return false;
}
}
public void playAudio(String path) {
Log.v("audio path",path);
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.reset();
try {
mediaPlayer.setDataSource(path);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public void stopAudio() {
if (mediaPlayer != null) {
mediaPlayer.stop();
// mediaPlayer.reset();
isStopped = true;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
@Override
public void unbindService(ServiceConnection conn) {
super.unbindService(conn);
mediaPlayer.reset();
mediaPlayer.release();
}
@Override
public void onDestroy() {
super.onDestroy();
mediaPlayer.reset();
mediaPlayer.release();
}
}
答案 0 :(得分:0)
因为您正在调用notifyDataSetChanged(),并且只要您这样做,它就会更新整个recyclerview。您最好调用notifyItemChanged(position)来更新您应该更新的特定项目。
((PatientActivity) mContext).runOnUiThread(new Runnable() {
@Override
public void run() {
if (mService.isPlaying()) {
num = mService.getDuration();
seekBar.setProgress(num / 1000);
runningTimerTextView.setText(convertMilliToMinutes(num));
// vhItemHolder.seekBar.setFocusable(false);
mHandler.postDelayed(this, 50);
} else {
playposition = -1;
mHandler.removeCallbacks(null);
seekBar.setProgress(0);
seekBar.setFocusable(false);
runningTimerTextView.setText("00:00");
playPauseImageView.setImageResource(R.drawable.play_icon);
}
}
});
你可以把它转换成类似的东西。
if (position == playposition) {
if (mBound) {
Log.v("service", "bound");
mHandler.removeCallbacks(null);
seekBar.setMax(mService.getrunningTime() / 1000);
Log.v("duration", mService.getrunningTime() + "");
playPauseImageView.setImageResource(R.drawable.stop_icon);
if (mService.isPlaying()) {
num = mService.getDuration();
seekBar.setProgress(num / 1000);
runningTimerTextView.setText(convertMilliToMinutes(num));
// vhItemHolder.seekBar.setFocusable(false);
notifyItemChanged(position);
} else {
playposition = -1;
mHandler.removeCallbacks(null);
seekBar.setProgress(0);
seekBar.setFocusable(false);
runningTimerTextView.setText("00:00");
playPauseImageView.setImageResource(R.drawable.play_icon);
notifyItemChanged(position);
}
}
}
尝试删除runnable的全部用法。
答案 1 :(得分:0)
setHasStableIds(真);在适配器构造函数中添加它,并在适配器中覆盖这两个方法。
@Override
public long getItemId(int pos) {
return pos;
}
@Override
public int getItemViewType(int pos) {
//return pos;
return Integer.parseInt(messageArrayList.get(position).getmSentBy());
}
它可能对你有帮助......