为什么bindservice在将其移动到工作线程后仍会导致应用ANR

时间:2013-12-21 11:57:30

标签: android multithreading

我在onCreate中有一个绑定服务需要很长时间,我试图通过将它移动到工作线程来解决这个问题,但它仍然导致UI等待。我该怎么办

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);


        new Thread(){
            public void run(){
                android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);

                Intent serviceIntent = new Intent(getApplicationContext(), Recognizer.class);
                bindService(serviceIntent, mConnection,Context.BIND_AUTO_CREATE);
            }
        }.start();
}

3 个答案:

答案 0 :(得分:4)

根据您的描述,似乎在UI线程中调用bindService不是ANR的根本原因。相反,您应该在不生成用户线程的情况下调用bindService。一个主要原因是,这会导致内存泄漏。

当配置发生变化时,只要线程仍处于活动状态,它就不会给Activity执行垃圾收集的机会。这是因为您的用户线程仍然引用Activity

ANR根本原因应来自RecognizermConnection。如果您可以发布它们的实施细节,这可以帮助我们帮助您。

问自己以下问题

  1. 您是否在mConnection的onServiceConnected
  2. 中执行任何I / O密集型任务
  3. 您是否在识别器的onCreate
  4. 中执行任何I / O密集型任务
  5. ...

答案 1 :(得分:2)

正如其他人所说,问题不在你的Activity中,而在于你的Service。您的onBind()通话时间过长,主(UI)主题上调用了onBind()。你在onBind()电话中做了太多工作。您需要做的是将Service的初始化从onBind()调用移到单独的后台线程中。为了防止客户端在初始化之前使用Service,您需要为每个绑定客户端保留一个标志,指示后台线程是否已完成初始化。如果客户端在准备好之前尝试使用Service(即:完全初始化),那么您可以返回一些错误代码或抛出一个合适的异常。

请记住,所有Android组件(ActivityServiceBroadcastReceiverContentProvider)中的生命周期调用都在主(UI)线程上运行,并且必须快速运行。

答案 2 :(得分:-1)

问题不在您的活动中。你说你的绑定服务需要很长时间。因此,您必须在服务的onBind方法中创建线程。

public class ClientService extends Service
{
    @Override
    public IBinder onBind(final Intent intent)
    {
        new Thread(){
            public void run(){
                // Your code here
            }
        }.start();
    }
}