4

私はそのように、独自のプロセスを持つ IntentService を持っています:

AndroidManifest.xml

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

IntentService が実行されると、2 つのスレッドが作成されます。スレッドが長いタスク (1 分以上) であるタスクの 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 がブロックされることはありません。サービスが別のプロセス (UI スレッドではない) にある場合、なぜこのエラーが発生するのでしょうか?

編集1:

IntentService を Service に変更しましたが、まだ同じ問題が発生します。私が得たいものを説明しようとします。私のアプリのアーキテクチャには、ローダーを使用してデータベースから復元されたデータを表示するアクティビティがあります。データベースに要求されたデータがない場合、インターネットからデータを回復するサービスに要求します (サービスはインターネット要求を管理し、いくつかの html を解析し、データベースを新しいデータで更新し、最後にサービスが変更について通知します)。 )

このサービスには独自のプロセスがあります。サービスは発生する可能性のある例外をキャッチしますが、このようにしてアプリはインターネットまたはパーサーの障害に対してより堅牢になります (アプリはクラッシュしません)。

ローダーの目的はデータベースからデータを取得することであり、サービスの目的はインターネットからデータを取得してデータベースを更新することです。ローダーとサービス間の通信は、変更または要求の通知のみを目的としています。

最後に、このサービスには、タスクのキューと、タスクを実行するエグゼキューターがあります。

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());

    }


}
4

1 に答える 1