java - Android 服务中调度的 AsyncTask 仅正确执行一次

标签 java android multithreading httpclient android-asynctask

我正在尝试创建每 30*1000 毫秒拉取一次 Web 服务器的简单 Android 程序。我的应用程序中有专门的服务 - PollerService

Android Manifest.xml:
<application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".PullServerAndListenActivivty"
        android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service android:name=".PollerService" />
</application>

该类创建计划执行器并注册其计时器任务以开始调用引擎,引擎按顺序拉取服务器。

PollerService.java:

public class PollerService extends Service {
public static final int INTERVAL = 20*1000;
private ScheduledExecutorService executor;

public void onCreate() {
    super.onCreate();
    executor = Executors.newSingleThreadScheduledExecutor();
    executor.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            Engine.tick ();             
        }
    }, 0, INTERVAL, TimeUnit.MILLISECONDS);
}

public void onDestroy() {
    executor.shutdownNow();
}

public IBinder onBind(Intent arg0) {
    return null;
};
}

引擎只是在 GUI 线程中创建 AsyncTask 子类实例并执行它。 onPostExecute 通过在 Activity 中分配的控制台写入一行并调用 UI 组件。

public class Engine {
private static Console console; //Assigned in Activity onCreate
private static Activity context;//Assigned in Activity onCreate 
    ...
public static void tick() {
    final String requestURL = String.format(urlFormat, serverURL);
    try {
        context.runOnUiThread(
                new Runnable () {
                    public void run() {
                        new RequestTask().execute(requestURL);                      
                    };
                }
        );
    }
    catch (Throwable e) {
        Log.e("SBOX", e.getMessage(), e);
    }
}

public static void processCommand(String result) {
    try {
        final Command command = fromJSONToCommand(result);
        context.runOnUiThread(new Runnable() {
            public void run() {
                console.writeLine("Receieved command: " + command);
            }
        });
    } catch (Exception e) {
        Log.e ("SBOX", e.getMessage(), e);      
    }
}

Yak,我从简单的 RequestTask 实例创建开始,我的印象是它会自己在 UI 线程上运行,但试图解决这个问题我终于找到了这种方法,但仍然没有用。只想说我在这里尝试了很多。

RequestTask 看起来像这样,简单的 http 调用:

class RequestTask extends AsyncTask<String, Void, String>{

@Override
protected String doInBackground(String... uri) {
    HttpClient httpclient = new DefaultHttpClient();
    HttpResponse response;
    String responseString = null;
    try {
        response = httpclient.execute(new HttpGet(uri[0]));
        StatusLine statusLine = response.getStatusLine();
        if(statusLine.getStatusCode() == HttpStatus.SC_OK){
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            response.getEntity().writeTo(out);
            out.close();
            responseString = out.toString();
        } else{
            response.getEntity().getContent().close();
            throw new IOException(statusLine.getReasonPhrase());
        }
    } catch (Exception e) {
        Log.e("SBOX", e.getMessage(), e);
    }
    return responseString;
}

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    Engine.processCommand (result);
}
}

所以问题是它只正确运行一次,定时器调度,第一次调用引擎,它运行 RequestTask,它拉服务器,获取响应,在控制台打印它。但是第二次它进入计时器方法,然后服务没有任何生命迹象。 LogCat 无异常,不打印 RequestTask 中的日志。

当然是时候开始调试了,但也许有人可以让我免于这种痛苦并在代码中显示错误?如果评论 Engine.tick() 调用,执行程序本身会完美连续地工作。

对于解决问题的线索将非常有用。

最佳答案

I am trying to create simple Android program that pulls web server every 30*1000 milliseconds.

你肯定是在努力解决它。

第 1 步:在您的 Activity 和服务之间建立一个真实的通信 channel 。不要使用静态数据成员,因为您可能会造成内存泄漏。有很多候选对象(createPendingResult()Messenger 等)。为了这个答案,我假设您将使用广播 Intent,因此选择一些独特的操作字符串并在 onResume 中设置一个 BroadcastReceiver () 在您的 Activity 中收听此类广播(并在 onPause() 中删除该接收器)。

第 2 步:在您的服务中创建一个 pollServer() 方法,该方法具有来自 RequestTaskdoInBackground() 方法的代码.但是,不是返回一个字符串,而是让它发送广播 Intent,将您的字符串作为额外的。

第 3 步:从 ScheduledExecutorService 调用 pollServer(),而不是 Engine.tick()

第 4 步:完全删除 EngineRequestTask

关于java - Android 服务中调度的 AsyncTask 仅正确执行一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8901825/

相关文章:

java - 像素阵列的旋转

java - 如何在 Spring Boot 测试中连接到内存中的 HSQLDB 以进行查询

c++ - 我如何在另一个线程 Qt 中显示 MessageBox

c++ - 如何在 C++ 中使函数线程安全?

android - 即使android应用程序关闭,静态变量是否保留值

java - super.run() 调用后,Thread 类中的控制不会返回

Tomcat 上的 Java Web 应用程序 - 显示用户上传的文件

Java用户名和密码总是返回true

android - org.gradle.api.InvalidUserCodeException : Querying the mapped value of provider (java. util.Set) before task ... 已完成不支持

java - moveToFirst的SQLite数据库函数