在doInBackground中创建一个Handler

时间:2015-03-13 20:07:21

标签: java android android-asynctask

我正在尝试创建一个定期查看下载缓冲区的计时器线程,并查看我为下载文件而创建的线程中有多少字节。但是,我总是得到这样的消息:无法在未调用Looper.prepare()的线程内创建处理程序

我的代码:

private class DownloadPdfTask extends AsyncTask<String, Integer, String> {

    private PowerManager.WakeLock mWakeLock;

    @Override
    protected String doInBackground(String... params) {

   // ... code 
   try {
            // Create the URL, needs java.net.URL
            URL mUrl;
            mUrl = new URL(params[0]);

            // Variable to measure Latency (until first byte is received)
            long beforeConnect = System.currentTimeMillis();


            // Open connection to the URL
            mConnection = (HttpURLConnection) mUrl.openConnection();
            mConnection.connect();

            long afterConnect = System.currentTimeMillis();

            mLatency = afterConnect - beforeConnect;

            // expect HTTP 200 OK, so we don't mistakenly save error report
            // instead of the file
            if (mConnection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                return "Server returned HTTP " + mConnection.getResponseCode()
                        + " " + mConnection.getResponseMessage();
            }

            fileLength = mConnection.getContentLength();

            // Download the file
            is = mConnection.getInputStream();
            final File osFile = new File("sdcard/filename.pdf");
            if (!osFile.exists())
            {
                try
                {
                    osFile.createNewFile();
                }
                catch (IOException e)
                {
                    // TODO Auto-generated catch block
                    return e.toString();
                }
            }

            os = new FileOutputStream(osFile);

            final byte data[] = new byte[4096];
            int count;

            //  Create timer thread to peek buffer and see how many bytes are there
            final Handler mHandler = new Handler();
            Runnable mHandlerTask = new Runnable() {
                @Override
                public void run() {
                    mThroughputEverySecond += " " + total;
                    // Run timer task every second
                    mHandler.postDelayed(this, 1000);
                }
            };

            while ((count = is.read(data)) != -1) {
                // Allow canceling with back button
                if (isCancelled()) {
                    is.close();
                    return null;
                }
                total += count;
                // Publishing the progress
                if (fileLength > 0) { // Only if total length is known
                    publishProgress((int) (total * 100 / fileLength));
                }
                os.write(data, 0, count);
            }

            // Stop timer task after download is completed
            mHandler.removeCallbacks(mHandlerTask);

        } catch (Exception e) {
            return e.toString();

2 个答案:

答案 0 :(得分:3)

尝试使用new Handler(Looper.getMainLooper())来实例化您的处理程序。

答案 1 :(得分:2)

可以在任何线程上实例化handler,但该线程必须具有looper对象。如何制作一个活套?致电looper.prepare();

然后你必须创建你的处理程序,然后调用Looper.loop();

看看这个:

class LooperThread extends Thread {
  public Handler mHandler;

  public void run() {
      Looper.prepare();

      mHandler = new Handler() {
          public void handleMessage(Message msg) {

          }
      };

      Looper.loop();

  }
}

Ui线程有一个looper对象,所以你不需要在创建处理程序之前调用looper.prepar(),但是对于其他线程,你必须按照我的编码。