2014-05-17 77 views
0

我使用AsyncTask下載視頻文件我在AsyncTask內更新視圖,但會出現異常「只有創建視圖層次結構的原始線程才能觸及其視圖」。這是我的示例代碼。請檢查它,並建議我在哪裏需要更正。如何避免異常「只有創建視圖層次結構的原始線程才能觸及其視圖」?

在這些行中出現異常。

tvPercent.setText((int)per + "%"); 
tvSpeed.setText(networkSpeed+"kbps"); 

的AsyncTask類

public class DownloadFileFromURL extends AsyncTask<String, String, String> { 

    ProgressBar ProgBar; 
    TextView tvSpeed; 
    TextView tvPercent; 

    int downloadedSize = 0; 
    int totalSize = 0; 

    private long networkSpeed;  
    private long previousTime; 
    private long totalTime; 

// public DownloadFileFromURL(ProgressBar pb) 
// { 
//  ProgBar = pb; 
//  
// } 

    public DownloadFileFromURL(ProgressBar pb, TextView speed, TextView per) 
    { 
     ProgBar = pb; 
     tvSpeed = speed; 
     tvPercent = per; 
    } 


    @Override 
    protected void onPreExecute() 
    { 
     super.onPreExecute(); 

     ProgBar.setProgress(0); 
     //ProgBar.setMax(100); 

     previousTime = System.currentTimeMillis(); 
    } 


    @Override 
    protected String doInBackground(String... videoURL) 
    { 
     try 
     { 

      URL url = new URL(videoURL[0]); 
      HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); 

      urlConnection.setRequestMethod("GET"); 
      urlConnection.setDoOutput(true); 

      //connect 
      urlConnection.connect(); 

      File file = getOutputMediaFile(videoURL[0]); 

      FileOutputStream fileOutput = new FileOutputStream(file); 

      //Stream used for reading the data from the internet 
      InputStream inputStream = urlConnection.getInputStream(); 

      //this is the total size of the file which we are downloading 
      totalSize = urlConnection.getContentLength(); 

      Log.e("Download", ""+totalSize); 

      ProgBar.setMax(totalSize); 




      //create a buffer... 
      byte[] buffer = new byte[1024]; 
      int bufferLength = 0; 

      while ((bufferLength = inputStream.read(buffer)) > 0) 
      { 
       fileOutput.write(buffer, 0, bufferLength); 
       downloadedSize += bufferLength; 



       // update the progressbar // 
       ProgBar.setProgress(downloadedSize); 



       float per = ((float)downloadedSize/totalSize) * 100; 
       // update the progress in percentage // 
       tvPercent.setText((int)per + "%"); 


       totalTime = System.currentTimeMillis() - previousTime; 
       networkSpeed = downloadedSize/totalTime; 

       // update network speed // 
       tvSpeed.setText(networkSpeed+"kbps"); 




      } 

      //close the output stream when complete // 
      fileOutput.close(); 
      downloadedSize = 0; 
      totalSize = 0; 




     } 
     catch (final MalformedURLException e) 
     {  
      e.printStackTrace(); 
     } 
     catch (final IOException e) 
     {   
      e.printStackTrace(); 
     } 
     catch (final Exception e) 
     { 
      e.printStackTrace(); 
     } 

     return null; 
    } 


    protected void onProgressUpdate(String... progress) 
    { 
     // setting progress percentage 
     //ProgBar.setProgress(Integer.parseInt(progress[0])); 
    } 


    @Override 
    protected void onPostExecute(String file_url) 
    { 

    } 




} 
+0

您應該'setText'到'TextView'在'onProgressUpdate'或'onPostExecute' – Raghunandan

+0

我的推杆內onProgressUpdate(TextView的),但是TextView的沒有方法裏面有更新。 – Android

+0

閱讀asynctask的文檔並相應地更改 – Raghunandan

回答

2

只能從主線程更新UI。將tvPercent.setText((int)per + "%");更改爲onProgressUpdate,並在doInBackground中隨時調用publishProgress(.)以更新文本。

+0

親愛的!請詳細說明一下。當我從doInBackground()方法中刪除TextView時,然後progressBar在doInBackground()方法內更新得非常好,我沒有明白你的觀點 – Android

0

我拿了很多次相同的問題,然後最終我得到了這個問題的最終解決方案。 刪除所有更改xml的代碼或更新佈局xml文件的背景方法在後執行方法上執行。

+0

。 ProgBar.setProgress(downloadedSize); – Android

0

AsyncTask在單獨的線程中執行其主要工作(在doInBackground方法中),但只有主線程才能訪問用戶界面。 doInBackground中的代碼無法訪問用戶界面。

在主線程上調用方法onPreExecute,onProgressUpdate,onPostExecute。在這些方法中訪問用戶界面。

在doInBackground中調用publishProgress以在主線程上調用onProgressUpdate。

Read all about AsyncTask here.

相關問題