AsyncTask 只能执行一次

AsyncTask can be executed only once

通过使用Android Studio,我需要设计一个从网站读取数据的移动应用程序

http://sspapi-dev.samsungrs.com/health

并且每分钟刷新一次数据。我面临的问题是 Android 中的 AsyncTask 只能执行一次,所以下次我尝试刷新页面并再次从网站读取数据时,我收到以下错误消息。

2018-12-03 14:48:21.308 5065-5065/com.samsung.asynctaskexample E/AndroidRuntime: FATAL EXCEPTION: main Process: com.samsung.asynctaskexample, PID: 5065 java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once) at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:605) at android.os.AsyncTask.execute(AsyncTask.java:560) at com.samsung.asynctaskexample.MainActivity.updateHTML(MainActivity.java:45) at com.samsung.asynctaskexample.MainActivity.access[=16=]0(MainActivity.java:10) at com.samsung.asynctaskexample.MainActivity.run(MainActivity.java:37) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6682) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

修复此错误消息的不同方法有哪些? 这是我的代码。

MainActivity.java

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity implements AsyncResponse {
    GetMethodDemo asyncTask = new GetMethodDemo();
    TextView t1;
    String website = "http://sspapi-dev.samsungrs.com/health";

    private Timer autoUpdate;
    int refresh_interval = 60000;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        t1 = findViewById(R.id.textview1);

        asyncTask.delegate = this;
    }

    @Override
    public void onResume() {
        super.onResume();
        autoUpdate = new Timer();
        autoUpdate.schedule(new TimerTask() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    public void run() {
                        updateHTML();
                    }
                });
            }
        }, 0, refresh_interval);
    }

    private void updateHTML() {
        asyncTask.execute(website);
    }

    @Override
    public void onPause() {
        autoUpdate.cancel();
        super.onPause();
    }

    @Override
    public void processFinish(String output){
        t1.setText(output);
    }
}

JsonHelper.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class JsonHelper{

    HttpURLConnection connection;
    String data;

    public String getdatafromurl(String url){
        try{
            URL url1 = new URL(url);

            connection = (HttpURLConnection) url1.openConnection();
            connection.connect();
            InputStream inputStream = connection.getInputStream();

            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            String line = "";
            StringBuffer buffer = new StringBuffer();

            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
            String result = buffer.toString();
            return result;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }
}

GetMethodDemo.java

import android.os.AsyncTask;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class GetMethodDemo extends AsyncTask<String, Void, String> {
    public AsyncResponse delegate = null;
    String server_response;

    @Override
    protected String doInBackground(String... strings) {

        URL url;
        HttpURLConnection urlConnection = null;

        try {
            url = new URL(strings[0]);
            urlConnection = (HttpURLConnection) url.openConnection();

            int responseCode = urlConnection.getResponseCode();

            if(responseCode == HttpURLConnection.HTTP_OK){
                server_response = readStream(urlConnection.getInputStream());
            }

            JsonHelper jsonhelper = new JsonHelper();
            String data = jsonhelper.getdatafromurl(strings[0]);

            return data;

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        delegate.processFinish(server_response);
    }

// Converting InputStream to String

    private String readStream(InputStream in) {
        BufferedReader reader = null;
        StringBuffer response = new StringBuffer();
        try {
            reader = new BufferedReader(new InputStreamReader(in));
            String line = "";
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return response.toString();
    }
}

AsyncResponse.java

public interface AsyncResponse {
    void processFinish(String output);
}

顺便利用

while(true) {
            asyncTask.execute(website);

            try
            {
                Thread.sleep(refresh_interval);
            }
            catch(InterruptedException ex)
            {
                break;
            }
        }

我最初尝试过的,似乎是个坏主意,因为 Thread.sleep 功能会干扰其他 Android 应用程序甚至整个 Android 操作系统的性能.我发现按照我上面描述的方式使用 Timer 是一个很好的替代品。

只是我需要找出我需要对代码进行哪些更改才能多次从任何给定的固定网站读取数据,例如,以特定的时间间隔刷新。

您可以做的最简单的事情是为每次调用服务器创建一个不同的 GetMethodDemo 实例。为此,您需要从 activity class 中删除 asyncTask 字段并将 updateHTML() 方法更改为如下所示:

private void updateHTML() {
    GetMethodDemo asyncTask = new GetMethodDemo();
    asyncTask.execute(website);
}

我只想提一下,除了使用计时器和异步任务之外,还有其他替代方法可以实现您的目标。您可以使用 WorkManager + Worker、RxJava 等。我建议您在代码运行后查看其中的一些内容。