Android AsyncTask每x分钟执行一次

时间:2015-02-25 00:38:44

标签: android android-asynctask timertask

我有一个AsyncTask什么ping一些服务器,我也创建一个Timer但是当我尝试执行时我有一个错误

02-25 02:13:42.645  22313-22313/info.senyk.ustat E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: info.senyk.ustat, PID: 22313
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:579)
        at android.os.AsyncTask.execute(AsyncTask.java:535)
        at info.senyk.ustat.StatsActivity$PingTimer$1$1.run(StatsActivity.java:190)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:155)
        at android.app.ActivityThread.main(ActivityThread.java:5696)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)

我的活动

public class StatsActivity extends ActionBarActivity {

View mDecorView;

String Login = "0";
String PWD = "0";
String Hostname = "0";
String Port = "0";

String PingResult= "";


PingAsync pingasync;
Ping ping = new Ping();


TextView InfoPing;


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

    mDecorView = getWindow().getDecorView();

    Login = getIntent().getExtras().getString("Login");
    PWD = getIntent().getExtras().getString("PWD");
    Hostname = getIntent().getExtras().getString("Hostname");
    Port = getIntent().getExtras().getString("Port");

    TextView InfoServerId = (TextView) findViewById(R.id.textViewServerId);
    InfoServerId.setText(Login + ":" + PWD + "@" + Hostname + ":" + Port);

    InfoPing = (TextView) findViewById(R.id.textViewPing);

    pingasync = new PingAsync();
    pingasync.execute();

}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_stats, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
        mDecorView.setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);}
}

public void click(View view) {
    PingTimer pingTimer = new PingTimer();
    pingTimer.startTimer();

}


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

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        InfoPing.setText("Ping ...");
    }

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

        PingResult = ping.ping(Hostname);

        return PingResult;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        InfoPing.setText(result);

    }

}


public class PingTimer extends ActionBarActivity {

    Timer timer;
    TimerTask timerTask;

    final Handler handler = new Handler();

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

    @Override
    protected void onResume() {
        super.onResume();
        startTimer();
    }

    public void startTimer() {
        timer = new Timer();


        initializeTimerTask();
        timer.schedule(timerTask, 5000, 10000);
    }

    public void stoptimertask(View v) {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }

    public void initializeTimerTask() {

        timerTask = new TimerTask() {
            public void run() {
                handler.post(new Runnable() {
                    public void run() {

                        pingasync.execute();


                    }
                });
            }
        };
    }
}

据我所知AsyncTask已经执行但是如果我使用

InfoPing.setText(ping.ping(主机名));

代替

pingasync.execute();

我的活动冻结执行ping.ping(主机名)

任何想法如何解决?

2 个答案:

答案 0 :(得分:3)

根据文档,AsyncTasks只能执行一次。尝试在计时器运行中重新初始化它。

public void initializeTimerTask() {
    timerTask = new TimerTask() {
        public void run() {
            handler.post(new Runnable() {
                public void run() {
                    new PingAsyncTask().execute();
                }
            });
        }
    };
}
  

线程规则:

     

此类必须遵循一些线程规则才能正常工作:

     

必须在UI线程上加载AsyncTask类。这是从JELLY_BEAN开始自动完成的。       必须在UI线程上创建任务实例。   必须在UI线程上调用execute(Params ...)。   不要手动调用onPreExecute(),onPostExecute(Result),doInBackground(Params ...),onProgressUpdate(Progress ...)。   该任务只能执行一次(如果尝试第二次执行,则会抛出异常。)

http://developer.android.com/reference/android/os/AsyncTask.html

此外,在这种情况下使用Handler而不是TimerTask()是一种更好的做法。

答案 1 :(得分:0)

LogCat,我们可以知道,当您的应用首先打开时,您的PingAsync()会被执行:

java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)

因此,请勿在{{1​​}}方法中调用execute(),在事件开始时调用它,例如按onCreate()。但是我们必须在这里初始化它:

Button