用户在播映音效的时分,偶现ANR现象,友盟上传上来的log如下

Mediaplayer.prepare()导致的ANR问题

能够发现,在履行Mediaplayer.prepare方法的时分ANR了

原因分析:

Mediaplappearayer有两个准备资approach源的方法,一个是prepare,还有一个prepareAsync方法,这两个方法的差异是,一个是同步的,一个是异步的

咱们看一下pre源码网站pare和prepareAsynjavaeec的源码(C++层)

stAPPatus_t MediaPlayer::preparapprovee()
{
ALOGV("prepare");
Mutex::Autolock _l(mLock);
mLockThreadId = getThreadId();
if (mPrepareSync) {
mLockThreadId = 0;
return -EALREADY;
}
mPrepareSync = true;
status_t re线程安全t = prepareAsync_l();
if (ret != NO_ERROR) {
mLockThreadId = 0;
return ret;
}
if (mPrepareSync) {
mSignal.wjava根底知识点ait(mLock);  // wait for prepare done
mPrepareSync = false;
}
ALOGV("prepare complete - status=%d", mPappointmentrepareStatus);
mLockThreadId =java编译器 0;
retu源码网站rn mPrepareStatus;
}
status_t MediaPlayer::prepareAsync()
{
AappstoreLOGV("prepareAsync");
Mutex::Autolock _l(mLock);
reappointmentturn prepareAsjava怎么读ync_l();
}

从源码咱们能够看出,不管是prepa源码re和prepareAsync方法,毕竟都会调用到prepa线程的几种状况reAsync源码编辑器_l(),可是prepare多了一段

  if (mPrepareSync) {
mSignal.wait(mLock)线程同步;  // wait for prepare done
mPrepareSync = false;
}

这儿调用了wait方法使播映线程等待资源的源码编辑器手机版下载准备,所以使得java层达到了同步调用的作用,然后线程和进程的差异是什么在prepare完成之线程同步后会调用notify方法唤醒播映线程,代码如下

  void MediaPlayer::notify(int msg, int ext1, int e源码共享网xt2, const Parcel *obj)
{
...
case MEDIA_PREPARED:appointment
ALOGV("prepared");
mCurrentState = MEDIA_PLAYER_PREPARED;
if (mPrepareSync) {
ALOGV("signal application thread");
mPrepareSync = false;
mPrepareStatus = Njava就业培训班O_ERROR;
mSi源码编辑器手机版下载gnal.signal();
}
break;
}

通过看源码,公开能够确认是因为prepare方法相似直接在当前线程去读取资源,即便资源文件是一个网络资源,当网络条件比较差即弱网情况下时,那么发生ANR的几率就会十分高了,源码编辑器手机版下载而且假appear设央求间断或许文件不完整,也会导致播映失利,解决方法之一的话java根底知识点能够选用下面的方法去播映一个语音

  MediaPlappreciateayer mediaPlayer = new MediaPlay源码编辑器编程猫下载er()java言语;
mediaPlayer.setDataSource(url);
mejava就业培训班diaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});