不可见的进度条未通过代码显示
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);
当我遇到类似问题时,它会有所帮助。
【讨论】:
以上是关于不可见的进度条未通过代码显示的主要内容,如果未能解决你的问题,请参考以下文章