9

我注意到有时异步任务无法正常工作,实际上它的doInBackground()方法不会被调用,服务在该活动的后台运行。 例如,当音乐在带有服务的后台运行时,Async任务不会在后台解析XML,因为它的doInBackground在当时不工作,并且进度对话框或progressBar保持旋转状态。当服务在后台运行时,异步任务无法正常工作(doInBackground未执行),Android

我在几篇文章中读到AsyncTask.THREAD_POOL_EXECUTOR可以在这些问题帮助像:

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
    new Test().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
} else { 
    new Test().execute(); 
} 

没有帮助在我的情况。在上述暗示之后有同样的问题。

这里我给刚刚有点我的示例代码,了解我在做什么::

public class TestAct extends Activity { 

    ImageButton play,forward,backward; 
    private ListView mList; 
    // many more variables 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.test_layout); 

     //binding the service here 
     // start service is called 

     init(); 
    } 

    private void init(){ 

     play=(ImageButton)findViewById(R.id.playBtn); 
     forward=(ImageButton)findViewById(R.id.forward); 
     backward=(ImageButton)findViewById(R.id.backward); 
     mList=(ListView)findViewById(R.id.list); 

     new GetData().execute(); 

     play.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       // calling the play() method of ServiceConnection here 
      } 
     }); 

      // adding header to Listview 
      // other code and click listeners 

    } 

    class GetData extends AsyncTask<Void, Void, Void>{ 

     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 

      // starting the progress Bar 
      // initializing the Arraylist,Maps etc 
     } 

     @Override 
     protected Void doInBackground(Void... params) { 
      //parsing the XML here 
      return null; 
     } 

     @Override 
     protected void onPostExecute(Void result) { 
      super.onPostExecute(result); 

      // stop the ProgressBar 
      // Updating my UI here 
        // setting Adapter for ListView 
     } 
    } 
} 

这工作一般正常,但当服务在backgound运行(我的意思是,当播放音乐时在后面挂)。

我没有得到背后这个异步任务问题的确切原因。 在这种情况下mannual线程实现的帮助...... ??

嗯,我认为这个问题是因为“服务在主线程中运行,所以当它运行时,它会阻止我的AsyncTask运行”......所以我认为如果我们可以在后台线程中运行服务,那可以提供帮助。这就是为什么我尝试IntentService在单独的线程中运行服务,但我怀疑...如果IntentService可以运行无限期类似于服务...并且IntentService几次阻止AsyncTask。 所以我不认为它为这类问题提供了100%完美的解决方案。

任何人都可以帮我解决这个问题,并理解完整的场景。

在此先感谢。

+0

是您扩展业务或IntentService – koti 2013-02-15 09:50:20

+0

我使用的服务,为播放音乐背景 – 2013-02-15 09:54:35

+0

异步任务应该工作。你在某个地方犯了错误。 – Leonidos 2013-02-15 09:57:55

回答

1

这里是一个暗示,如何我终于解决了我的问题::

1)我用IntentService而不是服务作为服务mainThread同时运行IntentService在与mainThread不同的线程中运行,以确保我的后台服务不会影响我当前的任务。此外,我使用AIDL来进行我的用户界面和后台线程之间的通信(这已经适用于服务,因此在这部分中没有任何新功能)。

2)我用无痛线程代替的AsyncTask,我中断线程的onDestroy()方法以确保线程不会无限期继续。

应用似乎比早些时候表现好得多。

希望这将帮助其他人太:)

+0

这是不公平的。人们提出了所有解决方案...... – 2013-02-25 08:32:48

+1

@ user1521536:你说得对,人们向我建议的解决方案,但他们都没有包含我应用的解决方案提示,所以只是为了帮助其他人,我将它们组合在一起以获得更好的解决方案。 – 2014-01-27 07:44:21

1

我认为问题是在上一个完成之前开始另一个GetData AsyncTask。在执行另一个任务之前,确保前一个任务完成。要做到这一点使用以下代码:

// make sure we don't collide with another pending AsyncTask 
if (getDataTask == null || getDataTask.getStatus() == AsyncTask.Status.FINISHED || getDataTask.isCancelled()) { 
    getDataTask= new GetData(); 
    getDataTask.execute(); 
} 

此外,请确保您有运行任务的参考。在您的应用程序正在运行时,您可以使用Application类的子类来执行此操作,或者覆盖onSaveInstanceState(Bundle outState) 并在onCreate(Bundle savedInstanceState)中收到对它的引用。

+0

感谢您的宝贵建议 – 2013-02-22 12:05:33

0

根据Android开发人员AsyncTask文档的线程规则部分,AsyncTask必须在UI线程上创建并启动,因此如果您从服务中的后台线程启动它,则会导致错误行为。

http://developer.android.com/reference/android/os/AsyncTask.html

+1

向任何一个downvoted,我可以问澄清为什么downvote?根据我对用户问题的理解,他将在一个意图服务中启动它,但不会在UI线程上运行,除非我只是用后台线程或IntentService误导有关服务的底层声明。 – 2013-02-22 16:03:48

-2

你真的不应该使用AsyncTasks一般:)有一个很好的解释here。想想如果用户在设备运行的同时旋转设备,会发生什么情况。该活动被重新创建,但该任务在后台运行并持有对“旧”活动的引用。有很多方法可以解决这个问题,而且他们肯定还是有些情况下AsyncTasks是正确的方法。

但是,你真的应该考虑切换到一个Loader或者(如果你觉得冒险的)尝试RoboSpice :)

+0

感谢您的宝贵建议 – 2013-02-22 12:09:33

3

有时候你会想在比什么IntentService向你的服务的生命周期更多的控制权,在这种情况下,你可以只需在服务中创建一个线程并在其中运行后台代码即可。实际上,更具体地说,创建一个包含Looper的HandlerThread,以便您可以在主线程和后台线程之间使用标准的android方法进行通信(消息)。

Answered here

+0

感谢您的宝贵意见 – 2013-02-22 12:09:18

1

阅读已经张贴在这里的所有问题和解答。纠正我,如果我错了你的情况是你解析XML和获取歌曲列表,当用户选择任何歌曲,你想要与服务播放权?

如果场景是正确的,那么我们可以用更简单的方式实现它。

  1. 活动中,onResume()方法解析XML文件并获得歌曲列表,更新列表视图(不开始在这里与服务相关的任何东西)
  2. 当歌用户点击,然后通过特定的键/字符串意图的服务和启动服务
  3. 在服务的OnStartCommand()方法得到的标识,并开始了歌曲作为正常媒体API

这将真正为你做的工作。

关于

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
    new Test().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
} else { 
    new Test().execute(); 
} 

问题这是AsyncTask对不同版本的Android的不同的行为。 查看你的代码正在做的事情是在你正在初始化服务的活动中,因此服务在后台运行而没有做任何有益的事情。 当用户点击播放时,您正在调用创建问题的服务的播放功能。

所以要从Activity中调用服务的功能,您应该正确使用您未提及的AIDL。如果你写了这样的话应该是完美的。

但这里的建议是将歌曲ID传递给服务,它应该从服务播放不应该在活动中调用服务的功能。

,如果你想在活动的onResume更新歌曲列表,那么你必须编写AIDL和完成情况

希望这会有所帮助。

+0

感谢drax您宝贵的建议,但我已经实现了使用IntentService而不是Service的事情,并用无痛线程取代了异步任务,事情工作相当不错:) – 2013-02-22 11:56:53

+1

我已经实现了你的在我的测试项目中的场景。出于这个原因你甚至可以使用AIDL。如果你发现答案接受任何答案。 – 2013-02-22 12:00:26

1

我注意到,有时异步任务工作不正常,其实 其doInBackground()方法不会被调用,出现这种情况主要是

你知道,有AsyncTasks是可以的限制一次执行?我曾经遇到过任务没有开始/正常工作的问题,这是因为我超过了这个数字。有关该主题的更多信息,请查看Android AsyncTask threads limits?

当任何服务在该活动的后台运行时。例如, 音乐在服务后台运行时,Async任务不会在后台解析XML,因为其doInBackground在当时不工作 以及进度对话框或progressBar保持旋转状态。

你检查死锁的可能性(特别是,如果你使用wait()notify())?

嗯,我认为这个问题是因为“服务在主线程中运行,因此 当它运行时,它阻止我的AsyncTask运行” ......所以,我认为如果我们能在后台线程 运行服务那么可以帮助 。这就是为什么我

你要在服务中要做的事情应该在自己的线程运行。这样你就可以确定什么都不会被阻止。例如,如果你有东西需要填充,你可以使用接收器。

希望我能帮助有点...

相关问题