Как установить изображение из Url с помощью AsyncTask?
Я программист-новичок. Я делаю программу для Android, которая отображает изображение на ImageView с заданного URL-адреса. Моя проблема заключается в том, как вы используете это в AsyncTask?
Эти коды работают на min SDK 2.2, но я переключился на min SDK 3.0, поэтому он должен запускаться на AsyncTask. Спасибо за помощь!:)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
satellite(); //satellite image from main menu
}
//******satellite url
private void satellite() {
// TODO Auto-generated method stub
ImageView imgView =(ImageView)findViewById(R.id.satellite);
Drawable drawable = LoadImageFromWeb("http://www.pagasa.dost.gov.ph/wb/sat_images/satellite.gif");
imgView.setImageDrawable(drawable);
}
private Drawable LoadImageFromWeb(String url){
try{
InputStream is = (InputStream) new URL(url).getContent();
Drawable d = Drawable.createFromStream(is, "src name");
return d;
}catch (Exception e) {
System.out.println("Exc="+e);
return null;
}
}
Ответы
Ответ 1
Ну, я не знаю, почему SDK для Android не поддерживает его (пока). Я расширил класс ImageView классом UrlImageView с поддержкой асинхронной загрузки и кэширования. Я помещаю код моего класса ниже, который подключается и воспроизводится. Тело класса находится в конце моего сообщения, теперь я пишу две строки, как использовать его удобным способом.
Теперь поддерживаются еще два метода:
setImageUrl(URL url) // sets the bitmap by its URL
cancelLoading(); // tell this view to cancel pending load
Как использовать Java-код:
// [somewhere in your activity]
UrlImageView urlImg = new UrlImageView(this).setImageUrl("http://abc.png");
...
urlImg.setImageUrl("http://abc2.png"); // works like expected
Как связать в своих макетах:
<!-- thumbnail -->
<com.gplushub.android.view.UrlImageView
android:id="@+id/thumbnail"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_gravity="center_vertical"
android:layout_marginRight="2dp"
android:scaleType="fitXY" />
.. и снова в вашем действии java-код:
((UrlImageView)findViewById(R.id.thumbnail)).setImageUrl("http://foo.bar.png");
Я использую его в списках с более чем 100 записями - очень хорошо flinging. Здесь тело класса, вы можете использовать его, модифицировать, расширять, что угодно:
package com.gplushub.android.view;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
/**
* an {@link ImageView} supporting asynchronous loading from URL. Additional
* APIs: {@link #setImageURL(URL)}, {@link #cancelLoading()}.
*
* @author [email protected] / Eugen Plischke
*
*/
public class UrlImageView extends ImageView {
private static class UrlLoadingTask extends AsyncTask<URL, Void, Bitmap> {
private final ImageView updateView;
private boolean isCancelled = false;
private InputStream urlInputStream;
private UrlLoadingTask(ImageView updateView) {
this.updateView = updateView;
}
@Override
protected Bitmap doInBackground(URL... params) {
try {
URLConnection con = params[0].openConnection();
// can use some more params, i.e. caching directory etc
con.setUseCaches(true);
this.urlInputStream = con.getInputStream();
return BitmapFactory.decodeStream(urlInputStream);
} catch (IOException e) {
Log.w(UrlImageView.class.getName(), "failed to load image from " + params[0], e);
return null;
} finally {
if (this.urlInputStream != null) {
try {
this.urlInputStream.close();
} catch (IOException e) {
; // swallow
} finally {
this.urlInputStream = null;
}
}
}
}
@Override
protected void onPostExecute(Bitmap result) {
if (!this.isCancelled) {
// hope that call is thread-safe
this.updateView.setImageBitmap(result);
}
}
/*
* just remember that we were cancelled, no synchronization necessary
*/
@Override
protected void onCancelled() {
this.isCancelled = true;
try {
if (this.urlInputStream != null) {
try {
this.urlInputStream.close();
} catch (IOException e) {
;// swallow
} finally {
this.urlInputStream = null;
}
}
} finally {
super.onCancelled();
}
}
}
/*
* track loading task to cancel it
*/
private AsyncTask<URL, Void, Bitmap> currentLoadingTask;
/*
* just for sync
*/
private Object loadingMonitor = new Object();
public UrlImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public UrlImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public UrlImageView(Context context) {
super(context);
}
@Override
public void setImageBitmap(Bitmap bm) {
cancelLoading();
super.setImageBitmap(bm);
}
@Override
public void setImageDrawable(Drawable drawable) {
cancelLoading();
super.setImageDrawable(drawable);
}
@Override
public void setImageResource(int resId) {
cancelLoading();
super.setImageResource(resId);
}
@Override
public void setImageURI(Uri uri) {
cancelLoading();
super.setImageURI(uri);
}
/**
* loads image from given url
*
* @param url
*/
public void setImageURL(URL url) {
synchronized (loadingMonitor) {
cancelLoading();
this.currentLoadingTask = new UrlLoadingTask(this).execute(url);
}
}
/**
* cancels pending image loading
*/
public void cancelLoading() {
synchronized (loadingMonitor) {
if (this.currentLoadingTask != null) {
this.currentLoadingTask.cancel(true);
this.currentLoadingTask = null;
}
}
}
}
Ответ 2
Если изображение не так велико, вы можете просто использовать анонимный класс для задачи async. Это было бы так:
ImageView mChart = (ImageView) findViewById(R.id.imageview);
String URL = "http://www...anything ...";
mChart.setTag(URL);
new DownloadImageTask.execute(mChart);
и класс задачи
public class DownloadImagesTask extends AsyncTask<ImageView, Void, Bitmap> {
ImageView imageView = null;
@Override
protected Bitmap doInBackground(ImageView... imageViews) {
this.imageView = imageViews[0];
return download_Image((String)imageView.getTag());
}
@Override
protected void onPostExecute(Bitmap result) {
imageView.setImageBitmap(result);
}
private Bitmap download_Image(String url) {
...
}
Ответ 3
Попробуйте этот код, сделайте свою переменную переменной глобальной и измените свою спутниковую функцию следующим образом:
private void satellite() {
// TODO Auto-generated method stub
ImageView imgView =(ImageView)findViewById(R.id.satellite);
new yourTask().execute();
}
затем создайте класс asyncTask следующим образом:
private class yourTask extends AsyncTask<Integer, Void, Integer> {
@Override
protected void onPreExecute() {
super.onPreExecute();
//show a progress bar
}
@Override
protected String doInBackground(Integer... params) {
drawable = LoadImageFromWeb("http://www.pagasa.dost.gov.ph/wb/sat_images/satellite.gif");
return 0;
}
@Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
imgView.setImageDrawable(drawable);
}
}
Ответ 4
Вот код для реализации Aynctask
Сделайте свой вытачиваемый объект глобальным в классе Aynctask.
Class MyDownloader extends AsyncTask<Void,Void,String>{
Drawable drawable;
@Override
public String doInBackground(Void... args){
drawable = LoadImageFromWeb("http://www.pagasa.dost.gov.ph/wb/sat_images/satellite.gif");
return null; // here you can pass any string on response as on error or on success
}
public void onPostExecute(String result){
if(drawable!=null){
imgView.setImageDrawable(drawable);
}
}
}
теперь создайте объект этого класса и выполните его
private void satellite() {
// TODO Auto-generated method stub
ImageView imgView =(ImageView)findViewById(R.id.satellite);
new MyDownloader.execute();
}
Вот хороший пример ссылки для кэширования изображения, проверьте эту ссылку и пример
https://github.com/novoda/ImageLoader
Ответ 5
Вы правы, когда вы выполняете любую сетевую операцию позже Android 2.2(Froyo)
Должно использовать Asynctask
Это лучший пример, чтобы понять AsyncTask
Ответ 6
на основе ответа from comeGetSome я создал свою собственную реализацию, которая работает с обычным классом ImageView вместо создания нового класса UrlImageView, а также доступны новые параметры: - что делать, когда загрузка завершается или отменяется
Теперь загрузите изображение так, как вы хотите, например, из любого из трех методов loadImage
UrlImageLoader urlImageLoader=new UrlImageLoader();
ImageView imageView=new ImageView(context);
//load and set the image to ImageView
urlImageLoader.loadImage(imageView, "http://www......com/.....jpg");
//for loading a image only - load image and do any thing with the bitmap
urlImageLoader.loadImage("http://www......com/.....jpg", new UrlImageLoader.OnLoadingCompleteListener() {
@Override
public void onComplete(ImageView imageView, Bitmap bmp) {
// do anything with the Bitmap
// here imageView will be null
}
@Override
public void onCancel(ImageView imageView) {
}
});
urlImageLoader.loadImage(imageView, "http://www......com/.....jpg", new UrlImageLoader.OnLoadingCompleteListener() {
@Override
public void onComplete(ImageView imageView, Bitmap bmp) {
// do anything with the Bitmap
// here imageView is not null
imageView.setImageBitmap(bmp);
}
@Override
public void onCancel(ImageView imageView) {
}
});
создать этот класс для загрузки UrlImageLoader
/*special thanks to stackoverflow.com user comeGetSome for UrlImageLoadingTask code
* question - http://stackoverflow.com/questions/14332296/how-to-set-image-from-url-using-asynctask/15797963
* comeGetSome - http://stackoverflow.com/users/1005652/comegetsome
*/
package com.GameG.SealTheBox;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;
public class UrlImageLoader {
public static interface OnLoadingCompleteListener {
public void onComplete(ImageView imageView, Bitmap bmp);
public void onCancel(ImageView imageView);
}
ArrayList<UrlImageLoadingTask> loadingList=new ArrayList<UrlImageLoadingTask>();
/**
* Loads a image from url and calls onComplete() when finished<br>
* @Note you should manually set the loaded image to ImageView in the onComplete()
* @param imageView
* @param url
* @param onComplete
*/
public void loadImage(ImageView imageView, String url, OnLoadingCompleteListener onComplete){
try {
URL url2=new URL(url);
if(imageView!=null){
for(int i=0;i<loadingList.size();i++){
UrlImageLoadingTask tmptask=loadingList.get(i);
if(tmptask.updateView!=null && tmptask.updateView.equals(imageView)){
tmptask.cancel(true);
break;
}
}
}
UrlImageLoadingTask loadtask=new UrlImageLoadingTask(imageView,onComplete,url);
loadtask.execute(url2);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
/**
* Loads a image from url and calls onComplete() when finished
* @param url
* @param onComplete
*/
public void loadImage(String url, OnLoadingCompleteListener onComplete){
loadImage(null,url,onComplete);
}
/**
* Loads a image from url and sets the loaded image to ImageView
* @param imageView
* @param url
*/
public void loadImage(ImageView imageView, String url){
loadImage(imageView,url,null);
}
/**
* Cancel loading of a ImageView
*/
public void cancel(ImageView imageView){
for(int i=0;i<loadingList.size();i++){
UrlImageLoadingTask tmptask=loadingList.get(i);
if(tmptask.updateView.equals(imageView)){
loadingList.remove(i);
tmptask.cancel(true);
break;
}
}
}
/**
* Cancel loading of a Url
*/
public void cancel(String url){
for(int i=0;i<loadingList.size();i++){
UrlImageLoadingTask tmptask=loadingList.get(i);
if(tmptask.url.equals(url)){
loadingList.remove(i);
tmptask.cancel(true);
break;
}
}
}
/**
* Cancel all loading tasks
*/
public void cancelAll(){
while(loadingList.size()>0){
UrlImageLoadingTask tmptask=loadingList.get(0);
loadingList.remove(tmptask);
tmptask.cancel(true);
}
}
private class UrlImageLoadingTask extends AsyncTask<URL, Void, Bitmap> {
public ImageView updateView=null;
public String url;
private boolean isCancelled = false;
private InputStream urlInputStream;
private OnLoadingCompleteListener onComplete=null;
private UrlImageLoadingTask(ImageView updateView, OnLoadingCompleteListener onComplete, String url) {
this.updateView=updateView;
this.onComplete=onComplete;
this.url=url;
}
@Override
protected Bitmap doInBackground(URL... params) {
try {
URLConnection con = params[0].openConnection();
// can use some more params, i.e. caching directory etc
con.setUseCaches(true);
this.urlInputStream = con.getInputStream();
return BitmapFactory.decodeStream(urlInputStream);
} catch (IOException e) {
Log.w(UrlImageView.class.getName(), "failed to load image from " + params[0], e);
return null;
} finally {
if (this.urlInputStream != null) {
try {
this.urlInputStream.close();
} catch (IOException e) {
; // swallow
} finally {
this.urlInputStream = null;
}
}
}
}
@Override
protected void onPostExecute(Bitmap result) {
if (!this.isCancelled) {
// hope that call is thread-safe
if(onComplete==null){
if(updateView!=null)
this.updateView.setImageBitmap(result);
}else{
onComplete.onComplete(updateView, result);
}
}
loadingList.remove(this);
}
/*
* just remember that we were cancelled, no synchronization necessary
*/
@Override
protected void onCancelled() {
this.isCancelled = true;
try {
if (this.urlInputStream != null) {
try {
this.urlInputStream.close();
} catch (IOException e) {
;// swallow
} finally {
this.urlInputStream = null;
}
}
} finally {
super.onCancelled();
if(onComplete!=null)
onComplete.onCancel(updateView);
loadingList.remove(this);
}
}
}
}
Ответ 7
Просто создайте новый класс " DownloadImageTask", как и следующий, и поместите его в ту же папку, где у вас есть Активность.
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.widget.ImageView;
import android.os.AsyncTask;
import java.io.*;
public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap myImage = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
myImage = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return myImage;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
После этого добавьте строку, чтобы отобразить этот класс в Деятельности.
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.util.Log;
import android.widget.ImageView;
public class HomeScreen extends ActionBarActivity {
private final String TAG = "test1";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
setContentView(R.layout.activity_home_screen);
InitHomeScreen();
}
protected void InitHomeScreen()
{
String imageUrl = "http://s20.postimg.org/4t9w2pdct/logo_android_png.png";
Log.d(TAG, "Get an Image");
// Get an Image
try{
AsyncTask<String, Void, Bitmap> execute = new DownloadImageTask((ImageView) findViewById(R.id.imageView))
.execute(imageUrl);
// R.id.imageView -> Here imageView is id of your ImageView
}
catch(Exception ex)
{
}
}
// Other code...
Не забудьте разрешить доступ к ИНТЕРНЕТу в ваше приложение для Android.
Проверьте файл манифеста.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.dmitry.myapplication1" >
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".HomeScreen"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>