我有一个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(主机名)
任何想法如何解决?
答案 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