不可见的进度条未通过代码显示

Posted

技术标签:

【中文标题】不可见的进度条未通过代码显示【英文标题】:Invisible Progress Bar not showing up through code 【发布时间】:2018-12-13 16:07:26 【问题描述】:

我正在制作一个项目 android 应用程序,它采用图像 URL、下载图像并显示图像。如果图像尺寸较大,我想向用户显示图像正在下载的不确定进度。

Java 代码:

public class MainActivity extends AppCompatActivity 

    ImageView downloadedImg;
    ProgressBar progressBar;
    Handler handler;


    public void downloadImage(View view)

        progressBar.setVisibility(View.VISIBLE);

        ImageDownloader task = new ImageDownloader();
        Bitmap myimage;
        try 
            myimage = task.execute("http://wallpaperswide.com/download/high_tech_earth-wallpaper-2880x1800.jpg").get();
            downloadedImg.setImageBitmap(myimage);
        
        catch (Exception e) 
            e.printStackTrace();
        
    

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        downloadedImg = (ImageView)findViewById(R.id.imageView);
        progressBar = (ProgressBar)findViewById(R.id.pbar);
        handler = new Handler();

    

    public class ImageDownloader extends AsyncTask<String,Void,Bitmap>

        protected void onPreExecute()
            super.onPreExecute();
            //progressBar.setVisibility(View.VISIBLE);
        

        @Override
        protected Bitmap doInBackground(String... urls) 
            try 
                URL url = new URL(urls[0]);
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.connect();
                InputStream inputStream = connection.getInputStream();
                Bitmap mybitmap = BitmapFactory.decodeStream(inputStream);
                return mybitmap;
            
            catch (Exception e) 
                e.printStackTrace();
            
            return null;
        

        @Override
        protected void onPostExecute(Bitmap bitmap) 
            super.onPostExecute(bitmap);
            handler.post(new Runnable() 
                @Override
                public void run() 
                    progressBar.setVisibility(View.GONE);
                    downloadedImg.setVisibility(View.VISIBLE);
                
            );
        

    

    public void reset(View view)
        downloadedImg.setVisibility(View.GONE);
        progressBar.setVisibility(View.INVISIBLE);
    

XML 代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    tools:context="com.example.syeddanish.downloadingimages.MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_
        android:layout_
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:onClick="downloadImage"
        android:text="Download Image" />

    <Button
        android:id="@+id/button1"
        android:layout_
        android:layout_
        android:layout_below="@+id/button"
        android:onClick="reset"
        android:text="Reset" />

    <ProgressBar
        android:id="@+id/pbar"
        android:layout_
        android:layout_
        android:layout_centerVertical="true"
        android:indeterminate="true"
        android:visibility="invisible" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_
        android:layout_
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:visibility="gone"
        android:layout_below="@+id/button1" />


</RelativeLayout>

我面临的问题是我希望进度条在下载开始时变得可见(即当“按下下载图像按钮”时)。我试图以两种方式做到这一点,即

    在开头使用progressbar.setVisibility(View.VISIBLE); “下载图片”按钮的onClick方法。 或 通过在 ASyncTask 的 onPreExecute() 方法中使用 progressbar.setVisibility(View.VISIBLE);,但使用上述任何一种方式都不会显示进度条。

谁能指出我做错了什么?

【问题讨论】:

我猜问题出在 xml 上,不推荐使用 fill_parent,而是使用匹配父级或使用特定的高度和宽度 我认为您的代码没有错误。可能是您使用的progressbar 的颜色? 【参考方案1】:

没有NetworkOnMainThreadException,这段代码能编译和运行吗? 你的问题是get()的用法

在这部分:

        Bitmap myimage;
    try 
        myimage = task.execute("http://wallpaperswide.com/download/high_tech_earth-wallpaper-2880x1800.jpg").get();
        downloadedImg.setImageBitmap(myimage);
    

您尝试从 task.execute(...) 获取图像,但 task.get() 根据文档:

   [...]Waits if necessary for the computation to complete, and then retrieves its result.[...]

所以你正在等待你的“任务”在主线程上执行并阻塞它,直到完成。正因为如此,你的进步 永远不可见,因为 UI 线程被阻塞。一旦你的任务完成, 进度被设置为不可见。

此外,不要重新发明轮毂。使用可用的库之一 用于图像下载和缓存。

例如:Picasso、Glide

两者还提供使用 (1) 后备和 (2) 加载图像的功能。


如果您仍想自己尝试,请不要使用 Pokémon-“gotta catch'em all” 方法来捕获您的异常,而是处理特定的 Exceptions可能会发生并向用户显示一条消息,将其发送给您的崩溃跟踪器等。只捕获您希望抛出的异常,否则......让它崩溃。

我不明白,为什么你应该在那里捕获异常。

AsyncTask、Activity 和内存泄漏

接下来是 AsyncTasks 没有整齐地耦合到 Activities 生命周期。当您运行任务并在后台执行时,但是 您的活动完成后,此任务仍将处于活动状态并泄漏对您的活动的引用。这会导致内存泄漏,因为 GC 无法正确完成它的工作,在你之后清理。

让您的 AsyncTask 至少是一个静态类,并在您的活动完成后停止/杀死该任务。

多项任务

接下来,检查您是否已经下载了图像,一旦用户单击了按钮,或者您将创建多个任务。

因此,让您的 ImageDownloader 成为您的活动的成员,并检查它是否已经在执行或完成。 (将其从您的方法中取出,并将其放在活动类头下方)。当您的活动调用onPause()onDestroy() 时,用火杀死任务。

也要注意方向变化

Android 任务 API 而非 AsyncTask

我强烈推荐使用 android task api。 (com.google.android.gms.tasks)

它非常适合在主线程或工作线程上运行的任务。包括延续,提供类似Future 的功能,并且可以与活动耦合。

参考:gms Task API Doc

【讨论】:

感谢您详尽的回答。我试图理解你所指出的,但我只想说我是一个初学者,知道的不多。我刚刚开始学习 android,这是我尝试制作的第一个应用程序之一,以了解线程的概念。因此,如果您能在基础水平上指导我,我将不胜感激。 顺便感谢您抽出宝贵的时间:)【参考方案2】:

尝试将downloadedImg.setImageBitmap(myimage); 放入onPostExecute(Bitmap bitmap)handler 并更改:

myimage = task.execute("http://wallpaperswide.com/download/high_tech_earth-wallpaper-2880x1800.jpg").get();

到:

task.execute("http://wallpaperswide.com/download/high_tech_earth-wallpaper-2880x1800.jpg");

还将Bitmap myimage; 作为全局变量放在您的 Asynctask 类上并进行更改:

Bitmap mybitmap = BitmapFactory.decodeStream(inputStream);
            return mybitmap;

到:

myimage= BitmapFactory.decodeStream(inputStream);

在 doInBackground 上

【讨论】:

很高兴能帮上忙 :) 你太好了?【参考方案3】:

考虑使用pBar.setAlpha(1f);

当我遇到类似问题时,它会有所帮助。

【讨论】:

以上是关于不可见的进度条未通过代码显示的主要内容,如果未能解决你的问题,请参考以下文章

react-bootstrap 的进度条未显示

Python 进度条未正确显示进度

Bootstrap 4 进度条未显示

带有英雄单元文本的 Twitter Bootstrap 进度条未正确显示

单击页面上的任意位置后,Android中的进度条未显示

当 UITableView 单元格中的进度条不可见时,如何更新它们