隐藏的进度栏无法通过代码显示

时间:2018-07-05 08:39:08

标签: android android-asynctask android-progressbar

我正在制作一个项目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>

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

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

任何人都可以指出我在做什么错吗?

3 个答案:

答案 0 :(得分:2)

此代码是否可以在没有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-Thread被阻止了。一旦完成任务, 进度被设置为不可见。

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

例如:PicassoGlide

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


如果您仍然想自己尝试,请不要使用Pokémon-“ gotta catch'em all” 来捕获异常的方法,而应处理特定的{{1} },并向用户显示一条消息,向您发送崩溃跟踪器等。仅捕获您希望抛出的异常,否则...使其崩溃。

我不明白,为什么您要在那里捕获异常。

AsyncTask,活动和内存泄漏

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

在活动结束后,至少使您的AsyncTask成为静态类,并停止/杀死任务。

多个任务

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

因此,让您的ImageDownloader成为您活动的成员,并检查其是否已经执行或完成。 (将其从您的方法中取出并放在活动类的标题下面)。当您的活动呼叫ActivitiesonPause()时,请用火杀死该任务。

也要注意方向变化

Android Task API而不是AsyncTask

我强烈建议您使用android任务api。 (onDestroy()

它非常适合在主线程或工作线程上运行的任务。包括延续,提供com.google.android.gms.tasks类似的功能,并且可以与“活动”结合使用。

参考:gms Task API Doc

答案 1 :(得分:1)

尝试将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类上并进行更改:

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

收件人:

myimage= BitmapFactory.decodeStream(inputStream);

在doInBackground上

答案 2 :(得分:0)

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

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