Как запустить CountDownTimer, когда я не в основном потоке - PullRequest
1 голос
/ 10 февраля 2012

Я пытаюсь загрузить файл с URL.Если загрузка не удалась (независимо от причины), я хочу, чтобы приложение повторило попытку через час.

Поскольку загрузка происходит в своей собственной ветке (а не в основной), я не могу запустить новуюТаймер обратного отсчета.

Я не хочу блокировать поток загрузки, поэтому я пытаюсь использовать CountDownTimer.

Есть ли другой способ сделать это?

Заранее спасибо!

private class Downloader extends AsyncTask<Object, Void, File> 
{

    @Override
    protected File doInBackground(Object... params) 
    {
        Context context = (Context) params[0];
        String strUrl = (String) params[1];
        String strFileName = (String) params[2];
        return download(context, strUrl, strFileName);
    }


    /**
     * Downloads files in a separate thread.  Adds notification of download to status bar.
     */
    public File download(final Context context, final String url, final String fileName)
    {
        boolean isVideoLoaded=false;
            try
            {                   
                    URL urlObj = new URL(url);
                    URLConnection con = urlObj.openConnection();
                    BufferedInputStream bis = new BufferedInputStream(con.getInputStream(), BUFFER_SIZE);

                    FileOutputStream fos = new FileOutputStream(retFile);
                    byte[] bArray = new byte[BUFFER_SIZE];
                    int current = 0;
                    int read = 0;
                    while(current != -1)
                    {
                        fos.write(bArray,0,current);
                        current = bis.read(bArray, 0, BUFFER_SIZE);
                        read = read + current;

                    }
                    fos.close();
                    bis.close();
                    isVideoLoaded = true;

                strFileName = retFile.getAbsolutePath();
            }
            catch(Exception ioe)
            {
                Log.d("Downloader.download", "Error: " + ioe.toString(), ioe);

            }
        }
        if (!isVideoLoaded) // if video is still not loaded
        {
            // sleep then try again
            new CountDownTimer(15000, 2000) 
            {

                public void onFinish()
                {

                        Downloader dh = new Downloader();

                        Object params[] = new Object[3];
                        params[0] = context;
                        params[1] = url;
                        params[2] = fileName;*/

                        dh.execute(params);    
                }

                @Override
                public void onTick(long millisUntilFinished) {
                    // TODO Auto-generated method stub
                }
            }.start();
        }
        return retFile;

    }


    protected void onPostExecute(File file) {
            // display downloaded file
    }

Ответы [ 2 ]

1 голос
/ 10 февраля 2012

Вы можете создать таймер, который начнет загрузку в вашем потоке пользовательского интерфейса.В вашем UI-классе используйте эту функцию

private StartOneHourTimer()
{
new CountDownTimer(10000 * 3600, 1000) {
     public void onTick(long millisUntilFinished) {
         mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
     }
     public void onFinish() {
         m_downloader = new Downloader(..);
         m_downloader.execute(..);
     }
  }.start();
}

В вашем Downloader onPostExecute () запустите новый таймер, срок действия которого истекает через 1 час.

protected void onPostExecute(File file)
    {
        if (!isVideoLoaded)
          startOneHourTimer();
        else
          //Call your normal UI code here
    }
0 голосов
/ 10 февраля 2012

Измените onPostExecute так, чтобы он вызывал к основному действию, чтобы показать, что загрузка не удалась (должна быть в состоянии добраться до него по MyMainActivity.this.someMethod().) Затем основное действие может сделать новый AsyncTask ( не использовать старый) и показать, что он должен отложить запуск.

Один из способов сделать это - добавить конструктор в AsyncTask, чтобы вы могли передать ему параметр задержки, тогда ваш AsyncTask может использовать параметр задержки как часть метода doInBackground.

Внутри doInBackground просто подождите с Thread.sleep()

...