主线程网络错误,使用AsyncTask时发生。

3

我正在尝试构建我的第一个Android应用程序,它使用AsyncTask执行POST请求(以登录网站)。

在关闭StrictMode时,我的应用程序可以正常工作,但是我希望在StrictMode下执行时也能无误。尽管我使用AsyncTask重新设计了我的应用程序,但它仍然给出以下错误:

android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1145)

从我在互联网上读到的内容来看,使用AsyncTask应该可以解决这个问题。我不想使用Java线程,因为我想学习正确的方法。
我建立了一个新类来执行任务,它叫做MyAsyncTask,下面是类代码:
<code>
package com.am.tuto;
import android.os.AsyncTask;// removed rest of imports for readability
public class MyAsyncTask extends AsyncTask<Void, Void, String> {
String u;
String p;

public MyAsyncTask(String u, String p)
{
    this.u=u;
    this.p=p;
}

@Override protected String doInBackground(Void... params) {
String msg="";
if ((u.length()>0)&&(p.length()>0))
{
    HttpClient httpclient = new DefaultHttpClient();
    HttpPost httppost = new HttpPost("http://irrationalgamers.com/test.php");
try 
{
    List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
    nameValuePairs.add(new BasicNameValuePair("username", u));
    nameValuePairs.add(new BasicNameValuePair("password", p));
    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
    HttpResponse response =httpclient.execute(httppost); // <----the error occurs
    HttpEntity entity = response.getEntity();
    String responseString = EntityUtils.toString(entity, "UTF-8");
    System.out.println(responseString);
    msg="success";
    msg=responseString;
} 

catch (ClientProtocolException e) 
{
// TODO Auto-generated catch block
} 
catch (IOException e) 
{
// TODO Auto-generated catch block
}  
}
else
{
   msg="failed";
}
return msg;
}

@Override protected void onPostExecute(String result) 
{
    MyBus.getInstance().post(new AsyncTaskResultEvent(doInBackground()));
}
}
</code>

我想这可能是因为我创建了自己的构造函数,但我觉得我确实必须传一些参数。我可以继续编写应用程序,但学习如何预防这个问题会很好。我读到的每篇关于错误的文章都指向AsyncTask,但在已实现时很难找到解决方案... 对此有何想法将不胜感激。

你是如何启动“AsyncTask”的? - ρяσѕρєя K
你该如何运行AsyncTask?使用get还是execute? - Blackbelt
3
MyBus.getInstance().post(new AsyncTaskResultEvent(doInBackground())); 这行代码在 onPostExecute 中引起问题,因为 onPostExecute 总是在 UI 线程上运行,而你正在从 onPostExecute 中调用 doInBackground - ρяσѕρєя K
它只是抛出了一个新的异常,它认为总线必须从主线程中运行... Caused by: java.lang.IllegalStateException: 从非主线程 null 访问事件总线 [Bus "default"] - Bart Hofma
@BartHofma:如果没有运行MyBus.getInstance().post(new AsyncTaskResultEvent(doInBackground()));这一行,会发生什么? - ρяσѕρєя K
显示剩余7条评论
1个回答

2
基本上,ρяσѕρєя K已经回答了你的问题。一些额外的细节:你不应该自己调用doInBackground。整个AsyncTask的重点在于管理将工作传递给后台工作线程并将结果返回给UI线程。doInBackground返回的是onPostExecute接收的参数。
你的onPostExecute应该像这样:
@Override
protected void onPostExecute(String result) {
    MyBus.getInstance().post(new AsyncTaskResultEvent(result));
}

感谢您的回复,我无法在周末测试我的代码,但我认为我的问题已得到解答。虽然我仍然不明白doInBackground()方法何时被调用,但我会接受这个答案,因为它回答了我提出的问题 :) 它是否在对象创建时运行? - Bart Hofma
AsyncTask会为您完成这项工作,您不必显式调用它。因此,您所做的就足够了:new MyAsyncTask(username, password).execute() - bolot
感谢您这么好地解释,而不是简单地复制/粘贴一个解决方案,我知道自己犯了什么错误,以及如果再次出现问题应该去哪里查找。周末结束后回家后我会尝试这段代码:D & ρяσѕρєя K - Bart Hofma
我刚试着这样做,想告诉你它完美地运行了!再次感谢 :) - Bart Hofma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接