0

我将 Activity 用作对话框(不认为有问题,但我提到了它)。

该对话框从用户那里获取一些数据,然后Apache's HttpClient我将这些数据发送到 Web 服务。这意味着我有一个 Button 和一个与该 Button 关联的 onClick() 方法。当onClick()发生时,我获取用户添加的数据并将其传递给将它们作为 JSON 发送的方法(命名为sendJSON )。

然后我添加了线程的代码。我扩展了 AsyncTask 作为参数传递数据,在里面doInBackground我调用了我的sendJSON方法,现在在 onClick 里面我只是execute()用用户数据作为参数来调用。

从我在 Google 上搜索的内容来看,错误是我调用了我的 Activity,因此我可以调用该sendJSON方法。然后是这样的:

Do not access the Android UI toolkit from outside the UI thread

所以我有两个问题。有什么快速解决此问题的方法?runOnUiThread在 onClick() 方法里面会为我工作吗?其次,从一开始我的逻辑有什么问题?我开始构建我需要的方法,然后为 Thread 添加代码。那么我应该如何从一开始就想到呢?

我花了很多时间去思考,编写代码并搜索以了解哪里出了问题,所以我只想知道我应该从中学到什么,不要再重复同样的错误。

谢谢

编辑:代码

点击

    @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);

         }
    }

异步任务

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) {
        //              
    }

}

发送JSON

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);


}

日志猫:

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): 在 android.os.AsyncTask$3.done(AsyncTask.java:266) 06-08 05:33:59.801: E/AndroidRuntime(397) : 在 java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273) 06-08 05:33:59.801: E/AndroidRuntime(397): 在 java.util.concurrent.FutureTask.setException(FutureTask.java :124) 06-08 05:33:59.801: E/AndroidRuntime(397): 在 java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307) 06-08 05:33:59.801: E/AndroidRuntime (397): 在 java.util.concurrent.FutureTask.run(FutureTask.java:137) 06-08 05:33:59.801: E/AndroidRuntime(397): 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor. java:1081) 06-08 05:33:59.801: E/AndroidRuntime(397): 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:574) 06-08 05:33:59.801: E/AndroidRuntime(397): 在 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):在 android.os.Handler.(Handler. java:121) 06-08 05:33:59.801: E/AndroidRuntime(397): 在 android.app.Activity.(Activity.java:727) 06-08 05:33:59.801: E/AndroidRuntime(397):在 org.teo.wifit.DialogActivity.(DialogActivity.java:30) 06-08 05:33:59.801: E/AndroidRuntime(397): 在 org.teo.wifit.DialogActivity$LongSend.doInBackground(DialogActivity.java:88 ) 06-08 05:33:59.801: E/AndroidRuntime(397): 在 org.teo.wifit.DialogActivity$LongSend.doInBackground(DialogActivity.java:1) 06-08 05:33:59.801: E/AndroidRuntime(397 ):在 android.os.AsyncTask$2.call(AsyncTask.java:252) 06-08 05:33:59.801: E/AndroidRuntime(397): 在 java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305 ) 06-08 05:33:59.801: E/AndroidRuntime(397): ... 4 更多

问题出在第 88 行: DialogActivity da = new DialogActivity();

4

3 回答 3

1

您不能从 doInBackground() 更新/访问 ui。您应该在 ui 线程上更新/访问 ui。您可以使用 runOnUithread。

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

检查上面链接中的文档

您可以在 doInBackground(params) 中进行所有与网络相关的操作。doInBackground(params) 计算的结果是 onPostExecute(result) 的参数。

doInBackground 在后台线程上调用。您可以返回结果并根据结果更新 ui 或在 onPostExecute 中显示对话框或消息。

于 2013-06-08T05:17:07.360 回答
1

检查并阅读 android 开发者指南

它告诉 Android UI 工具包不是线程安全的。因此,单线程模型确保 UI 不会同时被不同的线程修改:

当您的应用程序执行密集工作以响应用户交互时,除非您正确实现应用程序,否则这种单线程模型可能会产生较差的性能。具体来说,如果一切都发生在 UI 线程中,那么执行网络访问或数据库查询等长时间操作将阻塞整个 UI。当线程被阻塞时,不能调度任何事件,包括绘图事件。从用户的角度来看,应用程序似乎挂起。更糟糕的是,如果 UI 线程被阻塞超过几秒(目前大约 5 秒),用户会看到臭名昭著的“应用程序无响应”(ANR)对话框。如果他们不满意,用户可能会决定退出您的应用程序并卸载它。

此外,Andoid UI 工具包不是线程安全的。因此,您不能从工作线程操作您的 UI — 您必须从 UI 线程对您的用户界面进行所有操作。因此,Android 的单线程模型只有两条规则:

不要阻塞 UI 线程 不要从 UI 线程外部访问 Android UI 工具包

于 2013-06-08T04:40:31.517 回答
0

您不能在后台线程中进行与 UI 相关的操作,任何与 UI 相关的工作(例如显示或修改)都必须在主线程中完成。因此,如果您想执行这些操作,请使用 ActivityName.this.runOnUIThread() 方法或在 onPostExecute 中执行您的 UI 操作

于 2016-05-08T17:52:35.660 回答