7

メイン アクティビティからの入力に基づいて 30 秒ごとにビューを更新するために、IntentService に無限ループがあります。

public class IntentServiceTest extends IntentService {

String Tag = "IntentServiceTest";
String ACTION_RCV_MESSAGE = "com.jsouptest8.intent.action.MESSAGE";

public IntentServiceTest(){
    super("IntentServiceTest");
    Log.d(Tag, "IntentServiceTest constructor");
}

@Override
protected void onHandleIntent(Intent intent) {
    // TODO Auto-generated method stub
    Log.d(Tag, "in onHandleIntent");
    String url = intent.getStringExtra("URL");
    Document doc;
    int i=0;
    try{
      while(true){
         Log.d(Tag, "entered try block...");
         Log.d(Tag, "url = "+url);
         doc = Jsoup.connect(url)
         .get();

       Log.d(Tag, "past Jsoup.connect");
         Element data = doc.select("table").get(1).attr("bgcolor", "#f4f36f");
         Log.d(Tag, data.toString());
         Log.d(Tag, data.text());
         Log.d(Tag, "creating intent...");
         Intent broadcastIntent = new Intent();
         Log.d(Tag, "setting action...");
         broadcastIntent.setAction(ACTION_RCV_MESSAGE);
         broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
         broadcastIntent.putExtra("OUTPUT", data.toString());
         Log.d(Tag, "sending broadcast: "+(i++));
         sendBroadcast(broadcastIntent);
         Thread.sleep(30*1000);
      }
    }
    catch(StackOverflowError e){
        Log.d(Tag, "in StackOverflowError block...");
        Log.d(Tag, "creating intent...");
        Intent broadcastIntent = new Intent();
        Log.d(Tag, "setting action...");
        broadcastIntent.setAction(ACTION_RCV_MESSAGE);
        broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
        broadcastIntent.putExtra("OUTPUT", "系統忙線中, 請稍後再試");
        Log.d(Tag, "sending broadcast...");
        sendBroadcast(broadcastIntent);
    }
    catch(Exception e){
        Log.d(Tag, "in catch Exception block...");   
        onHandleIntent(intent);
    }
}

}

問題は、私がこのループに陥っていることです。メインアクティビティを強制終了してからそれに戻って新しい入力を入力しても、古い入力に基づいて IntentService が返されます。

行き詰まることなく、30 秒ごとに URL から自分自身を更新する方法を知る必要があります。ありがとう!

4

4 に答える 4

7

anIntentServiceは、タスクを終了して戻ることを意味します。このタスクは新しいスレッドで実行されます。IntentService で while ループを使用しないでください。あなたIntentServiceはいつか殺されます。私は個人的な経験からこれを言っています。その中でwhileループを使ってみました。while ループの最後で、sleep(60000)つまり 1 分を使用しました。しかし、しばらくして IntentService が強制終了されたことがわかりました。

一部の人がシグジェストしたため、AlarmManager を 30 秒間使用しないことをお勧めします。30秒では短すぎるからです。それはバッテリーを消耗します。AlarmManager の場合、RTCで最低 1 分間使用します。

それでも30秒にしたい場合は、サービスを使用してください。サービスでは、ロジックを使用します。ただし、別のスレッドでそれを行います。つまり、サービスで新しいスレッドを生成し、そこで while ループを使用して、sleep(). startForeGroundを使用することを忘れないでください。これにより、Android がサービスを強制終了する可能性が大幅に減少します。

于 2012-09-25T12:30:51.563 に答える
2

IntentService内でwhileステートメントを使用すること、またはそのことについてはあらゆる種類のサービスを使用することはお勧めできません。IntentServiceはタスクを終了してから自動的に終了することになっているため、IntentService内では特に悪い考えです。つまり、IntentServiceを使用するという目的全体を無効にすることになります。

IntentServiceのループを削除し、アラームを使用して30秒ごとにIntentServiceをウェイクアップすることをお勧めします。そうすれば、サービスは確実に30秒ごとに呼び出され、処理されていない間は実際にスリープ状態に戻ることができます。さらに、IntentServiceが古いリクエストを処理しているときにIntentServiceへの新しい呼び出しを受信した場合を処理するために、IntentServiceのonStartCommandメソッドにコードを追加して、呼び出しを処理のためにキューに入れるか、完全に無視するかを確認できます。

この方法を使用してアラームを設定します。

public void setRepeating(int型、long triggerAtMillis、longintervalMillis、PendingIntent操作)

リンク: http: //goo.gl/E9e6

より効率的なアプローチについては、setInexactRepeatingを使用してください(ただし、30秒のウェイクアップを保証するものではありません)

PS。通常、IntentServiceのonStartCommandをオーバーライドすることはありませんが、アプリが実際にその機能を使用している場合はオーバーライドできます。

于 2012-08-18T09:21:38.093 に答える
1

このリンクでは、タイマーを使用して自分自身を更新するサービスを見つけることができます

サービスを実行し続ける

while ループに慣れている場合は、ループが存在する if ステートメントを記述します。

if(thisIsTrue)
 {
   break; // this will exit the loop!
 }
于 2012-08-18T07:24:16.340 に答える
0

ループやタイマーなどの実行中のタスクをMainActivityそれ自体に保持し、毎回 IntentService を実行する方がよいでしょう。IntentService毎回タスクを実行して終了するか、さらにタスクを実行するためqueueです。

ドキュメントから -

IntentService はインテントを受け取り、ワーカー スレッドを起動し、必要に応じてサービスを停止します。

work queue processorパターンを使用してタスクを維持します。

于 2012-08-18T07:35:08.470 に答える