2011-06-24 90 views
1

我看過這個問題以前問過,但我找不到一個可行的答案,我一直在尋找同樣的問題幾天glumAndroid的ProgressBar不更新時更新setProgress

我有一個屏幕有3個進度條,我想在漫長的下載過程中更新。無論我嘗試什麼,我都無法獲得進度條更新。

完整源here

我FileDownloadManager類:

package org.touchandgo.speak; 

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.FileReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.HttpURLConnection; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.util.ArrayList; 

import android.app.Activity; 
import android.app.AlertDialog; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.net.ConnectivityManager; 
import android.os.Bundle; 
import android.os.Environment; 
import android.util.Log; 
import android.view.View; 
import android.widget.Button; 
import android.widget.CheckBox; 
import android.widget.ProgressBar; 
import android.widget.TextView; 

public class FileDownloadManager extends Activity 
{ 
    public static final String FILE_MANIFEST = "http://dl.dropbox.com/u/25690498/TouchAndGoSpeakImages/TouchAndGoSpeak_Download.manifest"; 
    public static final String LOCAL_FILE_MANIFEST = "TouchAndGoSpeak_Download.manifest"; 
    public static final String LOGid = "TouchAndGoSpeak"; 

    private String msBaseFolder = ""; 
    private TextView tvCurrent; 

    public void onCreate(Bundle icicle) 
    { 
     super.onCreate(icicle); 
     Log.d(LOGid, "Create activity"); 
     setContentView(R.layout.download); 

     mContext = this; 


     tvCurrent = (TextView) findViewById(R.id.tvCurrentAction); 
     tvCurrent.setText("Awaiting user input"); 
     tvCurrent.invalidate(); 

     Button bDownload = (Button) findViewById(R.id.btnStartDownload); 
     bDownload.setOnClickListener(new View.OnClickListener() 
     { 
      public void onClick(View arg0) 
      { 
       if (!isNetworkAvailable()) 
       { 
        AlertDialog adConfirm = new AlertDialog.Builder(mContext).create(); 
        adConfirm.setCancelable(false); // This blocks the 'BACK' button 
        adConfirm.setMessage("It appears you are offline, phone should be online for this to work."); 
        adConfirm.setButton("I'm online, go ahead.", new DialogInterface.OnClickListener() 
        { 
         @Override 
         public void onClick(DialogInterface dialog, int which) 
         { 
          dialog.dismiss(); 
          downloadfiles(); 
         } 
        }); 
        adConfirm.setButton2("I'll try later", new DialogInterface.OnClickListener() 
        { 
         @Override 
         public void onClick(DialogInterface dialog, int which) 
         { 
          dialog.dismiss(); 
         } 
        }); 

        adConfirm.show(); 

       } 
       else 
       { 
        downloadfiles(); 
       } 
      } 
     }); 

     Button bDownloadInfo = (Button) findViewById(R.id.btnDownloadInfo); 
     bDownloadInfo.setOnClickListener(new View.OnClickListener() 
     { 
      public void onClick(View arg0) 
      { 
       AlertDialog adConfirm = new AlertDialog.Builder(mContext).create(); 
       adConfirm.setCancelable(false); // This blocks the 'BACK' button 
       adConfirm.setMessage("This function will go to the internet and download the Touch And Go 'Speak' free image set.\n\nIt is highly recommended that you use a wi-fi connection for this.\n\nThese images are provided free of charge and as is. They are not my work, but are based upon various free resources from the internet that I have pulled together.\nNo copyright infringement is intended. Please contact me if you wish to assert copyright for any of these images.\nIf you own a set of images from another source (for example the {PECS image set) the you can copy these to the applocation folder on the sdcard (" + msBaseFolder + ") - for every folder you want to display in the list you must have a corresponding image file for the app to display (for example if you have a folder called '2. Sentence Starters' then in the base folder you must have am image file called '2. Sentence Starters.jpg'"); 
       adConfirm.setButton("OK", new DialogInterface.OnClickListener() 
       { 
        @Override 
        public void onClick(DialogInterface dialog, int which) 
        { 
         dialog.dismiss(); 
        } 
       }); 

       adConfirm.show(); 
      } 
     }); 


    } 


    private void processManifest() 
    { 
     tvCurrent.setText("Processing files to download..."); 
     tvCurrent.invalidate(); 

     //Get the text file 
     File file = new File(msBaseFolder,LOCAL_FILE_MANIFEST); 
     Log.d(LOGid, "Created new file " + msBaseFolder+ "/" + LOCAL_FILE_MANIFEST); 

     //Read text from file 
//  StringBuilder text = new StringBuilder(); 
     ProgressBar pb = (ProgressBar) findViewById(R.id.barFiles); 
     int iLineCnt=getLineCount(LOCAL_FILE_MANIFEST); 

     int iCurrentLine=0; 
     pb.setMax(iLineCnt); 
     Log.d(LOGid, "Set progress line count to " + iCurrentLine + " of " + iLineCnt); 

     try 
     { 
      BufferedReader br = new BufferedReader(new FileReader(file)); 
      Log.d(LOGid, "Created buffered reader"); 
      String line; 

      while ((line = br.readLine()) != null) 
      { 
       try 
       { 
        iCurrentLine++; 
        pb.setProgress(iCurrentLine); 
        pb.invalidate(); 
        Log.d(LOGid, "Set progress line count to " + iCurrentLine + " of " + iLineCnt); 
       } 
       catch (Exception ex) 
       { // swallow the error 
       } 
       String[] sDownloads = line.split(";"); 
       Log.d(LOGid, "Line read was" + line + " of which there are " + sDownloads.length + " parts"); 

       // line should have 3 parts 
       // 1. Source url 
       // 2. Target name 
       // 3. Target folder 
       if (sDownloads.length == 3) 
       { 
        // Does the file already exist 
        File fil; 
        File fld; 
        if (sDownloads[2].equals(".")) 
        { 
         fil = new File(msBaseFolder, sDownloads[1]); 
         fld = new File(msBaseFolder); 
        } 
        else 
        { 
         fil = new File(msBaseFolder + "/" + sDownloads[2], sDownloads[1]); 
         fld = new File(msBaseFolder + "/" + sDownloads[2]); 
        } 

        // Does the folder exist 
        Log.d(LOGid, "Ensure the dest folder exists: " + fld.getPath()); 
        fld.mkdirs(); 

        if (!fil.exists()) 
        { 
         downloadFile(sDownloads[0], sDownloads[1], fld.getPath(), true); 
        } 
        else 
        { 
         // Skipping a file 
        } 
       } 
      } 
     } 
     catch (Exception e) 
     { 
      //You'll need to add proper error handling here 
      Log.e(LOGid, "Error in processmanifest:" + e.getMessage()); 
     } 

     //Set the text 
     tvCurrent.setText("Finished Downloading Files..."); 
     tvCurrent.invalidate(); 
    } 

    private boolean downloadFile(String _source, String _dest, String _Folder, boolean isManifest) 
    { 
     try 
     { 
      tvCurrent.setText("Downloading file " + _dest + "..."); 
      tvCurrent.invalidate(); 
      //set the download URL, a url that points to a file on the internet 
      //this is the file to be downloaded 
      URL url = new URL(_source); 
      Log.d(LOGid, "Created URL"); 

      //create the new connection 
      HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); 
      Log.d(LOGid, "Created HTTP Connection"); 

      //set up some things on the connection 
      urlConnection.setRequestMethod("GET"); 
      Log.d(LOGid, "Set the request method"); 
      urlConnection.setDoOutput(true); 
      Log.d(LOGid, "Set doOutput"); 

      //and connect! 
      urlConnection.connect(); 
      Log.d(LOGid, "Connected the url connection"); 

      //set the path where we want to save the file 
      //in this case, going to save it on the root directory of the 
      //sd card. 
      File SDCardRoot = Environment.getExternalStorageDirectory(); 
      //create a new file, specifying the path, and the filename 
      //which we want to save the file as. 
      File file = new File(_Folder, _dest); 
      Log.d(LOGid, "Created dest file, path=" + file.getPath() + "...file=" + file.getName()); 

      //this will be used to write the downloaded data into the file we created 
      FileOutputStream fileOutput = new FileOutputStream(file); 
      Log.d(LOGid, "Created file output stream"); 

      //this will be used in reading the data from the internet 
      InputStream inputStream = urlConnection.getInputStream(); 
      Log.d(LOGid, "Created Input stream"); 

      //this is the total size of the file 
      int totalSize = urlConnection.getContentLength(); 
      Log.d(LOGid, "Got total size " + totalSize); 

      //variable to store total downloaded bytes 
      int downloadedSize = 0; 

      //create a buffer... 
      byte[] buffer = new byte[1024]; 
      Log.d(LOGid, "Created buffer"); 

      int bufferLength = 0; //used to store a temporary size of the buffer 
      ProgressBar pb; 
      if (isManifest) 
      { 
       pb = (ProgressBar) findViewById(R.id.barManifest);  
      } 
      else 
      { 
       pb = (ProgressBar) findViewById(R.id.barOneFile);  
      } 
      pb.setMax(totalSize); 
      Log.d(LOGid, "Set progressbar size"); 

      pb.setProgress(0); 
      pb.invalidate(); 

      Log.d(LOGid, "Set progress to zero"); 

      //now, read through the input buffer and write the contents to the file 
      while ((bufferLength = inputStream.read(buffer)) > 0) 
      { 
        //add the data in the buffer to the file in the file output stream (the file on the sd card 
        fileOutput.write(buffer, 0, bufferLength); 
        Log.d(LOGid, "Wrote infor to the buffer"); 
        //add up the size so we know how much is downloaded 
        downloadedSize += bufferLength; 
        //this is where you would do something to report the prgress, like this maybe 
      //  updateProgress(downloadedSize, totalSize); 

        pb.setProgress(downloadedSize); 
        pb.invalidate(); 

        Log.d(LOGid, "Set progress to " + downloadedSize); 
      } 
      pb.setProgress(totalSize); 
      pb.invalidate(); 
      //close the output stream when done 
      fileOutput.close(); 
      Log.d(LOGid, "closed the output file"); 

      tvCurrent.setText("Finished Downloading file " + _dest + "..."); 
      tvCurrent.invalidate(); 

      //catch some possible errors... 
     } 
     catch (MalformedURLException e) 
     { 
      Log.d(LOGid, "Error dowloading file:" + e.getMessage() + "...malformed URL"); 
      return false; 
     } 
     catch (IOException e) 
     { 
      Log.d(LOGid, "Error dowloading file:" + e.getMessage()+ "...IO Exception"); 
      return false; 
     } 
     catch (Exception e) 
     { 
      Log.d(LOGid, "Error dowloading file:" + e.getMessage()+ "...generic exception"); 
      return false; 
     } 
     return true; 
    } 

    private boolean getBaseFolder() 
    { 
     try 
     { 
      msBaseFolder = Environment.getExternalStorageDirectory() + "/" + SpeakProperties.msAppFolder(getSharedPreferences(SpeakProperties.APP_NAME, 0)); 
      File f = new File(msBaseFolder); 
      if (!f.exists()) 
      { 
       msBaseFolder = Environment.getExternalStorageDirectory() + "/" + SpeakProperties.APP_DEF_FOLDER; 
       f = new File(msBaseFolder); 
      } 

      if (!f.exists()) 
      { 
       return createNewBaseFolder(); 
      } 
      else 
      { 
       Log.d(LOGid, "The base folder for this app" + msBaseFolder + " does exists."); 
       return true;     
      } 
     } 
     catch (Exception ex) 
     { 
      Log.d(LOGid, "Could not get base folder:" + msBaseFolder + ". Error:" + ex.getMessage()); 
      return false; 
     } 
    } 

    private boolean createNewBaseFolder() 
    { 

     tvCurrent.setText("Creating new base folder..."); 
     tvCurrent.invalidate(); 
     final String sNewBaseFld = Environment.getExternalStorageDirectory() + "/" + SpeakProperties.APP_DEF_FOLDER; 
     AlertDialog adDelete = new AlertDialog.Builder(this).create(); 
     adDelete.setCancelable(false); // This blocks the 'BACK' button 
     adDelete.setMessage("The base folder for the application does not seem to exist. \n\nWould you like to create one now based on the application default folder setting? \n\nThe App Default Folder is:" + sNewBaseFld); 
     adDelete.setButton("OK", new DialogInterface.OnClickListener() 
     { 
      @Override 
      public void onClick(DialogInterface dialog, int which) 
      { 
       try 
       { 
        File fCreate = new File(sNewBaseFld); 
        if (!fCreate.exists()) 
        { 
         fCreate.mkdirs(); 
        } 
       }     
       catch (Exception ex) 
       { 
        Log.e(LOGid, "Could not delete file:" + ex.getMessage()); 
        showToast("Could not create folder:" +sNewBaseFld + ". Error was:" + ex.getMessage()); 
       } 
       dialog.dismiss(); 
      } 
     }); 
     adDelete.setButton2("Cancel", new DialogInterface.OnClickListener() 
     { 
      @Override 
      public void onClick(DialogInterface dialog, int which) 
      { 
       dialog.dismiss(); 
      } 
     }); 

     adDelete.show(); 

     // Now did we create the folder? 
     File f = new File(sNewBaseFld); 
     tvCurrent.setText("Finished Creating new base folder..."); 
     tvCurrent.invalidate(); 
     return f.exists(); 
    } 

    void showToast(String msg) { 
     AlertDialog ad = new AlertDialog.Builder(this).create(); 
     ad.setCancelable(false); // This blocks the 'BACK' button 
     ad.setMessage(msg); 
     ad.setButton("OK", new DialogInterface.OnClickListener() { 
      @Override 
      public void onClick(DialogInterface dialog, int which) { 
       dialog.dismiss(); 
      } 
     }); 
     ad.show(); 

    } 

    private void downloadfiles() 
    { 
     CheckBox cb = (CheckBox) findViewById(R.id.cbDownload); 
     if (!cb.isChecked()) 
     { 
      return; 
     } 

     if (!getBaseFolder()) 
     { 
      return; 
     } 

     if (downloadFile(FILE_MANIFEST, LOCAL_FILE_MANIFEST, msBaseFolder, true)) 
     { 
      processManifest(); 
     } 
     else 
     { 
      AlertDialog adConfirm = new AlertDialog.Builder(mContext).create(); 
      adConfirm.setCancelable(false); // This blocks the 'BACK' button 
      adConfirm.setMessage("Could not download the list of image files, perhaps you are offline?"); 
      adConfirm.setButton("OK.", new DialogInterface.OnClickListener() 
      { 
       @Override 
       public void onClick(DialogInterface dialog, int which) 
       { 
        dialog.dismiss(); 
       } 
      }); 

      adConfirm.show(); 

     } 
    } 

    private boolean isThereANewDownload() 
    { 
     tvCurrent.setText("Checking to see if there are new images..."); 
     tvCurrent.invalidate(); 
     // check if we have a TouchAndGoSpeak.manifest file on the sd card 
     File file = new File(msBaseFolder,LOCAL_FILE_MANIFEST); 
     if (!file.exists()) 
     { 
      Log.d(LOGid, "No Local Manifest so returning true"); 
      return true; 
     } 

     // if we have one then the user has downloaded the manifest before 
     // download the new file 

     Log.d(LOGid, "We have a Local Manifest getting again to check"); 
     if (downloadFile(FILE_MANIFEST, LOCAL_FILE_MANIFEST + ".new", msBaseFolder, false)) 
     { 
      return (compare(LOCAL_FILE_MANIFEST, LOCAL_FILE_MANIFEST + ".new")); 
     } 
     else 
     { 
      AlertDialog adConfirm = new AlertDialog.Builder(mContext).create(); 
      adConfirm.setCancelable(false); // This blocks the 'BACK' button 
      adConfirm.setMessage("Could not download the list of image files, perhaps you are offline? Unable to check if there are new files. Will try and download all files next."); 
      adConfirm.setButton("OK.", new DialogInterface.OnClickListener() 
      { 
       @Override 
       public void onClick(DialogInterface dialog, int which) 
       { 
        dialog.dismiss(); 
       } 
      }); 

      adConfirm.show(); 
      return true; 
     } 
    } 

    private int getLineCount(String _File) 
    { 
     int iLineCount = 0; 
     //Get the text file 
     File file = new File(msBaseFolder,_File); 
//  StringList sl_source = new StringList(); 

     try 
     { 
      BufferedReader br = new BufferedReader(new FileReader(file)); 
      String line; 

      while ((line = br.readLine()) != null) 
      { 
       iLineCount++; 
      } 
     } 
     catch (IOException e) 
     { 
      //You'll need to add proper error handling here 
     } 
     return iLineCount; 
    } 


    private boolean compare(String _File1, String _File2) 
    { 
     Log.d(LOGid, "Comparing the 2 files"); 

     //Get the text file 
     File file = new File(msBaseFolder,_File1); 
//  StringList sl_source = new StringList(); 
     ArrayList<String> _original_data = new ArrayList<String>(); 
     ArrayList<String> _new_data = new ArrayList<String>(); 

     try { 
      BufferedReader br = new BufferedReader(new FileReader(file)); 
      String line; 

      while ((line = br.readLine()) != null) 
      { 
       _original_data.add(line); 
      } 
     } 
     catch (IOException e) 
     { 
      //You'll need to add proper error handling here 
     } 

     file = new File(msBaseFolder,_File2); 
     try 
     { 
      BufferedReader br = new BufferedReader(new FileReader(file)); 
      String line; 

      while ((line = br.readLine()) != null) 
      { 
       _new_data.add(line); 
      } 
     } 
     catch (IOException e) 
     { 
      //You'll need to add proper error handling here 
     } 

     return _original_data.equals(_new_data);  
    } 

    /** 
    * @return the networkAvailable 
    */ 
    public boolean isNetworkAvailable() 
    { 

     boolean networkAvailable = true; 
     try 
     { 
      Context c = getApplicationContext(); 
      ConnectivityManager connectionManager = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE); 
      networkAvailable = connectionManager.getActiveNetworkInfo() != null && connectionManager.getActiveNetworkInfo().isConnected(); 
     } 
     catch (Exception ex) 
     { 
      Log.d(LOGid, "Error determining the network connectivity:" + ex.getClass().toString() + " message:" + ex.getMessage()); 
     } 
     return networkAvailable; 
    }  

    private Context mContext; 
} 

編輯:工作downloadFiles方法與進度更新

我最後downloadFile看起來是這個樣子的線程和處理程序添加。 mHandler是在UI的onCreate內實例化的私有類變量。

感謝大家的幫助!

private boolean downloadFile(String _source, String _dest, String _Folder, 
     boolean isManifest) 
{ 
    m_downloadSuccess = true; 
    m_source = _source; 
    m_dest = _dest; 
    m_Folder = _Folder; 
    if (isManifest) 
    { 
     m_pb = (ProgressBar) findViewById(R.id.barManifest); 
    } 
    else 
    { 
     m_pb = (ProgressBar) findViewById(R.id.barOneFile); 
    } 

    // Start lengthy operation in a background thread 
    new Thread(new Runnable() 
    { 
     public void run() 
     { 
      try 
      { 
       // Update the progress bar 
       mHandler.post(new Runnable() 
       { 
        public void run() 
        { 
         Log.d(LOGid, "Set File max progress to " + mFileTotal); 
         Log.d(LOGid, "Set File progress to 0"); 
         Log.d(LOGid, "Downloading file " + m_dest + "..."); 
         tvCurrent.setText("Downloading file " + m_dest + "..."); 
        } 
       }); 

       // set the download URL, a url that points to a file on the 
       // internet 
       // this is the file to be downloaded 
       URL url = new URL(m_source); 
       Log.d(LOGid, "Created URL"); 

       // create the new connection 
       HttpURLConnection urlConnection = (HttpURLConnection) url 
         .openConnection(); 
       Log.d(LOGid, "Created HTTP Connection"); 

       // set up some things on the connection 
       urlConnection.setRequestMethod("GET"); 
       Log.d(LOGid, "Set the request method"); 
       urlConnection.setDoOutput(true); 
       Log.d(LOGid, "Set doOutput"); 

       // and connect! 
       urlConnection.connect(); 
       Log.d(LOGid, "Connected the url connection"); 

       // set the path where we want to save the file 
       // in this case, going to save it on the root directory of 
       // the 
       // sd card. 
       File SDCardRoot = Environment.getExternalStorageDirectory(); 
       // create a new file, specifying the path, and the filename 
       // which we want to save the file as. 
       File file = new File(m_Folder, m_dest); 
       Log.d(LOGid, "Created dest file, path=" + file.getPath() 
         + "...file=" + file.getName()); 

       // this will be used to write the downloaded data into the 
       // file we created 
       FileOutputStream fileOutput = new FileOutputStream(file); 
       Log.d(LOGid, "Created file output stream"); 

       // this will be used in reading the data from the internet 
       InputStream inputStream = urlConnection.getInputStream(); 
       Log.d(LOGid, "Created Input stream"); 

       // this is the total size of the file 
       mTotalSize = urlConnection.getContentLength(); 
       Log.d(LOGid, "Got total size " + mTotalSize); 

       // variable to store total downloaded bytes 
       int downloadedSize = 0; 

       // create a buffer... 
       byte[] buffer = new byte[1024]; 
       Log.d(LOGid, "Created buffer"); 

       int bufferLength = 0; // used to store a temporary size of 
             // the buffer 

       mProgressCurrentFileStatus = 0; 
       // m_pb.setProgress(0); 
       Log.d(LOGid, "Set progress to zero"); 

       // Update the progress bar 
       mHandler.post(new Runnable() 
       { 
        public void run() 
        { 
         Log.d(LOGid, "Set progress totalsize to " + mTotalSize); 
         m_pb.setMax(mTotalSize); 

         Log.d(LOGid, "Set File progress to " + mFileCount); 


         Log.d(LOGid, "Set progress to:" + mProgressCurrentFileStatus); 
         m_pb.setProgress(mProgressCurrentFileStatus); 
        } 
       }); 

       // now, read through the input buffer and write the contents 
       // to the file 
       while ((bufferLength = inputStream.read(buffer)) > 0) 
       { 
        // add the data in the buffer to the file in the file 
        // output stream (the file on the sd card 
        fileOutput.write(buffer, 0, bufferLength); 
        Log.d(LOGid, "Wrote infor to the buffer"); 
        // add up the size so we know how much is downloaded 
        downloadedSize += bufferLength; 
        // this is where you would do something to report the 
        // prgress, like this maybe 
        // updateProgress(downloadedSize, totalSize); 

        mProgressCurrentFileStatus = downloadedSize; 
        // Update the progress bar 
        mHandler.post(new Runnable() 
        { 
         public void run() 
         { 
          Log.d(LOGid, "Set progress size:" + mTotalSize); 
          m_pb.setMax(mTotalSize); 

          Log.d(LOGid, "Set progress to:" + mProgressCurrentFileStatus); 
          m_pb.setProgress(mProgressCurrentFileStatus); 
         } 
        }); 

        Log.d(LOGid, "Set progress to " + downloadedSize); 
       } 
       // close the output stream when done 
       fileOutput.close(); 
       Log.d(LOGid, "closed the output file"); 

       mHandler.post(new Runnable() 
       { 
        public void run() 
        { 
         tvCurrent.setText("Finished Downloading file " + m_dest + "..."); 
        } 
       }); 
       m_downloadSuccess = true; 
       // catch some possible errors... 
      } catch (MalformedURLException e) 
      { 
       Log.d(LOGid, "Error dowloading file:" + e.getMessage() 
         + "...malformed URL"); 
       m_downloadSuccess = false; 
      } catch (IOException e) 
      { 
       Log.d(LOGid, "Error dowloading file:" + e.getMessage() 
         + "...IO Exception"); 
       m_downloadSuccess = false; 
      } catch (Exception e) 
      { 
       Log.d(LOGid, "Error dowloading file:" + e.getMessage() 
         + "...generic exception"); 
       m_downloadSuccess = false; 
      } 
     } 
    }).start(); 

    return m_downloadSuccess; 
} 
+0

並且所有日誌設置進度都會顯示? – Snicolas

+0

是的,下載工作和日誌顯示更新。 –

回答

4

它看起來像你這樣做,你測量的進步你的UI線程內工作(直接從回調,而不是放置一個新的線程中調用)。這不會給系統任何CPU時間來響應您的臨時進度更新。

處理這個問題的正確方法是在後臺線程中完成工作,並定期更新進度。這些更新必須發生在UI線程內,但您的Activity的runOnUiThread(Runnable)方法可以爲您完成。 (另外,您可以發佈可運行在您的活動的處理程序UI線程執行。)

編輯:添加例如線程創建 你的工作在你的downloadFiles()方法來實現,所以這是你在想什麼一個單獨的線程。更換你downloadFiles()的呼叫,例如,

Thread worker = new Thread(new Runnable() { 
    @Override 
    public void run() { 
     downloadFiles(); 
    } 
}); 
worker.start(); 

現在,你還需要修改downloadFiles() - 因爲它不是在UI線程上,它是不允許修改的UI。您不需要調用pb.setMax(totalSize);,而需要在UI線程中執行該操作。您可以編寫一個可運行(或幾個)修改UI從正確的線程以類似的方式來運行一個新的線程:

runOnUiThread(new Runnable() { 
    @Override 
    public void run() { 
     // do things that modify the UI 
    } 
}); 

你必須要小心這裏的唯一的事 - 你可運行的run()方法可能需要訪問包含runOnUiThread()調用的方法中的某些局部變量。爲了合法地提供該訪問,它使用的變量必須爲final。如果您的變量不能最終確定,您需要將它們的值複製到可運行使用的最終變量中。例如:

final ProgressBar final_pb = pb; 
final int final_downloadedSize = downloadedSize; 
runOnUiThread(new Runnable() { 
    @Override 
    public void run() { 
     final_pb.setProgress(final_downloadedSize); 
    } 
}); 
+0

好的,謝謝,這不是我想到的。這似乎是一個好方法。我對Java/Android線程不熟悉,任何機會我都可能會面露面,並要求提供一個基本示例來說明如何分離可以更新我的UI的線程? –

+0

這個答案是正確的。如果你需要一個如何做到這一點的例子,那麼在Android示例代碼(ApiDemos/src/com/example/android/apis/app/AlertDialogSamples.java)中的ApiDemos應用程序中有一個例子。如果我想教你如何吸雞蛋,我很抱歉。 –