我在网上找到的一个讲解异步加载图片的例子,照着他的代码我改成这样,可是总是得不到图片,总提示bitmap = null,报空指针错误。是不是和里面的回调接口有关?这个回调接口我也不明白,指点下?逻辑我这个是没问题的,就是不知道怎么就是得不到bitmap资源。上代码。大家看看。帮个忙。
这个是传入url然后判断是否缓存里面有,没有的话从网络下载并加入缓存:代码如下:import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;public class TileCheck {
public Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>();

private ExecutorService executorService = Executors.newFixedThreadPool(12); // 固定12个线程来执行任务
private final Handler handler = new Handler();
public Bitmap checkLoadBitmap(final String Url,final ImageCallback callback) {
// 如果缓存过就从缓存中取出数据
if (imageCache.containsKey(Url)) {
SoftReference<Bitmap> softReference = imageCache.get(Url);
if (softReference.get() != null) {
return softReference.get();
}
}
// 缓存中没有图像,则从网络上取出数据,并将取出的数据缓存到内存中
executorService.submit(new Runnable() {
public void run() {
try {

final Bitmap bitmap = loadImageFromUrl(Url); 

// tileLoader.setBitmap(drawingTile);
// Bitmap bitmap = drawingTile.getBitmap();

imageCache.put(Url, new SoftReference<Bitmap>(bitmap)); handler.post( new Runnable() {
public void run() {
callback.imageLoaded(bitmap);
}
});
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
return null;
}
// 从网络上取数据方法
private Bitmap loadImageFromUrl(String strURL) throws IOException {
URL url = new URL(strURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setConnectTimeout(1000);
conn.setRequestMethod("GET");
conn.connect();
for (int i = 0; i < 1; i++) {
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream is = conn.getInputStream();
Bitmap bm = BitmapFactory.decodeStream(is, null, null);
if (is != null) {
is.close();
is = null;
}
if (conn != null) {
conn.disconnect();
conn = null;
}
return bm;
}
}
return null;
}
// protected Bitmap loadImageFromUrl(String Url) {
// try {
//
//// TileLoader tileLoader = new TileLoader(TileLayer);
//
//
//
// return Drawable.createFromStream(new URL(Url).openStream(),
// "image.png");
//
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
// }

// 对外界开放的回调接口
public interface ImageCallback {
// 注意 此方法是用来设置目标对象的图像资源
public void imageLoaded(Bitmap bitmap);
}

}
我这边是调用上面的函数获取bitmap并画出来:String urllll = drawingTile.getTileSrc();
TileCheck tilecheck = new TileCheck();

ImageCallback callback = null;

Bitmap bitmap = tilecheck.checkLoadBitmap(urllll, callback);


// tileLoader.setBitmap(drawingTile);
// Bitmap bitmap = drawingTile.getBitmap();
Point drawPoint = drawingTile.getScreenPos();
canvas.drawBitmap(bitmap, drawPoint.x, drawPoint.y, null);大牛们,是哪里有问题。?

解决方案 »

  1.   

    Bitmap bitmap = tilecheck.checkLoadBitmap(urllll, callback);
    这句话只有当本地存在图片时bitmap才不为空你要实现ImageCallback接口,然后在ImageCallback接口的imageLoaded()方法中才能拿到下载下来的图片
      

  2.   


    恩 总是null的原因是你说的这个 可是这个imageloaded()借口就是不知道怎么实现啊,又修改了下代码,下面的代码是在主线程了调用Tilecheck里的方法,实现了imagecallback借口里的imageloaded可是还是不对啊   public void onDraw(Canvas canvas) {
    canvas.drawColor(Color.WHITE);
    for(int index = 0 ; index <= 11 ; index ++){
              ………
                              ………
    String urllll = needdrawbitmap.urlSrc();

    Bitmap bitmap = loadBitmap(urllll,index);


    Point drawPoint = needdrawbitmap.getScreenPos();
    canvas.drawBitmap(bitmap, drawPoint.x, drawPoint.y, null);
    }
    }
            private TileCheck tilecheck = new TileCheck();
    // 引入线程池,并引入内存缓存功能,并对外部调用封装了接口,简化调用过程
    private Bitmap loadBitmap(final String url,int id) {
    // 如果缓存过就会从缓存中取出图像,ImageCallback接口中方法也不会被执行
    Bitmap cacheImage = tilecheck.checkLoadBitmap(url, new TileCheck.ImageCallback() {
    // 请参见实现:如果第一次加载url时下面方法会执行
    public Bitmap imageLoaded(Bitmap bitmap) {
    return bitmap;
    }

    });
    // if (cacheImage != null) {
    // return cacheImage;
    // }
    return cacheImage;
    }我知道主要是红色区域的代码问题,可是就不知道怎么改啊,大牛,怎么在红色区域哪里返回能给我得到和返回bitmap呢?
      

  3.   

    晕  那个红色没显示出来主要就是这个代码public Bitmap imageLoaded(Bitmap bitmap) {
                            return bitmap;
                 }
      

  4.   

    方法改为返回void,然后在回调方法上做操作if (imageCache.containsKey(Url)) {
                SoftReference<Bitmap> softReference = imageCache.get(Url);
                if (softReference.get() != null) {
                    callback.imageLoaded(softReference.get());
                }else{
                    executorService.submit(new Runnable() {
                        public void run() {
                          try {
                        
                        final Bitmap bitmap = loadImageFromUrl(Url); 
                        
    //                    tileLoader.setBitmap(drawingTile);
    //                    Bitmap bitmap = drawingTile.getBitmap();
                        
                        imageCache.put(Url, new SoftReference<Bitmap>(bitmap));                    handler.post( new Runnable() {
                            public void run() {
                                callback.imageLoaded(bitmap);
                            }
                        });
                    }
                    catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            });            }        }
      

  5.   

    大哥,我学安卓刚1个月,瓦片地图现在为止瓦片都是公司给的切好了的,框架页是公司给的,要我实现给经纬度和zoom然后显示出地图,能拖动什么的,我在这方面还是小白啊。
      

  6.   

    异步加载你用AsyncTask吧,你写的它都帮你写好了,内部实现原理和你差不多。线程池是静态的。所以可以多次使用无压力
      

  7.   


    现在在用asynctask   是比我这个封装的好,不过貌似不能多次使用啊~差不多解决了现在,谢谢了啊~
      

  8.   

    多次使用指的是可以new多个而不用担心线程池过多
      

  9.   

    缓存需要得到下载图片的地址,根据地址得到图片名字,之后到本地去查询,有的话就不下载了。。也就是说下载之前判断一下sdcard有木有这张图片