Android
Android

Reputation: 82

How to avoid exception "Only the original thread that created a view hierarchy can touch its views"?

I am using AsyncTaskfor downloading video file I am update views inside the AsyncTask but exception arises "Only the original thread that created a view hierarchy can touch its views". Here is my sample code. Please check it and suggest me where I need correction.

The exception arises at these lines.

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

AsyncTask Class

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)
    {

    }




}

Upvotes: 0

Views: 945

Answers (3)

Tim
Tim

Reputation: 36

AsyncTask does its main work(in doInBackground method) on a separate thread, but only the main thread can access the user interface. Code in doInBackground can not access the user interface.

The methodes onPreExecute, onProgressUpdate, onPostExecute is invoked on the main thread. Do any access to the user interface in these methods.

Call publishProgress in doInBackground to invoke onProgressUpdate on the main thread.

Read all about AsyncTask here.

Upvotes: 0

Devganiya Hitesh
Devganiya Hitesh

Reputation: 1207

I Fetched same problem many time then finally i got final solution for this problem. remove all code that that change xml or update layout xml file from background method do it on post execute method.

Upvotes: 0

Mus
Mus

Reputation: 1860

You can update UI only from the main thread. Move tvPercent.setText((int)per + "%"); to onProgressUpdate and call publishProgress(.) in doInBackground whenever you want to update the text.

Upvotes: 2

Related Questions