【问题标题】:Trying to get downloading file size, but get an error尝试获取下载文件大小,但出现错误
【发布时间】:2011-03-12 09:39:33
【问题描述】:
private class DownloadLargeFileTask extends AsyncTask<Void, Void, Void> 
{
    private final ProgressDialog dialog;

    public DownloadLargeFileTask(ProgressDialog dialog) {
         this.dialog = dialog;
    }

    protected void onPreExecute() {
        dialog.show();
    }


    protected void onPostExecute(Void unused) {
        dialog.dismiss();
    }

    @Override
    protected Void doInBackground(Void... arg0) {
        download();
        return null;
    }
}

private void download ()
{
    try 
    {
        long startTime = System.currentTimeMillis();

        URL u = new URL("http://mds.podfm.ru/188/download/040_Sergejj_Palijj_-_Karantin_CHast_2.mp3");
        HttpURLConnection c = (HttpURLConnection) u.openConnection();

        c.setRequestMethod("GET");
        c.setDoOutput(true);
        c.connect();
        FileOutputStream f = new FileOutputStream(new File("/sdcard/","my.mp3"));

        InputStream in = c.getInputStream();

        byte[] buffer = new byte[1024];
        int len1 = 0;
        int downloadedSize = 0;
        while ( (len1 = in.read(buffer)) != -1 ) 
        {
          f.write(buffer,0, len1);
          downloadedSize += len1; 
          ReturnDownloadedBytes(downloadedSize);
        }
        f.close();
        Log.d("ImageManager", "download ready in" + ((System.currentTimeMillis() - startTime) / 1000) + " sec");
    }
    catch (IOException e)
    {
        Log.d("ImageManager", "Error" + ((System.currentTimeMillis()) / 1000) + e + " sec");
    }
}

private void ReturnDownloadedBytes(int size)
{
    text.setText(String.valueOf(size));

}

错误说:只有创建视图层次结构的原始线程才能接触其视图。 我认为这意味着我从一个 therad 创建 textview 并尝试从另一个(AsyncTask)获得访问权限,但如何获得它? 谢谢

编辑
这是所有代码。但即使我发送 publishProgress(downloadedSize) int value = 10 它总是输出 text.setText(String.valueOf(progress)); 不同的值,如 [Ljava.lang.float;@43ed62f78

public class list extends Activity {

private TextView text;



@Override
public void onCreate(Bundle icicle)
{
    super.onCreate(icicle);
    setContentView(R.layout.main);

    text = (TextView)findViewById(R.id.result);
}

public void selfDestruct(View view) {

    ProgressDialog dialog = new ProgressDialog(this);
    dialog.setMessage("????????. ?????...");
    new DownloadLargeFileTask(dialog).execute();

}


private class DownloadLargeFileTask extends AsyncTask<Void, Integer, Void> 
{
    private final ProgressDialog dialog;

    public DownloadLargeFileTask(ProgressDialog dialog) {
         this.dialog = dialog;
    }

    protected void onPreExecute() {
        dialog.show();
    }


    protected void onPostExecute(Void unused) {
        dialog.dismiss();
    }

    protected void onProgressUpdate(Integer...progress) {

        text.setText(String.valueOf(progress));

    }

    @Override
    protected Void doInBackground(Void... arg0) {
        try 
        {
            long startTime = System.currentTimeMillis();

            URL u = new URL("http://mds.podfm.ru/188/download/040_Sergejj_Palijj_-_Karantin_CHast_2.mp3");
            HttpURLConnection c = (HttpURLConnection) u.openConnection();

            c.setRequestMethod("GET");
            c.setDoOutput(true);
            c.connect();
            FileOutputStream f = new FileOutputStream(new File("/sdcard/","my.mp3"));

            InputStream in = c.getInputStream();

            byte[] buffer = new byte[1024];
            int len1 = 0;
            int downloadedSize = 10;
            while ( (len1 = in.read(buffer)) != -1 ) 
            {
              f.write(buffer,0, len1);
              //downloadedSize += len1; 
              **publishProgress(downloadedSize);**
            }
            f.close();
            Log.d("ImageManager", "download ready in" + ((System.currentTimeMillis() - startTime) / 1000) + " sec");
        }
        catch (IOException e)
        {
            Log.d("ImageManager", "Error" + ((System.currentTimeMillis()) / 1000) + e + " sec");
        }
        return null;
    }
}

【问题讨论】:

    标签: android multithreading android-asynctask


    【解决方案1】:

    您对错误的评估是正确的。我假设text 是在Activity 中定义的TextView 对象,因此它是在UI 线程中创建的。在doInBackground() 中运行的代码在单独的线程中运行。只有 UI 线程可以对 UI 元素执行更新,因此当您尝试调用 setText 时,您会收到您报告的错误消息。

    Abhinav 在如何解决该问题方面也是正确的,因为 AsyncTask 有一个方法,您可以调用该方法将更新从后台线程发送到 UI 线程:publishProgress,它调用 onProgressUpdate()

    将此方法添加到您的AsyncTask

    @Override
    protected void onProgressUpdate(Integer... integer){
        text.setText(integer[0].toString());
    }
    

    并更改download() 中的while 循环:

    while ( (len1 = in.read(buffer)) != -1 ) 
    {
      f.write(buffer,0, len1);
      downloadedSize += len1; 
      publishProgress(downloadedSize);
    }
    

    【讨论】:

    • 你能解释一下“URL,Integer,Long”在这个“私有类 DownloadFilesTask 扩展 AsyncTask”中是什么意思,以及这个 params/ 的顺序有什么不同。谢谢
    • 当我调用 text.setText(String.valueOf(progress));结果我在 TextView 中得到类似 [Ljava.lang.float;@43ed62f78 - 这是什么意思?
    • @SERG 检查documentation,它们是ParamsProgressResult。我需要查看更多代码来诊断其他问题。
    • @SERG 请不要发布新问题作为对现有问题的回答。也就是说,将上面的代码与您的代码进行比较,您可以看到onProgressUpdate() 的参数是一个值的array,这就是我使用integer[0].toString() 来获取所需值的原因。当您使用String.valueOf(progress) 时,您将只是内存位置,因为progress 是一个数组。请使用我在回答中提供的方法。
    【解决方案2】:

    您可以通过将进度发布到 UI 线程来更改 UI。从 doInBackground 调用 publishProgress。这将在您的 AsyncTask 中调用 onProgressUpdate,您可以从中更新 UI。

    您必须在 AsyncTask 中定义 onProgressUpdate。 http://developer.android.com/reference/android/os/AsyncTask.html#onProgressUpdate(Progress...)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-21
      • 1970-01-01
      • 1970-01-01
      • 2011-07-12
      • 1970-01-01
      • 2020-11-11
      • 1970-01-01
      • 2019-02-08
      相关资源
      最近更新 更多