在 doInBackground 中创建一个处理程序

Create a Handler inside doInBackground

我正在尝试创建一个计时器线程,它会定期查看下载缓冲区,并查看我创建的用于下载文件的线程中有多少字节。但是,我总是收到此消息:无法在未调用 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();

A handler 可以在任何线程上实例化,但该线程必须有一个循环对象。如何创建循环器?打电话 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() 但对于其他线程你必须按照我的代码做。

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