在先前被取消后,在 Activity 启动时运行的 AsyncTask 失败
我正在使用 AsyncTask 在应用程序启动时获取联系人的铃声,直到我的 Activity 在 AsyncTask 期间关闭几次后,它才能正常工作,发生这种情况后,AsyncTask 将只能到达 onPreExecute() 而不会 doInBackground ,所以我永远无法获取铃声,直到强制停止或设备重新启动。
谁能解释为什么会发生这种情况?
为什么 AsyncTask 会到达 onPreExecute 但从未运行 doInBackground()?
这是我的代码:(遵循 Shelves 源代码)
public void getRingTone(){
Log.d("cda", "Into getRingTone");
if (audio_service.getStreamVolume(AudioManager.STREAM_RING) > 0) {
if(aRingTone != null){
oRingtone = RingtoneManager.getRingtone(this,
Uri.parse(aRingTone));
}
this.setVolumeControlStream(AudioManager.STREAM_RING);
}
}
private void saveRingToneTask(Bundle outState) {
final SelectRingtoneTask task = srtt;
if (task != null && task.getStatus() != AsyncTask.Status.FINISHED) {
task.cancel(true);
srtt = null;
}
}
private void restoreRingToneTask(Bundle savedInstanceState) {
srtt = (SelectRingtoneTask) new SelectRingtoneTask().execute();
}
private void onAddRingTone() {
srtt = (SelectRingtoneTask) new SelectRingtoneTask().execute();
}
private void onCancelAddRingTone() {
if (srtt != null && srtt.getStatus() == AsyncTask.Status.RUNNING) {
srtt.cancel(true);
srtt = null;
}
}
--
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
restoreRingToneTask(savedInstanceState);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (isFinishing()) {
saveRingToneTask(outState);
}
}
private class SelectRingtoneTask extends AsyncTask<String, Void, Void> {
@Override
public void onPreExecute() {
Log.d("cda", "Into selectRingToneTask - onPreExecute() - " + selectRingtoneFinished);
findViewById(R.id.answercallimage).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
try {
serviceBinder.answer(lineId);
onCancelAddRingTone();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
findViewById(R.id.declinecallimage).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mNotificationManager.cancel(2);
callConnected = false;
try {
serviceBinder.reject(lineId);
onCancelAddRingTone();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
public Void doInBackground(String... params) {
Log.d("cda", "Into selectRingToneTask - !!!!!!!!!!!!!!!");
if(!this.isCancelled()){
getRingTone();
}
return null;
}
@Override
public void onCancelled() {
Log.d("cda", "Into selectRingToneTask - onCancelled() - ");
}
@Override
public void onPostExecute(final Void unused) {
selectRingtoneFinished = true;
Log.d("cda", "Into selectRingToneTask - onPostExecute - " + selectRingtoneFinished);
if(oRingtone != null && playRingTone){
Log.d("cda", "Into getRingTone - PLAY RINGTONE");
oRingtone.play();
}
}
}
onAddRingtone() 用于 onCreate 中, onCancelRingTone() 用于 onDestroy() 中,以及您可以在上面的代码中看到的位置。
我已经花了3天时间解决这个问题,但我还没有找到解决方案?我采取了错误的方法吗?使用取消错误?有错误吗?
I am using an AsyncTask to fetch the ring tone for a contact when my application starts, it works fine until after my Activity closes a couple of times during the AsyncTask, after this happens the AsyncTask will only ever get to onPreExecute() and never doInBackground, so I can never fetch the ringtone then until either a force stop or device restart.
Can anyone explain why this might be happening?
Why the AsyncTask would get to onPreExecute but then never run doInBackground()?
Here is my code: (Following the Shelves source code)
public void getRingTone(){
Log.d("cda", "Into getRingTone");
if (audio_service.getStreamVolume(AudioManager.STREAM_RING) > 0) {
if(aRingTone != null){
oRingtone = RingtoneManager.getRingtone(this,
Uri.parse(aRingTone));
}
this.setVolumeControlStream(AudioManager.STREAM_RING);
}
}
private void saveRingToneTask(Bundle outState) {
final SelectRingtoneTask task = srtt;
if (task != null && task.getStatus() != AsyncTask.Status.FINISHED) {
task.cancel(true);
srtt = null;
}
}
private void restoreRingToneTask(Bundle savedInstanceState) {
srtt = (SelectRingtoneTask) new SelectRingtoneTask().execute();
}
private void onAddRingTone() {
srtt = (SelectRingtoneTask) new SelectRingtoneTask().execute();
}
private void onCancelAddRingTone() {
if (srtt != null && srtt.getStatus() == AsyncTask.Status.RUNNING) {
srtt.cancel(true);
srtt = null;
}
}
--
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
restoreRingToneTask(savedInstanceState);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (isFinishing()) {
saveRingToneTask(outState);
}
}
private class SelectRingtoneTask extends AsyncTask<String, Void, Void> {
@Override
public void onPreExecute() {
Log.d("cda", "Into selectRingToneTask - onPreExecute() - " + selectRingtoneFinished);
findViewById(R.id.answercallimage).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
try {
serviceBinder.answer(lineId);
onCancelAddRingTone();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
findViewById(R.id.declinecallimage).setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mNotificationManager.cancel(2);
callConnected = false;
try {
serviceBinder.reject(lineId);
onCancelAddRingTone();
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
public Void doInBackground(String... params) {
Log.d("cda", "Into selectRingToneTask - !!!!!!!!!!!!!!!");
if(!this.isCancelled()){
getRingTone();
}
return null;
}
@Override
public void onCancelled() {
Log.d("cda", "Into selectRingToneTask - onCancelled() - ");
}
@Override
public void onPostExecute(final Void unused) {
selectRingtoneFinished = true;
Log.d("cda", "Into selectRingToneTask - onPostExecute - " + selectRingtoneFinished);
if(oRingtone != null && playRingTone){
Log.d("cda", "Into getRingTone - PLAY RINGTONE");
oRingtone.play();
}
}
}
And onAddRingtone() is used in onCreate and onCancelRingTone() is used in onDestroy() as well as where you can see if in the code above.
I have spent 3 days on this and I haven't been able to find a solution? Am I taking the wrong approach? Using cancel wrong? Is there a bug?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我相信正在发生的事情是,您的 AsyncTask 拥有旧活动的句柄,当您在任务中间创建一个新活动时,您实际上已经泄漏了 AsyncTask。 DroidFu 库有一个解决方法,通过跟踪重写的 Application 类和依赖于该应用程序的重写的 AsyncTask 中的活动活动。幸运的是它是开源的,所以你可以看到他们是如何做到的。 其他信息< /a>
I believe what is happening is that your AsyncTask has a handle on the old activity, when you create a new one in the middle of the task you have essentially leaked your AsyncTask. The DroidFu library has a workaround for this by keeping track of the active activity in an overridden Application class and an overridden AsyncTask dependent on the Application. Luckily its open source so you can see how they do it. Additional Info