我有两个简单的类:
public class MainActivity extends Activity {
NetworkTask task;
@Override
protected void onCreate(Bundle savedInstanceState) {
[...]
task = new NetworkTask();
task.execute();
}
public void myClickHandler(View view) {
switch(view.getId()) {
case R.id.button1:
// Why this line crash?
task.connection("127.0.0.1");
break;
}
}
}
和
public class NetworkTask extends AsyncTask<String, Void, String> {
Socket sock;
volatile boolean running = true;
public int connection(String url){
try{
sock = new Socket(url, 4567)
}
catch (IOException ex){
Logger.getLogger(NetworkTask.class.getName()).log(Level.SEVERE, null, ex);
return -1;
}
}
public String doInBackground(String... strings) {
// If I do this, it works well
//connection(127.0.0.1);
while(running)
{
[...]
}
return null;
}
}
当我从AsyncTask方法的外部调用连接方法时,我评论说,应用程序崩溃了更多特别的«sock = new Socket(...)»行。但是当在AsynTask方法内部完成连接调用时,会创建套接字。 我不明白为什么。
发生了什么事?
感谢。
答案 0 :(得分:4)
这是因为你做的时候
task.connection("127.0.0.1");
您仍然在主(UI)线程中工作 - 您没有正确使用AsyncTask。相反,你就像普通的课程一样使用它,因此,你会在新的Android版本上获得NetworkOnMainThreadException
。
然而,当您从doInBackground()
致电时,这意味着您通过execute
启动了AsyncTask,并且工作在单独的主题中完成,让一切正常运行。
请记住,如果您正在进行非网络活动,您仍然可以从外部拨打电话。但是,我建议尽可能少地保持AsyncTask依赖于外部,因为AsyncTasks只运行一次。如果你想做更多工作,那么你必须创建一个新实例,这意味着如果你依赖setter方法或类似方法,你必须确保再次调用这些方法,这使得这个简单的类比需要的更复杂。
对于一个好的,关于如何使用AsyncTask的点解释,this是一个非常好的来源。当然是official documentation。