我正在制作一个项目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>
我面临的问题是我希望进度条在下载开始时(例如,当按下“下载图像按钮”时)变得可见。我正在尝试通过两种方式做到这一点,即
progressbar.setVisibility(View.VISIBLE);
单击“下载图像”按钮的onClick方法。
或progressbar.setVisibility(View.VISIBLE);
,但是使用上述任何一种方法都不会显示进度条。任何人都可以指出我在做什么错吗?
答案 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被阻止了。一旦完成任务, 进度被设置为不可见。
此外,不要重新发明焊缝。使用那里可用的库之一 用于图像下载和缓存。
两者均提供使用(1)后备和(2)加载图片的功能。
如果您仍然想自己尝试,请不要使用Pokémon-“ gotta catch'em all” 来捕获异常的方法,而应处理特定的{{1} },并向用户显示一条消息,向您发送崩溃跟踪器等。仅捕获您希望抛出的异常,否则...使其崩溃。
我不明白,为什么您要在那里捕获异常。
AsyncTask,活动和内存泄漏
接下来是,Exceptions
没有整齐地耦合到AsyncTasks
生命周期。当您运行任务并在后台执行时,但是
您的活动完成后,此任务仍将保留,并且会泄漏对您的活动的引用。这会导致内存泄漏,因为GC无法正确执行它的工作,请在您清除之后清除它。
在活动结束后,至少使您的AsyncTask成为静态类,并停止/杀死任务。
多个任务
接下来,检查用户单击按钮后是否已经下载了图像,或者要创建多个任务。
因此,让您的ImageDownloader成为您活动的成员,并检查其是否已经执行或完成。 (将其从您的方法中取出并放在活动类的标题下面)。当您的活动呼叫Activities
或onPause()
时,请用火杀死该任务。
也要注意方向变化。
Android Task API而不是AsyncTask
我强烈建议您使用android任务api。 (onDestroy()
)
它非常适合在主线程或工作线程上运行的任务。包括延续,提供com.google.android.gms.tasks
类似的功能,并且可以与“活动”结合使用。
答案 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);
当我遇到类似问题时,它会有所帮助。