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

Invisible Progress Bar not showing up through code

我正在制作一个项目 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_width="fill_parent"
    android:layout_height="match_parent"
    tools:context="com.example.syeddanish.downloadingimages.MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        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_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button"
        android:onClick="reset"
        android:text="Reset" />

    <ProgressBar
        android:id="@+id/pbar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:indeterminate="true"
        android:visibility="invisible" />

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


</RelativeLayout>

我面临的问题是我希望进度条在下载开始时可见(即 "Download Image button is pressed" 时)。我正在尝试以两种方式做到这一点,即

  1. 通过在开头使用 progressbar.setVisibility(View.VISIBLE); "Download Image" 按钮的 onClick 方法。 或
  2. 通过在 ASyncTask 的 onPreExecute() 方法中使用 progressbar.setVisibility(View.VISIBLE);,但使用上述任何方法都不会显示进度条。

谁能指出我做错了什么?

没有 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.[...]

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

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

例如:Picasso, Glide

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


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

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

AsyncTask、Activity 和内存泄漏

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

让你的 AsyncTask 至少是静态的 class 和 stop/kill 任务,一旦你的 activity 完成。

多项任务

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

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

也要注意 方向变化

Android 任务 API 而不是 AsyncTask

我强烈建议使用 android 任务 api。 (com.google.android.gms.tasks)

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

参考文献:gms Task API Doc

尝试将 downloadedImg.setImageBitmap(myimage); 放入 onPostExecute(Bitmap bitmap) 处理程序并更改:

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 class 上并更改:

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

至:

myimage= BitmapFactory.decodeStream(inputStream);

关于 doInBackground

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

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