gpt4 book ai didi

android - 具有自己进程的 IntentService 中的 ANR

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:09:49 27 4
gpt4 key购买 nike

我有一个有自己进程的 IntentService,就像这样:

AndroidManifest.xml

<service 
android:name="com.app.services.UpdateDatabaseService"
android:process=":updateDatabaseService"
android:label="@string/service_name"
android:exported="false" >
</service>

然后当 IntentService 运行时,它会创建两个线程。其中一个任务是一个线程,是一个长任务(超过1分钟)。我遇到了 ANR 问题。

10-24 18:51:27.923: E/ActivityManager(148): ANR in com.app:FooService
10-24 18:51:27.923: E/ActivityManager(148): Reason: Executing service com.app/.services.FooService
10-24 18:51:27.923: E/ActivityManager(148): Load: 1.08 / 0.48 / 0.21
10-24 18:51:27.923: E/ActivityManager(148): CPU usage from 13433ms to 1122ms ago:
10-24 18:51:27.923: E/ActivityManager(148): 92% 1375/com.emanga:updateMangaDatabase: 87% user + 5.7% kernel / faults: 5740 minor
10-24 18:51:27.923: E/ActivityManager(148): 0.4% 148/system_server: 0.2% user + 0.1% kernel / faults: 13 minor
10-24 18:51:27.923: E/ActivityManager(148): 0.2% 45/adbd: 0% user + 0.2% kernel
10-24 18:51:27.923: E/ActivityManager(148): 0.1% 758/logcat: 0% user + 0.1% kernel
10-24 18:51:27.923: E/ActivityManager(148): 0% 266/com.android.phone: 0% user + 0% kernel / faults: 2 minor
10-24 18:51:27.923: E/ActivityManager(148): 93% TOTAL: 87% user + 6.2% kernel + 0% irq
10-24 18:51:27.923: E/ActivityManager(148): CPU usage from 1804ms to 2442ms later:
10-24 18:51:27.923: E/ActivityManager(148): 70% 1375/com.emanga:updateMangaDatabase: 65% user + 4.9% kernel / faults: 123 minor

用户界面在任何时候都不会被阻塞。因此,如果服务在单独的进程(不是 UI 线程)中,为什么会出现此错误?

编辑 1:

我将 IntentService 更改为 Service 但我遇到了同样的问题。我会尝试解释我想要得到的东西。我的应用程序的架构具有显示使用加载程序从数据库恢复的数据的 Activity 。如果数据库没有请求的数据,那么它会请求一个服务,该服务将从互联网恢复数据(该服务管理互联网请求,它解析一些 html,用新数据更新数据库,最后服务通知更改)

此服务有其自己的流程,因为虽然服务会捕获可能发生的异常,但通过这种方式,应用程序可以更稳健地应对 Internet 或解析器故障(应用程序不会崩溃)

加载器的目的是从数据库中获取数据,服务的目的是从互联网获取数据并更新数据库。 Loader 和 Services 之间的通信仅用于通知更改或请求。

最后这个服务有一个任务队列和一个运行任务的执行器。

public class UpdateDatabaseService extends Service {

private static final String ACTION = "com.app.services.UpdateDatabaseService";
public static final String ACTION_TASK_1 = ACTION + ".latestChapters";
public static final String ACTION_TASK_2 = ACTION + ".latestMangas";

private static final byte PARALLELTASKS = 2;

public LinkedBlockingQueue<Runnable> tasks = new LinkedBlockingQueue<Runnable>();

private ExecutorService executor = Executors.newFixedThreadPool(PARALLELTASKS);

private final IBinder mBinder = new MyBinder();

public class MyBinder extends Binder {
public UpdateDatabaseService getService() {
return UpdateDatabaseService.this;
}
}

@Override
public IBinder onBind(Intent arg0) {
return mBinder;
}

@Override
public void onCreate(){
// By default always it does DefaultTask1
tasks.put(new DefaultTask1());

if(!isEmptyTable("tableFoo")){
tasks.put(new DefaultTask2());
}

executor();
}

public int onStartCommand(Intent intent, int flags, int startId) {

if(intent != null && intent.getAction() != null) {

String action = intent.getAction();
if(action == ACTION_TASK_1){
tasks.put(new Task1());
} else
if(action == ACTION_TASK_2){
tasks.put(new Task2());
}
}


// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}

private void executor(){

while(true){
executor.execute(tasks.take());

}


}

最佳答案

每个进程都有一个主应用程序 (UI) 线程。它是调用组件生命周期方法的线程,例如 ServiceonStartCommand()。而且,您不能占用该线程,否则您将收到 ANR。

通常,这不是 IntentService 的问题。没有 IntentService 子类应该创建自己的线程,因此只有两个重要的线程:主应用程序线程和 IntentService 提供的后台线程(调用onHandleIntent())。确保您的所有工作都在 onHandleIntent() 中。如果您自己 fork 其他线程,要么摆脱它们,要么从 IntentService 切换到常规 Service,这样您就可以安排 服务仅在所有您的线程完成其工作时关闭,而不是在onHandleIntent() 完成时关闭。

此外,我强烈建议您摆脱 android:process,因为您在浪费 CPU 和 RAM,对用户没有明显的好处。

关于android - 具有自己进程的 IntentService 中的 ANR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19574652/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com