onClick和AsyncTask致命异常#1

时间:2013-06-08 04:34:26

标签: android android-asynctask

我使用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();

3 个答案:

答案 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操作