在服务中重复从网站获取数据(android)

时间:2016-07-01 00:55:04

标签: android service

我正在编写一个应用程序,应该每隔15分钟从一个网站获取数据(在代码中只需10秒钟来检查它是否可以轻松工作)。我在其中使用服务和处理程序。以下是我的服务类:

应该每隔10秒调用一次getRating(),我使用ION库在其中进行计算,然后调用getData方法。
getData()用于获取x的值(它不能分配给全局变量,因为它在内部类中)。

问题是调用方法getRating之后的代码是在方法完成之前执行的(我尝试在方法内部和之后显示toast,后面的那个显示第一个)因此变量y没有正确更新。

我的问题是为什么会发生这种情况?我应该怎么做才能纠正它? 我在想什么:

  • 以某种方式将方法执行后的代码延迟了足够的时间来完成方法。
  • 或者我应该使用其他方式获取数据?另一个图书馆可能吗?

谢谢。

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 :在我的情况下,我可以保证x的值不会为零,所以我可以在x尚未更新时跳过,这样可以解决问题,但有一些延迟。我怎样才能更有效率地做到这一点?

1 个答案:

答案 0 :(得分:0)

这里有一些问题:

  • Handler中创建Service与在应用主线程中的后台线程中运行不同。
  • 因为Runnable正在重新排队,所以只要系统不处于低功耗模式,它就会继续执行。一旦发生这种情况,您的Service将不再获得执行上下文,并且您的轮询将无效。考虑使用JobScheduler(需要API 21或更新版本)或警报来处理定期请求。
  • 运行RunnablegetRating()代码运行的原因是因为getRating()调用的ION方法是异步。它将在后台线程上正常运行,然后在完成后通过提供的方法回调您的应用程序。如果你在getData()方法中做了类似的事情,那么你可能会遇到类似的问题。