2012-08-13 92 views
19

我已经创建了基于函数的图像上传asynctask。上传后,我在onPostExecute上发生此错误。我在Runnable上读了一些Stackoverflow的答案,但是尽管实现了不同的解决方案,我仍然一遍又一遍地得到错误。Android AsyncTask [无法在未调用Looper.prepare()的线程中创建处理程序]

我的代码:

class uploadFile extends AsyncTask<String, String, String> { 
     private ProgressDialog pDialog; 

     /** 
     * -------------------------------------------------------------------- 
     * --------------------------------- Before starting background thread 
     * Show Progress Dialog 
     * */ 
     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 
      pDialog = new ProgressDialog(MainActivity.this); 
      pDialog.setMessage("Uploading file"); 
      pDialog.setIndeterminate(false); 
      pDialog.setCancelable(false); 
      pDialog.show(); 
     } 

     /** 
     * -------------------------------------------------------------------- 
     * --------------------------------- getting all recent articles and 
     * showing them in listview 
     * */ 
     @Override 
     protected String doInBackground(String... args) { 
      HttpURLConnection conn = null; 
      DataOutputStream dos = null; 
      DataInputStream inStream = null; 
      String existingFileName = Environment.getExternalStorageDirectory() 
        .getAbsolutePath() + "/mypic.png"; 
      String lineEnd = "\r\n"; 
      String twoHyphens = "--"; 
      String boundary = "*****"; 
      int bytesRead, bytesAvailable, bufferSize; 
      byte[] buffer; 
      int maxBufferSize = 1 * 1024 * 1024; 
      String serverResponseMessage = ""; 
      String urlString = "http://google.info/imgupl/index.php"; 
      try { 
       // ------------------ CLIENT REQUEST 
       FileInputStream fileInputStream = new FileInputStream(new File(
         existingFileName)); 
       // open a URL connection to the Servlet 
       URL url = new URL(urlString); 
       // Open a HTTP connection to the URL 
       conn = (HttpURLConnection) url.openConnection(); 
       // Allow Inputs 
       conn.setDoInput(true); 
       // Allow Outputs 
       conn.setDoOutput(true); 
       // Don't use a cached copy. 
       conn.setUseCaches(false); 
       // Use a post method. 
       conn.setRequestMethod("POST"); 
       conn.setRequestProperty("Connection", "Keep-Alive"); 
       conn.setRequestProperty("Content-Type", 
         "multipart/form-data;boundary=" + boundary); 
       dos = new DataOutputStream(conn.getOutputStream()); 
       dos.writeBytes(twoHyphens + boundary + lineEnd); 
       dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" 
         + existingFileName + "\"" + lineEnd); 
       dos.writeBytes(lineEnd); 
       // create a buffer of maximum size 
       bytesAvailable = fileInputStream.available(); 
       bufferSize = Math.min(bytesAvailable, maxBufferSize); 
       buffer = new byte[bufferSize]; 
       // read file and write it into form... 
       bytesRead = fileInputStream.read(buffer, 0, bufferSize); 
       while (bytesRead > 0) { 
        dos.write(buffer, 0, bufferSize); 
        bytesAvailable = fileInputStream.available(); 
        bufferSize = Math.min(bytesAvailable, maxBufferSize); 
        bytesRead = fileInputStream.read(buffer, 0, bufferSize); 
       } 
       // send multipart form data necesssary after file data... 
       dos.writeBytes(lineEnd); 
       dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); 
       // close streams 
       Integer serverResponseCode = conn.getResponseCode(); 
       serverResponseMessage = conn.getResponseMessage(); 
       Toast.makeText(getApplicationContext(), serverResponseMessage, 
         Toast.LENGTH_SHORT).show(); 
       Toast.makeText(getApplicationContext(), 
         serverResponseCode.toString(), Toast.LENGTH_SHORT) 
         .show(); 
       Log.e("Debug", "File is written"); 
       fileInputStream.close(); 
       dos.flush(); 
       dos.close(); 
      } catch (MalformedURLException ex) { 
       Log.e("Debug", "error: " + ex.getMessage(), ex); 
      } catch (IOException ioe) { 
       Log.e("Debug", "error: " + ioe.getMessage(), ioe); 
      } 
      // ------------------ read the SERVER RESPONSE 
      try { 
       inStream = new DataInputStream(conn.getInputStream()); 

       while ((str = inStream.readLine()) != null) { 
        Log.e("Debug", "Server Response " + str); 
       } 
       inStream.close(); 

      } catch (IOException ioex) { 
       Log.e("Debug", "error: " + ioex.getMessage(), ioex); 
      } 
      return null; 
     } 

     /** 
     * -------------------------------------------------------------------- 
     * --------------------------------- After completing background task 
     * Dismiss the progress dialog 
     * **/ 
     protected void onPostExecute(String args) { 
      // dismiss the dialog after getting all products 
      pDialog.dismiss(); 
      MainActivity.this.runOnUiThread(new Runnable() { 
        public void run() { 
        Toast.makeText(MainActivity.this, "Hello", Toast.LENGTH_SHORT).show(); 
        } 
       }); 

     } 
    } 

我的logcat:

08-13 22:13:32.627: E/AndroidRuntime(9554): FATAL EXCEPTION: AsyncTask #1 
08-13 22:13:32.627: E/AndroidRuntime(9554): java.lang.RuntimeException: An error occured while executing doInBackground() 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at android.os.AsyncTask$3.done(AsyncTask.java:200) 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274) 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at java.util.concurrent.FutureTask.setException(FutureTask.java:125) 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308) 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088) 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581) 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at java.lang.Thread.run(Thread.java:1019) 
08-13 22:13:32.627: E/AndroidRuntime(9554): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at android.os.Handler.<init>(Handler.java:121) 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at android.widget.Toast.<init>(Toast.java:68) 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at android.widget.Toast.makeText(Toast.java:231) 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at dev.google.imageupload.MainActivity$uploadFile.doInBackground(MainActivity.java:128) 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at dev.google.imageupload.MainActivity$uploadFile.doInBackground(MainActivity.java:1) 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at android.os.AsyncTask$2.call(AsyncTask.java:185) 
08-13 22:13:32.627: E/AndroidRuntime(9554):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306) 
08-13 22:13:32.627: E/AndroidRuntime(9554):  ... 4 more 

编辑完成后zapl的建议:

08-13 22:38:06.297: E/AndroidRuntime(11511): FATAL EXCEPTION: AsyncTask #1 
08-13 22:38:06.297: E/AndroidRuntime(11511): java.lang.RuntimeException: An error occured while executing doInBackground() 
08-13 22:38:06.297: E/AndroidRuntime(11511): at android.os.AsyncTask$3.done(AsyncTask.java:200) 
08-13 22:38:06.297: E/AndroidRuntime(11511): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274) 
08-13 22:38:06.297: E/AndroidRuntime(11511): at java.util.concurrent.FutureTask.setException(FutureTask.java:125) 
08-13 22:38:06.297: E/AndroidRuntime(11511): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308) 
08-13 22:38:06.297: E/AndroidRuntime(11511): at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
08-13 22:38:06.297: E/AndroidRuntime(11511): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088) 
08-13 22:38:06.297: E/AndroidRuntime(11511): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581) 
08-13 22:38:06.297: E/AndroidRuntime(11511): at java.lang.Thread.run(Thread.java:1019) 
08-13 22:38:06.297: E/AndroidRuntime(11511): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() 
08-13 22:38:06.297: E/AndroidRuntime(11511): at android.os.Handler.<init>(Handler.java:121) 
08-13 22:38:06.297: E/AndroidRuntime(11511): at android.widget.Toast.<init>(Toast.java:68) 
08-13 22:38:06.297: E/AndroidRuntime(11511): at android.widget.Toast.makeText(Toast.java:231) 
08-13 22:38:06.297: E/AndroidRuntime(11511): at dev.google.imageupload.MainActivity$uploadFile.doInBackground(MainActivity.java:128) 
08-13 22:38:06.297: E/AndroidRuntime(11511): at dev.google.imageupload.MainActivity$uploadFile.doInBackground(MainActivity.java:1) 
08-13 22:38:06.297: E/AndroidRuntime(11511): at android.os.AsyncTask$2.call(AsyncTask.java:185) 
08-13 22:38:06.297: E/AndroidRuntime(11511): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306) 
08-13 22:38:06.297: E/AndroidRuntime(11511): ... 4 more 
+4

只需在'onPostExecute'中直接创建'Toast',因为它已经在UI线程上执行了。 'AsyncTask's只能从UI线程执行,而那些'onSomthing'方法将从UI线程再次被调用 – zapl 2012-08-13 14:13:06

+0

删除runOnUiThread并导致另一个问题:( – MrYanDao 2012-08-13 14:22:22

+0

分享新问题:D。也让我知道你上传图片后你想做什么 – 2012-08-13 14:26:53

回答

44

您正试图更新从后台线程的用户界面。将烤面包移至onPostExecute(在UI线程上执行)(推荐),或者拨打runOnUiThread

runOnUiThread(new Runnable() { 
    public void run() { 
     // runs on UI thread 
    } 
}); 
+0

我已经拥有这在我的onPostExecute上。 – MrYanDao 2012-08-13 14:21:11

+3

正确(这是不必要的),但是你也在'doInBackground'中有两个'Toast'调用,这导致了异常。 – 2012-08-13 14:34:15

+0

所以你的意思是说我不能在'doInBackground'中有'Toast'?对不起,我有点小菜在这里:(对不起! 编辑我想我明白了吧。等一下.. – MrYanDao 2012-08-13 14:35:00

6

在dev.shaunidiot.imageupload.MainActivity $ uploadFile.doInBackground(MainActivity.java:128)

你可以使用的AsyncTask S上的进步机制,从内部doInBackground同时更新UI正在运行的任务:

更换

Toast.makeText(getApplicationContext(), serverResponseMessage, 
     Toast.LENGTH_SHORT).show(); 
Toast.makeText(getApplicationContext(), 
     serverResponseCode.toString(), Toast.LENGTH_SHORT) 
     .show(); 

doInBackground

publishProgress(serverResponseMessage, serverResponseCode.toString()); 

,并添加以下到您的AsyncTask实现

@Override 
protected void onProgressUpdate(String... values) { 
    if (values != null) { 
     for (String value : values) { 
      // shows a toast for every value we get 
      Toast.makeText(MainActivity.this, value, Toast.LENGTH_SHORT).show(); 
     } 
    } 
} 

你已经在AsyncTask<Params, Progress, Result>这样的情况下,设置String是进步类型要使用不同的东西,你可以进步尝试使用runOnUiThread,但我不知道这是否会起作用。

相关问题