对服务使用 AsyncTask 类仍然得到“跳过 31 帧!应用程序可能在其主线程上做太多工作。”。为啥?

Posted

技术标签:

【中文标题】对服务使用 AsyncTask 类仍然得到“跳过 31 帧!应用程序可能在其主线程上做太多工作。”。为啥?【英文标题】:Using AsynTask class for services still getting " Skipped 31 frames! The application may be doing too much work on its main thread.". WHY?对服务使用 AsyncTask 类仍然得到“跳过 31 帧!应用程序可能在其主线程上做太多工作。”。为什么? 【发布时间】:2021-01-19 06:26:55 【问题描述】:

我刚刚创建了单击按钮的简单服务并在AsynTask 类中启动服务,但在 logcat I/Choreographer 上收到消息:跳过 31 帧!应用程序可能在其主线程上做了太多工作。为什么?

这是我的代码

MainActivity.java

package com.example.servicesandroidtutu;
import androidx.appcompat.app.AppCompatActivity;    
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity 

    private MyAsynTask myAsynTask;
    private Button start, stop;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        start = findViewById(R.id.button);
        stop = findViewById(R.id.button2);

        myAsynTask = new MyAsynTask();

        start.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                myAsynTask.execute();
            
        );

        stop.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                myAsynTask.cancel(true);
            
        );

    

    class MyAsynTask extends AsyncTask<Void,  Void, Void>

        @Override
        protected void onPreExecute() 
            super.onPreExecute();
            startService(new Intent(getApplicationContext(), MyService.class));
        

        @Override
        protected Void doInBackground(Void... voids) 

            return null;
        

        @Override
        protected void onCancelled(Void aVoid) 
            super.onCancelled(aVoid);
            stopService(new Intent(getApplicationContext(), MyService.class));
        
    


MyService.java

   package com.example.servicesandroidtutu;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;

public class MyService extends Service 


    @Nullable
    @Override
    public IBinder onBind(Intent intent) 
        return null;
    

    @Override
    public void onDestroy() 
        super.onDestroy();
        Log.d("Service", "stopped...");

    

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 

        Log.d("Service", "started...");

        return super.onStartCommand(intent, flags, startId);
    

【问题讨论】:

这能回答你的问题吗? ***.com/questions/14678593/…。如果不是EDIT 添加(格式正确)堆栈跟踪的问题。 您不能以这种方式取消您的异步任务,因为当您尝试这样做时它早已完成。所以你也不能停止服务。 【参考方案1】:

您的代码正在进行繁重的处理,需要时间来处理,因此会发生这些跳过的 31 帧。你的服务是做什么的?不要在主线程上执行任何 heave 操作。 更多详情请查看this page

另外,我建议您不要使用 AsyncTask,因为它自 API 30 以来已被弃用。

AsyncTask deprecation

Google 官方推荐使用 Kotlin 协程或 java 线程。

【讨论】:

在我的服务中,我只是记录消息。我也用过 Thread 但还是一样 我还注意到,当您的活动正在销毁时,您还没有取消 onDestroy() 中的 AsyncTask。 @Override protected void onDestroy() if (myAsynTask != null) myAsynTask.cancel(true); super.onDestroy(); 相反,我使用了 onCancelled() 这将破坏 asyntask 以及 stopService 什么时候调用onCancelled?您不应在按钮单击侦听器中调用它以避免内存泄漏

以上是关于对服务使用 AsyncTask 类仍然得到“跳过 31 帧!应用程序可能在其主线程上做太多工作。”。为啥?的主要内容,如果未能解决你的问题,请参考以下文章

AsyncTask 和 SOAP 网络服务

AsyncTask 真的在概念上存在缺陷还是我只是遗漏了啥?

Android AsyncTask问题(连接到Web服务)

在android AsyncTask注册成功时如何移动类?

在其他类中获取 AsyncTask 的输出

AsyncTask - 基本原理 图文剖析