我使用Activity作为对话框(不要认为有问题,但我提到它)。
该Dialog从用户获取一些数据,然后使用Apache's HttpClient
我将该数据发送到Web服务。
这意味着我有一个Button和一个与该Button相关的onClick()方法。
当onClick()
发生时,我获取并将用户添加的数据传递给将其作为JSON发送的方法(名为 sendJSON )。
然后我添加了Thread的代码。我将AsyncTask传递作为参数扩展为数据,并在doInBackground
内调用我的 sendJSON 方法,现在在onClick中我只需用用户数据作为参数调用execute()
。
根据我在Google上搜索的内容,错误是我调用了我的Activity,因此我可以调用sendJSON
方法。
然后就是这样:
Do not access the Android UI toolkit from outside the UI thread
所以我有两个问题。什么是这个问题的快速解决方案? onClick()方法中的runOnUiThread
会为我做什么工作?
第二,从一开始我的逻辑出了什么问题?我开始构建我需要的方法,然后添加了Thread的代码。那么我应该从一开始就想到它呢?
我花了很多时间思考它,编写代码并搜索以了解错误,所以我只想知道我应该从中学到什么,不要再重复相同的错误。
谢谢
编辑:代码
onClick :
@Override
public void onClick(View v) {
if( v == send ) {
//Mocking data
String network="anetwork", password , comment;
String lat="1", longt="2";
EditText passwd = (EditText)findViewById(R.id.password);
password = passwd.getText().toString();
EditText com = (EditText)findViewById(R.id.comment);
comment = com.getText().toString();
LongSend ls = new LongSend();
ls.execute(lat,longt,network,password,comment);
}
}
AsyncTask :
public class LongSend extends AsyncTask<String, Void, Void> {
@Override
protected Void doInBackground(String... params){
Log.i("AsyncTask", "here 1");
int param1 = Integer.parseInt(params[0]);
int param2 = Integer.parseInt(params[1]);
DialogActivity da = new DialogActivity();
try {
da.sendJson(param1, param2, params[2], params[3], params[4]);
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPreExecute() {
}
@Override
protected void onPostExecute(Void nothing) {
//
}
}
sendJSON
public void sendJson( int lat, int longt, String network, String passwd, String comment ) throws JSONException {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("web_service_here");
HttpResponse response;
JSONObject json = new JSONObject();
JSONObject nested = new JSONObject();
try {
Log.i("SENDJSON", " print");
nested.put("lat", lat);
nested.put("longt", longt);
json.put("coord", nested); //add "nested" to "json"
json.put("network", network);
json.put("password", passwd);
json.put("comment", comment);
StringEntity se = new StringEntity(json.toString());
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
httppost.getParams().setParameter("json", json);
Log.v("sendJSON", "json== " +json);
httppost.setEntity(se);
Log.v("sendJSON", "SE== " +se);
response = httpclient.execute(httppost);
if(response !=null) {
str = inputStreamToString(response.getEntity().getContent()).toString();
Log.i("POST", "send JSON data");
Log.i("DATA", "Data Send==" +str );
}
} catch ( ClientProtocolException e ) {
e.printStackTrace();
} catch ( IOException e) {
e.printStackTrace();
}
}
活动
public class DialogActivity extends Activity implements OnClickListener {
public static String str;
Button send;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_fragment);
send = (Button)findViewById(R.id.button_send);
send.setOnClickListener(this);
}
LogCat:
06-08 05:33:59.801:E / AndroidRuntime(397):致命异常:AsyncTask
1 06-08 05:33:59.801:E / AndroidRuntime(397):java.lang.RuntimeException:执行时出错
doInBackground()06-08 05:33:59.801:E / AndroidRuntime(397):at android.os.AsyncTask $ 3.done(AsyncTask.java:266)06-08 05:33:59.801: E / AndroidRuntime(397):at java.util.concurrent.FutureTask中$ Sync.innerSetException(FutureTask.java:273) 06-08 05:33:59.801:E / AndroidRuntime(397):at java.util.concurrent.FutureTask.setException(FutureTask.java:124) 06-08 05:33:59.801:E / AndroidRuntime(397):at java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:307) 06-08 05:33:59.801:E / AndroidRuntime(397):at java.util.concurrent.FutureTask.run(FutureTask.java:137)06-08 05:33:59.801:E / AndroidRuntime(397):at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1081) 06-08 05:33:59.801:E / AndroidRuntime(397):at java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:574) 06-08 05:33:59.801:E / AndroidRuntime(397):at java.lang.Thread.run(Thread.java:1020)06-08 05:33:59.801: E / AndroidRuntime(397):引起:java.lang.RuntimeException:不能 在没有调用Looper.prepare()的线程内创建处理程序 06-08 05:33:59.801:E / AndroidRuntime(397):at android.os.Handler。(Handler.java:121)06-08 05:33:59.801: E / AndroidRuntime(397):at android.app.Activity。(Activity.java:727)06-08 05:33:59.801: E / AndroidRuntime(397):at org.teo.wifit.DialogActivity。(DialogActivity.java:30)06-08 05:33:59.801:E / AndroidRuntime(397):at org.teo.wifit.DialogActivity $ LongSend.doInBackground(DialogActivity.java:88) 06-08 05:33:59.801:E / AndroidRuntime(397):at org.teo.wifit.DialogActivity $ LongSend.doInBackground(DialogActivity.java:1) 06-08 05:33:59.801:E / AndroidRuntime(397):at android.os.AsyncTask $ 2.call(AsyncTask.java:252)06-08 05:33:59.801: E / AndroidRuntime(397):at java.util.concurrent.FutureTask中$ Sync.innerRun(FutureTask.java:305) 06-08 05:33:59.801:E / AndroidRuntime(397):... 4更多
问题出在第88行:DialogActivity da = new DialogActivity();
答案 0 :(得分:1)
检查&amp;阅读android developper guide
它告诉Android UI工具包不是thread-safe。因此,单线程模型确保UI不会被不同的线程同时修改。:
当您的应用执行密集型工作以响应用户互动时, 除非你这样,否则这个单线程模型会产生很差 正确实施您的申请。具体来说,如果一切都是 发生在UI线程中,执行网络等长时间操作 访问或数据库查询将阻止整个UI。当线程是 阻止,不能调度任何事件,包括绘制事件。从 从用户的角度来看,应用程序似乎挂起了。更糟, 如果UI线程被阻止超过几秒钟(大约5秒) 当前的秒数)用户被告知臭名昭着 “应用程序无响应”(ANR)对话框。然后用户可以决定 退出你的应用程序并在他们不满意时卸载它。
此外,Andoid UI工具包不是线程安全的。所以,你必须 不要从工作线程操纵你的UI - 你必须做所有 从UI线程操作到您的用户界面。因此,那里 只是Android单线程模型的两个规则:
不要阻止UI线程不要访问Android UI工具包 在UI线程之外
答案 1 :(得分:1)
您无法从doInBackground()更新/访问ui。你应该在ui线程上更新/访问ui。您可以使用runOnUithread。
http://developer.android.com/reference/android/os/AsyncTask.html
检查上述链接中的文档
您可以在doInBackground(params)中执行所有与网络相关的操作。 doInBackground(params)计算的结果是onPostExecute(result)的参数。
在后台线程上调用doInBackground。您可以返回结果,并根据结果更新ui或在onPostExecute中显示对话框或消息。
答案 2 :(得分:0)
您无法在后台线程中执行与UI相关的操作,任何与UI相关的工作(如显示或修改)都必须在主线程中完成。因此,如果您想要执行这些操作,请使用ActivityName.this.runOnUIThread()方法或在onPostExecute中执行UI操作