2016-07-01 7 views
0

Ich schrieb eine App, die Daten von einer Website alle 15 Minuten erhalten sollte (im Code sind es 10 Sekunden, nur um zu überprüfen, ob es problemlos funktioniert). Ich benutze einen Service und einen Handler darin. Das Folgende ist meine Serviceklasse:Immer wieder Daten von einer Website innerhalb eines Dienstes (Android)

getRating() sollte alle 10 Sekunden aufgerufen werden, ich mache meine Berechnungen darin mit ION Bibliothek, dann rufen Sie die Methode getData auf.
getData() wird verwendet, um den Wert von x zu erhalten (es kann nicht einer globalen Variablen zugewiesen werden, da es sich um eine innere Klasse handelt).

Das Problem ist, dass der Code nach dem Aufruf der Methode getRating ausgeführt wird, bevor die Methode beendet ist

Meine Frage ist, warum passiert das? und was soll ich tun, um es zu korrigieren?
Was ich darüber nachgedacht:

  • irgendwie die Ausführung des Codes nach dem Verfahren von genügend Zeit verzögert zuerst die Methode zu beenden.
  • Oder sollte ich einen anderen Weg verwenden, um die Daten zu bekommen? vielleicht eine andere Bibliothek?

Vielen Dank.


package com.example.l50.bla; 

import android.app.NotificationManager; 
import android.app.Service; 
import android.content.Context; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.media.MediaPlayer; 
import android.net.ConnectivityManager; 
import android.net.NetworkInfo; 
import android.net.Uri; 
import android.os.Handler; 
import android.os.IBinder; 
import android.support.v7.app.NotificationCompat; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.TextView; 
import android.widget.Toast; 

import java.io.IOException; 
import java.net.HttpURLConnection; 
import java.net.URL; 
import java.util.Timer; 
import java.util.TimerTask; 

import com.koushikdutta.async.future.FutureCallback; 
import com.koushikdutta.ion.Ion; 


public class MyService extends Service { 
    Handler mHandler; 
    int T; 
    void getData(int x) 
    { 
     T=x; 
    } 
    @Override 
    public IBinder onBind(Intent arg0) { 
     return null; 
    } 
    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     return START_STICKY; 
    } 
    @Override 
    public void onCreate() { 
     mHandler = new Handler(); 
     Runnable r = new Runnable() { 
      @Override 
       public void run() { 
       getRating(); 
       int y=T; 

       mHandler.postDelayed(this, 10000); 
      } 
     }; 
     mHandler.postDelayed(r, 10000); 
    } 
    void getRating() { 
     String url ="http://www.somewebsite.com"; 
     Ion.with(getApplicationContext()) 
       .load(url) 
       .asString() 
       .setCallback(new FutureCallback<String>() { 
        @Override 
        public void onCompleted(Exception e, String result) { 
         int x; 
         // do some calculations, the result of these calculations is stored in x 
         getData(x); 
       }); 
    } 
    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     Toast.makeText(this, "Search Stopped", Toast.LENGTH_LONG).show(); 
    } 
} 

UPD: In meinem Fall kann ich garantieren, dass der Wert von x werden nicht Null sein, so kann ich nur überspringen, wenn sie x noch nicht aktualisiert, wird dies das Problem lösen, aber mit etwas Verzögerung. Wie kann ich es effizienter machen?

Antwort

0

Es gibt ein paar Dinge falsch hier:

  • ein Handler in einem Service zu schaffen, ist nicht das gleiche wie in einem Hintergrund-Thread ausgeführt wird, den Haupt-Thread Ihrer Anwendung ab.
  • Da der Runnable gerade neu in die Warteschlange eingereiht wird, wird er nur so lange ausgeführt, wie das System nicht im Energiesparmodus ist. Sobald das passiert, wird Ihr Service keinen Ausführungskontext mehr bekommen und Ihr Polling wird nicht funktionieren. Erwägen Sie, etwas wie JobScheduler (benötigt API 21 oder neuer) oder Alarme zu verwenden, um periodische Anfragen zu bearbeiten.
  • Der Grund Ihrer Runnable Code nach getRating() ausgeführt wird, weil die ION-Methode durch getRating() aufgerufen wird asynchrone ist. Es wird ordnungsgemäß auf einem Hintergrundthread ausgeführt und ruft dann nach Abschluss der App die App über die bereitgestellte Methode zurück. Wenn Sie in Ihrer getData() Methode etwas Ähnliches machen, werden Sie wahrscheinlich auf ein ähnliches Problem stoßen.
+0

Danke für Ihre Antwort. Über den 3. Punkt gibt es eine Möglichkeit, den Code nach 'getRating()' zu verzögern, bis die ION-Methode beendet ist? – joud

+0

Verzögern Sie nicht, nehmen Sie Ihre Aktion im Rückruf. –