安卓:帮助适应的ListView适配器一个ImageLoader的类(LazyList)适配器、ListView、LazyList、ImageLoader

2023-09-13 00:17:25 作者:心如死海花不再开@

我有一个实现了ImageThreadLoader类的定制的ListView适配器。不幸的是,类不启用缓存从网络选项,下载图像并将其保存为高速缓存。

然后,我发现这个 LazyList 或here真的很有用,它的行为完全一样喜欢我ImageThreadLoader类,但它能够将图像保存为缓存。所以,我要实现它的ImageLoader的类以我目前的自定义的ListView适配器。

不幸的是我的codeS和Lazylist的的结构是完全不同的,由此产生的对我尝试一些冲突。 例如,LazyList使用字符串数组用于图像的URL,在另一方面,我使用JSON作为图像URL的来源。

这就是为什么我需要帮助,在这里,以适应我的ListView适配器与本ImageLoader的类。

下面是codeS:

ImageLoader的类,我想实现我的自定义的ListView适配器:

 公共类ImageLoader的{

    //最简单的内存缓存实现。这应该被替换为类似SoftReference或BitmapOptions.inPurgeable(自1.6)
    私人的HashMap<字符串,位图>缓存=新的HashMap<字符串,位图>();

    私人文件cacheDir;

    公共ImageLoader的(上下文的背景下){
        //使背景THEAD低优先级。这样也不会影响用户界面性能
        photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);

        //查找目录保存缓存图像
        如果(android.os.Environment.getExternalStorageState()。等于(android.os.Environment.MEDIA_MOUNTED))
            cacheDir =新的文件(android.os.Environment.getExternalStorageDirectory()的Andr​​oid /数据/ LazyList);
        其他
            cacheDir = context.getCacheDir();
        如果(!cacheDir.exists())
            cacheDir.mkdirs();
    }

    最终诠释stub_id = R.drawable.stub;
    公共无效DisplayImage(字符串URL,活动活动,ImageView的ImageView的)
    {
        如果(cache.containsKey(URL))
            imageView.setImageBitmap(cache.get(URL));
        其他
        {
            queuePhoto(URL,活动,ImageView的);
            imageView.setImageResource(stub_id);
        }
    }

    私人无效queuePhoto(字符串URL,活动活动,ImageView的ImageView的)
    {
        //这个ImageView的可之前用于其它图像。所以有可能在队列一些旧的任务。我们需要将它们丢弃。
        photosQueue.Clean(ImageView的);
        PhotoToLoad P =新PhotoToLoad(URL,ImageView的);
        同步(photosQueue.photosToLoad){
            photosQueue.photosToLoad.push(对);
            photosQueue.photosToLoad.notifyAll();
        }

        //启动线程,如果它尚未开始
        如果(photoLoaderThread.getState()== Thread.State.NEW)
            photoLoaderThread.start();
    }

    私人位图getBitmap(字符串URL)
    {
        //我通过散列code识别图像。没有一个完美的解决方案,很好的演示。
        字符串文件名=将String.valueOf(url.hash code());
        文件F =新的文件(cacheDir,文件名);

        //从SD高速缓存
        位图B =去codeFILE(F);
        如果(B!= NULL)
            返回b;

        //从网页
        尝试 {
            点阵位图= NULL;
            InputStream的是=新的URL(网址).openStream();
            的OutputStream OS =新的FileOutputStream(F);
            Utils.CopyStream(是,OS);
            os.close();
            位=去codeFILE(F);
            返回的位图;
        }赶上(例外前){
           ex.printStackTrace();
           返回null;
        }
    }

    //德$ C $连拍影像和扩展它来减少内存消耗
    私人位图德codeFILE(文件f){
        尝试 {
            //德code图像尺寸
            BitmapFactory.Options O =新BitmapFactory.Options();
            o.inJustDe codeBounds = TRUE;
            BitmapFactory.de codeStream(新的FileInputStream(f)项,空,O);

            //找到正确的比例值。它应该是2的幂。
            最终诠释REQUIRED_SIZE = 70;
            INT width_tmp = o.outWidth,height_tmp = o.outHeight;
            int标= 1;
            而(真){
                如果(width_tmp / 2'; REQUIRED_SIZE || height_tmp / 2'; REQUIRED_SIZE)
                    打破;
                width_tmp / = 2;
                height_tmp / = 2;
                规模* = 2;
            }

            //德code与inSampleSize
            BitmapFactory.Options O2 =新BitmapFactory.Options();
            o2.inSampleSize =规模;
            返回BitmapFactory.de codeStream(新的FileInputStream(f)项,空,O2);
        }赶上(FileNotFoundException异常E){}
        返回null;
    }

    //任务队列
    私有类PhotoToLoad
    {
        公共字符串URL;
        公众的ImageView ImageView的;
        公共PhotoToLoad(字符串U,ImageView的我){
            URL = U;
            ImageView的=我;
        }
    }

    PhotosQueue photosQueue =新PhotosQueue();

    公共无效stopThread()
    {
        photoLoaderThread.interrupt();
    }

    //照片商店列表下载
    类PhotosQueue
    {
        私人堆叠式和LT; PhotoToLoad> photosToLoad =新的堆栈< PhotoToLoad>();

        //删除这个ImageView的所有实例
        公共无效清洁(ImageView的图像)
        {
            对于(INT J = 0; J< photosToLoad.size()){
                如果(photosToLoad.get(J).imageView ==图片)
                    photosToLoad.remove(J);
                其他
                    + D];
            }
        }
    }

    类PhotosLoader继承Thread {
        公共无效的run(){
            尝试 {
                而(真)
                {
                    //线程等待直到有在队列加载任何图像
                    如果(photosQueue.photosToLoad.size()== 0)
                        同步(photosQueue.photosToLoad){
                            photosQueue.photosToLoad.wait();
                        }
                    如果(photosQueue.photosToLoad.size()!= 0)
                    {
                        PhotoToLoad photoToLoad;
                        同步(photosQueue.photosToLoad){
                            photoToLoad = photosQueue.photosToLoad.pop();
                        }
                        BMP位= getBitmap(photoToLoad.url);
                        cache.put(photoToLoad.url,BMP);
                        对象标记= photoToLoad.imageView.getTag();
                        如果(标记= NULL和放大器;!及((字符串)标签).equals(photoToLoad.url)){
                            BitmapDisplayer BD =新BitmapDisplayer(BMP,photoToLoad.imageView);
                            活动一=(活动)photoToLoad.imageView.getContext();
                            a.runOnUiThread(BD);
                        }
                    }
                    如果(Thread.interrupted())
                        打破;
                }
            }赶上(InterruptedException异常E){
                //允许线程退出
            }
        }
    }

    PhotosLoader photoLoaderThread =新PhotosLoader();

    //用于在UI线程中显示位图
    类BitmapDisplayer实现Runnable
    {
        点阵位图;
        ImageView的ImageView的;
        公共BitmapDisplayer(位图B,ImageView的我){位= B,ImageView的= I;}
        公共无效的run()
        {
            如果(位图!= NULL)
                imageView.setImageBitmap(位);
            其他
                imageView.setImageResource(stub_id);
        }
    }

    公共无效clearCache(){
        //清除内存高速缓存
        cache.clear();

        //明确的SD高速缓存
        文件[]文件= cacheDir.listFiles();
        对于(F文件:文件)
            f.delete();
    }

}
 
inkhunter应该怎么登录 inkhunter有哪些特色

从LazyList项目自定义列表视图适配器:

 公共类LazyAdapter扩展了BaseAdapter {

    私人活动的活动;
    私有String []的数据;
    私有静态LayoutInflater吹气= NULL;
    公共ImageLoader的ImageLoader的;

    公共LazyAdapter(活动一,的String [] D){
        活性= A;
        数据= D;
        充气=(LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        ImageLoader的=新ImageLoader的(activity.getApplicationContext());
    }

    公众诠释getCount将(){
        返回data.length;
    }

    公共对象的getItem(INT位置){
        返回的位置;
    }

    众长getItemId(INT位置){
        返回的位置;
    }

    公共静态类ViewHolder {
        公共TextView的文字;
        公众ImageView的形象;
    }

    公共查看getView(INT位置,查看convertView,ViewGroup中父){
        查看VI = convertView;
        ViewHolder持有人;
        如果(convertView == NULL){
            VI = inflater.inflate(R.layout.item,NULL);
            持有人=新ViewHolder();
            holder.text =(TextView中)vi.findViewById(R.id.text);;
            holder.image =(ImageView的)vi.findViewById(R.id.image);
            vi.setTag(保持器);
        }
        其他
            支架=(ViewHolder)vi.getTag();

        holder.text.setText(项目+位置);
        holder.image.setTag(数据[位置]);
        imageLoader.DisplayImage(数据[位置],活动,holder.image);
        返回六;
    }
}
 

,这里是我的自定义的ListView适配器: * ProjectAdapter类的*

 公共类ProjectAdapter扩展ArrayAdapter<项目> {

    INT资源;
    字符串响应;
    上下文语境;
    私人最终静态字符串变量=MediaItemAdapter;

    私人ImageThreadLoader ImageLoader的=新ImageThreadLoader();

    //初始化适配器
    公共ProjectAdapter(上下文的背景下,INT资源,列表和LT;项目>项目){
        超(背景下,资源,项目);
        this.resource =资源;
    }

    @覆盖
    公共查看getView(INT位置,查看convertView,父母的ViewGroup)
    {
        TextView的textTitle;
        最后ImageView的形象;

        项目亲=的getItem(位置);

        的LinearLayout projectView;
      //充气视图
        如果(convertView == NULL)
        {
            projectView =新的LinearLayout(的getContext());
            字符串充气= Context.LAYOUT_INFLATER_SERVICE;
            LayoutInflater六;
            VI =(LayoutInflater)的getContext()getSystemService(充气)。
            vi.inflate(资源,projectView,真正的);
        }
        其他
        {
            projectView =(LinearLayout中)convertView;
        }

        尝试 {
          textTitle =(TextView中)projectView.findViewById(R.id.txt_title);
          图像=(ImageView的)projectView.findViewById(R.id.image);
        }赶上(ClassCastException异常E){
          Log.e(TAG,你的布局必须提供图像,并与ID的图标和文字文本视图,E);
          扔ê;
        }


        位图cachedImage = NULL;
        尝试 {
          cachedImage = imageLoader.loadImage(pro.smallImageUrl,新ImageLoadedListener(){
          公共无效imageLoaded(位图imageBitmap){
          image.setImageBitmap(imageBitmap);
          notifyDataSetChanged(); }
          });
        }赶上(MalformedURLException异常E){
          Log.e(TAG,坏遥感图像的URL:+ pro.smallImageUrl,E);
        }

        textTitle.setText(pro.project_title);

        如果(cachedImage!= NULL){
          image.setImageBitmap(cachedImage);
        }

        返回projectView;
    }

}
 

非常感谢你!

修改

更新: ProjectList活动

 公共类ProjectsList延伸活动{
        / **第一次创建活动时调用。 * /
        // ListView中,将举行我们的项目参考回到main.xml中
        ListView控件lstTest;
        //数组适配器,将举行我们的ArrayList和显示在ListView中的项目
        ProjectAdapter arrayAdapter;
        ProgressDialog对话框;
        //名单将承载我们的项目,让我们修改该阵列适配器
        ArrayList的<项目> prjcts = NULL;
        @覆盖
        公共无效的onCreate(包savedInstanceState){
            super.onCreate(savedInstanceState);
            的setContentView(R.layout.projects_list);
            //初始化的ListView
            lstTest =(ListView控件)findViewById(R.id.lstText);

             //初始化我们的ArrayList
            prjcts =新的ArrayList<项目>();
            //初始化我们的阵列适配器注意它引用listitems.xml布局
            arrayAdapter =新ProjectAdapter(ProjectsList.this,R.layout.listitems,prjcts,ProjectsList.this);

            //设置上述适配器作为首选我们的列表中选择适配器
        lstTest.setAdapter(arrayAdapter);

        如果(isOnline())
        {
        //实例化Web服务类与Web服务的URL,他不是说你必须通过
        // WebService的web服务=新的WebService(http://notalentrocks.com/myplaceapp/projects.json);
        WebService的web服务=新的WebService(http://liebenwald.spendino.net/admanager/dev/android/projects.json);

        //如果需要传递的参数,如果没有则通过一个虚构的如下
        地图<字符串,字符串> PARAMS =新的HashMap<字符串,字符串>();
        params.put(变种,);

        //从服务器获取JSON响应是其中的方法名称通常会去,如果需要的例子
        // webService.webGet(getMoreAllerts,则params);
        字符串响应= webService.webGet(,则params);

        尝试
        {
             对话框= ProgressDialog.show(ProjectsList.this,,撷取项目......,真正的);
             dialog.setCancelable(真正的);
             dialog.setCanceledOnTouchOutside(真正的);
             dialog.setOnCancelListener(新OnCancelListener(){
                公共无效OnCancel的(DialogInterface对话){

                }
             });
            //解析响应到我们的对象
            键入collectionType =新TypeToken< ArrayList的<项目>>(){}的getType()。

            // JSON期待一个列表中,这样不能从lstart使用我们的ArrayList
            名单<项目> 。LST =新GSON()fromJson(响应,collectionType);


            //现在我们有一个列表允许其添加到将举行我们的项目的ArrayList中。
            为(项目L:LST)
            {
                prjcts.add(升);
                ConstantData.projectsList.add(升);
            }

            //由于我们已经修改了ArrayList的,我们现在需要通知适配器
            //其数据已经更改,因此,它更新UI
            arrayAdapter.notifyDataSetChanged();
            dialog.dismiss();
        }
        赶上(例外五)
        {
            Log.d(错误,e.getMessage());
        }
        }
        lstTest.setOnItemClickListener(新OnItemClickListener(){
            公共无效onItemClick(适配器视图<>母公司视图中查看,INT位置,长的id){
                意图护理=新的意图(ProjectsList.this,ProjectDetail.class);
                care.putExtra(spendino.de.ProjectDetail.position,位置);
                startActivity(护理);
            }
        });

    }

    保护的布尔isOnline(){
        ConnectivityManager厘米=(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
        的NetworkInfo的NetInfo = cm.getActiveNetworkInfo();
        如果(NetInfo的= NULL和放大器;!&安培; netInfo.isConnected()){
            返回true;
        } 其他 {
             AlertDialog.Builder alertbox =新AlertDialog.Builder(本);
             alertbox.setTitle(spendino Helfomat);
             alertbox.setMessage(请检查您的网络连接);
             alertbox.setPositiveButton(OK,新DialogInterface.OnClickListener(){
                 公共无效的onClick(DialogInterface对话框,INT ID){
                      //Main.this.finish();
                 }
             });
             alertbox.show();
            返回false;
        }
    }



}
 

更新时间: 这是我的堆栈跟踪:

 十一月5号至12号:36:52.670:ERROR / AndroidRuntime(299):由:显示java.lang.NullPointerException
十一月5号至12日:36:52.670:ERROR / AndroidRuntime(299):在android.content.ContextWrapper.getCacheDir(ContextWrapper.java:183)
十一月5号至12日:38:29.386:ERROR / AndroidRuntime(324):在spendino.de.ImageLoader< INIT>(ImageLoader.java:41)
十一月5号至12日:36:52.670:ERROR / AndroidRuntime(299):在spendino.de.Main< INIT>(Main.java:56)
 

ImageLoader的41: cacheDir = context.getCacheDir(); 主要56是:私人 ImageLoaderCache ImageLoader的=新ImageLoaderCache(Main.this);

Main.java

公共类主要扩展活动{     / **第一次创建活动时调用。 * /

 的ArrayList<项目> prjcts = NULL;
私人最终静态字符串变量=MediaItemAdapter;
ImageLoader的ImageLoader的;
私人活动的活动;
ImageView的此搜索;
ImageView的IMAGE2;
ImageView的的Image3;

@覆盖
公共无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.main);

    如果(isOnline())
    {


    prjcts =新的ArrayList<项目>();
    WebService的web服务=新的WebService(http://liebenwald.spendino.net/admanager/dev/android/projects.json);
    地图<字符串,字符串> PARAMS =新的HashMap<字符串,字符串>();
    params.put(变种,);
    字符串响应= webService.webGet(,则params);

    ImageLoader的=新ImageLoader的(Main.this);
    尝试
    {
        键入collectionType =新TypeToken< ArrayList的<项目>>(){}的getType()。
        名单<项目> 。LST =新GSON()fromJson(响应,collectionType);
        为(项目L:LST)
        {
            prjcts.add(升);
            ConstantData.projectsList.add(升);
        }
    }
    赶上(例外五)
    {
        Log.d(错误,e.getMessage());
    }

    尝试 {
        此搜索=(ImageView的)findViewById(R.id.top1);
        IMAGE2 =(ImageView的)findViewById(R.id.top2);
        的Image3 =(ImageView的)findViewById(R.id.top3);
      }赶上(ClassCastException异常E){
        Log.e(TAG,你的布局必须提供图像,并与ID的图标和文字文本视图,E);
        扔ê;
      }

      //随机图像条目的索引

      INT最大= prjcts.size();
      名单<整数GT;指数=新的ArrayList<整数GT;(最大);
      对于(INT C = 1; C<最大++ C)
      {
          indices.add(C);
      }

      随机R =新的随机();
      INT arrIndex = r.nextInt(indices.size());
      INT randomIndex1 = indices.get(arrIndex);
      indices.remove(arrIndex);

      INT arrIndex2 = r.nextInt(indices.size());
      INT randomIndex2 = indices.get(arrIndex2);
      indices.remove(arrIndex2);

      INT arrIndex3 = r.nextInt(indices.size());
      INT randomIndex3 = indices.get(arrIndex3);
      indices.remove(arrIndex3);


      imageLazy(此搜索,prjcts.get(randomIndex1));
      imageLazy(图像2,prjcts.get(randomIndex2));
      imageLazy(的Image3,prjcts.get(randomIndex3));

      image1.setOnClickListener(新RandomClickListener(randomIndex1));
      image2.setOnClickListener(新RandomClickListener(randomIndex2));
      image3.setOnClickListener(新RandomClickListener(randomIndex3));
    }

    最终按钮项目=(按钮)findViewById(R.id.btn_projectslist);
    最终按钮的相关信息=(按钮)findViewById(R.id.btn_infos);
    最终按钮触点=(按钮)findViewById(R.id.btn_contact);
    project.setOnClickListener(project_listener);
    infos.setOnClickListener(infos_listener);
    contact.setOnClickListener(contact_listener);
}

/ *
 * isOnline  - 检查是否有NetworkConnection
 * @返回布尔
 * /
保护的布尔isOnline(){
    ConnectivityManager厘米=(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
    的NetworkInfo的NetInfo = cm.getActiveNetworkInfo();
    如果(NetInfo的= NULL和放大器;!&安培; netInfo.isConnected()){
        返回true;
    } 其他 {
         AlertDialog.Builder alertbox =新AlertDialog.Builder(本);
         alertbox.setTitle(spendino Helfomat);
         alertbox.setMessage(BITTEüberprüfenSIE IHRE Internetverbindung);
         alertbox.setPositiveButton(OK,新DialogInterface.OnClickListener(){
             公共无效的onClick(DialogInterface对话框,INT ID){
                  Main.this.finish();
             }
         });
         alertbox.show();
        返回false;
    }
}

公共静态类ViewHolder {
    公众ImageView的形象;
}

公共无效imageLazy(最终ImageView的形象,项目PRO)
{
    imageLoadery.displayImage(pro.smallImageUrl,活动,图像);
}

公共无效setImage(位图cachedImage,最终ImageView的形象,项目PRO)
{
    尝试 {
        cachedImage = imageLoader.loadImage(pro.smallImageUrl,新ImageLoadedListener()
        {
            公共无效imageLoaded(位图imageBitmap)
            {
                image.setImageBitmap(imageBitmap);
            }
        });
    }赶上(MalformedURLException异常E){
        Log.e(TAG,坏遥感图像的URL:+ pro.smallImageUrl,E);
    }
    如果(cachedImage!= NULL){
        image.setImageBitmap(cachedImage);
      }
}

公共类RandomClickListener实现View.OnClickListener
{
    私人最终诠释randomIndex;

    公共RandomClickListener(最终诠释randomIndex)
    {
        this.randomIndex = randomIndex;
    }
    @覆盖
    公共无效的onClick(视图v)
    {
        意图顶部=新的意图(Main.this,ProjectDetail.class);
        top.putExtra(spendino.de.ProjectDetail.position,randomIndex);
        startActivity(顶部);
    }
}
 

堆栈跟踪:

  05-12 13:48:12.606:ERROR / AndroidRuntime(433):在spendino.de.ImageLoaderCache $ PhotosLoader.run(ImageLoaderCache.java:244)
 

解决方案

看来你没有使用任何观点持有者在您的适配器

我曾更改您的classes.Hope它会为你的作品有任何困难

在 ImageThreadLoader 类

 进口的java.io.File;
进口java.io.FileInputStream中;
进口java.io.FileNotFoundException;
进口java.io.FileOutputStream中;
进口的java.io.InputStream;
进口java.io.OutputStream中;
进口的java.net.URL;
进口的java.util.HashMap;
进口java.util.Stack中;

进口android.app.Activity;
进口android.content.Context;
进口android.graphics.Bitmap;
进口android.graphics.BitmapFactory;
进口android.widget.ImageView;

公共类ImageThreadLoader {

    //最简单的内存缓存实现。这应该被替换为类似SoftReference或BitmapOptions.inPurgeable(自1.6)
    / **缓存。 * /
    私人的HashMap<字符串,位图>缓存=新的HashMap<字符串,位图>();

    / **缓存目录。 * /
    私人文件cacheDir;

    / **
     *实例化一个新的图像加载器。
     *
     *参数上下文语境
     * /
    公共ImageThreadLoader(上下文的背景下){
        //使背景THEAD低优先级。这样也不会影响用户界面性能
        photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);

        //查找目录保存缓存图像
        如果(android.os.Environment.getExternalStorageState()。等于(android.os.Environment.MEDIA_MOUNTED))
            cacheDir =新的文件(android.os.Environment.getExternalStorageDirectory(),cache_dir_img);
        其他
            cacheDir = context.getCacheDir();
        如果(!cacheDir.exists())
            cacheDir.mkdirs();
    }
    //这是用于一个存根当用户无法看到的实际图像..
    //这个图像可以看出
    最终诠释stub_id = R.drawable.sample_image;


    / **
     *显示图像。
     *
     *参数的URL网址
     *参数活动活动
     *参数的ImageView图像视图
     * /
    公共无效displayImage(字符串URL,活动活动,ImageView的ImageView的)
    {
        如果(cache.containsKey(URL))
            imageView.setImageBitmap(cache.get(URL));
        其他
        {
            queuePhoto(URL,活动,ImageView的);
            imageView.setImageResource(stub_id);
        }
    }

    / **
     *排队的照片。
     *
     *参数的URL网址
     *参数活动活动
     *参数的ImageView图像视图
     * /
    私人无效queuePhoto(字符串URL,活动活动,ImageView的ImageView的)
    {
        //这个ImageView的可之前用于其它图像。所以有可能在队列一些旧的任务。我们需要将它们丢弃。
        photosQueue.Clean(ImageView的);
        PhotoToLoad P =新PhotoToLoad(URL,ImageView的);
        同步(photosQueue.photosToLoad){
            photosQueue.photosToLoad.push(对);
            photosQueue.photosToLoad.notifyAll();
        }

        //启动线程,如果它尚未开始
        如果(photoLoaderThread.getState()== Thread.State.NEW)
            photoLoaderThread.start();
    }

    / **
     *获取位图。
     *
     *参数的URL网址
     返回:位图
     * /
    私人位图getBitmap(字符串URL)
    {
        //我通过散列code识别图像。没有一个完美的解决方案,很好的演示。
        字符串文件名=将String.valueOf(url.hash code());
        文件F =新的文件(cacheDir,文件名);

        //从SD高速缓存
        位图B =去codeFILE(F);
        如果(B!= NULL)
            返回b;

        //从网页
        尝试 {
            点阵位图= NULL;
            InputStream的是=新的URL(网址).openStream();
            的OutputStream OS =新的FileOutputStream(F);
            copyStream(是,OS);
            os.close();
            位=去codeFILE(F);
            返回的位图;
        }赶上(例外前){
           ex.printStackTrace();
           返回null;
        }
    }

    //德$ C $连拍影像和扩展它来减少内存消耗
    / **
     *德code文件。
     *
     *参数˚F的F
     返回:位图
     * /
    私人位图德codeFILE(文件f){
        尝试 {
            //德code图像尺寸
            BitmapFactory.Options O =新BitmapFactory.Options();
            o.inJustDe codeBounds = TRUE;
            BitmapFactory.de codeStream(新的FileInputStream(f)项,空,O);

            //找到正确的比例值。它应该是2的幂。
            最终诠释REQUIRED_SIZE = 70;
            INT width_tmp = o.outWidth,height_tmp = o.outHeight;
            int标= 1;
            而(真){
                如果(width_tmp / 2'; REQUIRED_SIZE || height_tmp / 2'; REQUIRED_SIZE)
                    打破;
                width_tmp / = 2;
                height_tmp / = 2;
                规模++;
            }

            //德code与inSampleSize
            BitmapFactory.Options O2 =新BitmapFactory.Options();
            o2.inSampleSize =规模;
            返回BitmapFactory.de codeStream(新的FileInputStream(f)项,空,O2);
        }赶上(FileNotFoundException异常E){}
        返回null;
    }

    //任务队列
    / **
     *本类PhotoToLoad。
     * /
    私有类PhotoToLoad
    {

        / **网址。 * /
        公共字符串URL;

        / **的图像视图。 * /
        公众的ImageView ImageView的;

        / **
         *实例化一个新的照片加载。
         *
         *参数ü在U
         *参数我的我
         * /
        公共PhotoToLoad(字符串U,ImageView的我){
            URL = U;
            ImageView的=我;
        }
    }

    / **的照片排队。 * /
    PhotosQueue photosQueue =新PhotosQueue();

    / **
     *停止线程。
     * /
    公共无效stopThread()
    {
        photoLoaderThread.interrupt();
    }

    //照片商店列表下载
    / **
     *本类PhotosQueue。
     * /
    类PhotosQueue
    {

        / **的照片加载。 * /
        私人堆叠式和LT; PhotoToLoad> photosToLoad =新的堆栈< PhotoToLoad>();

        //删除这个ImageView的所有实例
        / **
         * 清洁。
         *
         * @参数图像的图像
         * /
        公共无效清洁(ImageView的图像)
        {
            对于(INT J = 0; J< photosToLoad.size()){
                如果(photosToLoad.get(J).imageView ==图片)
                    photosToLoad.remove(J);
                其他
                    + D];
            }
        }
    }

    / **
     *本类PhotosLoader。
     * /
    类PhotosLoader继承Thread {

        / *(非Javadoc中)
         * @see java.lang.Thread中的#的run()
         * /
        公共无效的run(){
            尝试 {
                而(真)
                {
                    //线程等待直到有在队列加载任何图像
                    如果(photosQueue.photosToLoad.size()== 0)
                        同步(photosQueue.photosToLoad){
                            photosQueue.photosToLoad.wait();
                        }
                    如果(photosQueue.photosToLoad.size()!= 0)
                    {
                        PhotoToLoad photoToLoad;
                        同步(photosQueue.photosToLoad){
                            photoToLoad = photosQueue.photosToLoad.pop();
                        }
                        BMP位= getBitmap(photoToLoad.url);
                        cache.put(photoToLoad.url,BMP);
                        如果(((字符串)photoToLoad.imageView.getTag())。等于(photoToLoad.url)){
                            BitmapDisplayer BD =新BitmapDisplayer(BMP,photoToLoad.imageView);
                            活动一=(活动)photoToLoad.imageView.getContext();
                            a.runOnUiThread(BD);
                        }
                    }
                    如果(Thread.interrupted())
                        打破;
                }
            }赶上(InterruptedException异常E){
                //允许线程退出
            }
        }
    }

    / ** Photo Loader的线程。 * /
    PhotosLoader photoLoaderThread =新PhotosLoader();

    //用于在UI线程中显示位图
    / **
     *本类BitmapDisplayer。
     * /
    类BitmapDisplayer实现Runnable
    {

        / **位图。 * /
        点阵位图;

        / **的图像视图。 * /
        ImageView的ImageView的;

        / **
         *实例化一个新的位图显示器。
         *
         *参数B中的b
         *参数我的我
         * /
        公共BitmapDisplayer(位图B,ImageView的我){位= B,ImageView的= I;}

        / *(非Javadoc中)
         * @see了java.lang.Runnable#的run()
         * /
        公共无效的run()
        {
            如果(位图!= NULL)
                imageView.setImageBitmap(位);
            其他
              imageView.setImageResource(stub_id);
        }
    }

    / **
     * 清除缓存。
     * /
    公共无效clearCache(){
        //清除内存高速缓存
        cache.clear();

        //明确的SD高速缓存
        文件[]文件= cacheDir.listFiles();
        对于(F文件:文件)
            f.delete();
    }

     公共静态无效copyStream(InputStream的是,OutputStream的操作系统){
            最终诠释的buffer_size = 1024;
            尝试
            {
                字节[]字节=新字节[BUFFER_SIZE];
                对于(;;)
                {
                  诠释计数= is.​​read(字节,0,BUFFER_SIZE);
                  如果(计数==  -  1)
                      打破;
                  os.write(字节,0,计数);
                }
            }
            赶上(例外前){}
        }


}
 

现在您的 ProjectAdapter 类

 进口的java.util.List;

进口android.app.Activity;
进口android.content.Context;
进口android.view.LayoutInflater;
进口android.view.View;
进口android.view.ViewGroup;
进口android.widget.ArrayAdapter;
进口android.widget.ImageView;
进口android.widget.TextView;

公共类ProjectAdapter扩展ArrayAdapter<项目> {

    INT资源;
    字符串响应;
    上下文语境;
    名单<项目>项目;
    私人ImageThreadLoader ImageLoader的;
    LayoutInflater mInflater;
    活动活性;

    //初始化适配器
    公共ProjectAdapter(上下文的背景下,INT资源,列表和LT;项目>的项目,
            活动活动){
        超(背景下,资源,项目);
        this.resource =资源;
        ImageLoader的=新ImageThreadLoader(上下文);
        this.items =项目;
        mInflater =(LayoutInflater)上下文
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        this.activity =活动;
    }

    @覆盖
    公共查看getView(INT位置,查看convertView,ViewGroup中父){

        ViewHolder支架=无效;

        //充气视图
        如果(convertView == NULL){

            convertView = mInflater.inflate(资源,NULL);
            持有人=新ViewHolder();
            holder.image =(ImageView的)convertView.findViewById(R.id.image);
            holder.textTitle =(TextView中)convertView
                    .findViewById(R.id.txt_title);
            convertView.setTag(保持器);

        } 其他 {
            支架=(ViewHolder)convertView.getTag();
        }

        项目项目= items.get(位置);

        holder.textTitle.setText(project.project_title);

        字符串IMAGEURL = project.smallImageUrl;
        holder.image.setTag(IMAGEURL);
        imageLoader.displayImage(IMAGEURL,活动,holder.image);
        返回convertView;

    }

    静态类ViewHolder {

        TextView的textTitle;

        ImageView的形象;
    }
 

而在最后,当你设置你的的ListView适配器获取网络数据后,使用此

  your_listview.setAdapter(your_ProjectAdapter_instance);
your_ProjectAdapter_instance .notifyDataSetChanged();
 

I have a custom ListView adapter which implements an ImageThreadLoader class. Unfortunately the class doesn't enable a cache option-download the images from the web and save them as cache.

And then I found this LazyList or here really useful, it behaves quite the same like my ImageThreadLoader class but it's able to save the images as cache. So, I want to implement its ImageLoader class to my current custom ListView adapter.

Unfortunately the structure of my codes and the Lazylist's is quite different, resulting some conflicts on my attempts. For example, the LazyList use array of strings for the image URL, in the other hand I use JSON as the source of image URL.

That's why I need a help here to adapt my ListView adapter to this ImageLoader class.

Here are the codes:

ImageLoader Class which I want implement to my custom ListView adapter:

public class ImageLoader {

    //the simplest in-memory cache implementation. This should be replaced with something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
    private HashMap<String, Bitmap> cache=new HashMap<String, Bitmap>();

    private File cacheDir;

    public ImageLoader(Context context){
        //Make the background thead low priority. This way it will not affect the UI performance
        photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);

        //Find the dir to save cached images
        if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
            cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"Android/data/LazyList");
        else
            cacheDir=context.getCacheDir();
        if(!cacheDir.exists())
            cacheDir.mkdirs();
    }

    final int stub_id=R.drawable.stub;
    public void DisplayImage(String url, Activity activity, ImageView imageView)
    {
        if(cache.containsKey(url))
            imageView.setImageBitmap(cache.get(url));
        else
        {
            queuePhoto(url, activity, imageView);
            imageView.setImageResource(stub_id);
        }    
    }

    private void queuePhoto(String url, Activity activity, ImageView imageView)
    {
        //This ImageView may be used for other images before. So there may be some old tasks in the queue. We need to discard them. 
        photosQueue.Clean(imageView);
        PhotoToLoad p=new PhotoToLoad(url, imageView);
        synchronized(photosQueue.photosToLoad){
            photosQueue.photosToLoad.push(p);
            photosQueue.photosToLoad.notifyAll();
        }

        //start thread if it's not started yet
        if(photoLoaderThread.getState()==Thread.State.NEW)
            photoLoaderThread.start();
    }

    private Bitmap getBitmap(String url) 
    {
        //I identify images by hashcode. Not a perfect solution, good for the demo.
        String filename=String.valueOf(url.hashCode());
        File f=new File(cacheDir, filename);

        //from SD cache
        Bitmap b = decodeFile(f);
        if(b!=null)
            return b;

        //from web
        try {
            Bitmap bitmap=null;
            InputStream is=new URL(url).openStream();
            OutputStream os = new FileOutputStream(f);
            Utils.CopyStream(is, os);
            os.close();
            bitmap = decodeFile(f);
            return bitmap;
        } catch (Exception ex){
           ex.printStackTrace();
           return null;
        }
    }

    //decodes image and scales it to reduce memory consumption
    private Bitmap decodeFile(File f){
        try {
            //decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f),null,o);

            //Find the correct scale value. It should be the power of 2.
            final int REQUIRED_SIZE=70;
            int width_tmp=o.outWidth, height_tmp=o.outHeight;
            int scale=1;
            while(true){
                if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                    break;
                width_tmp/=2;
                height_tmp/=2;
                scale*=2;
            }

            //decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize=scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        } catch (FileNotFoundException e) {}
        return null;
    }

    //Task for the queue
    private class PhotoToLoad
    {
        public String url;
        public ImageView imageView;
        public PhotoToLoad(String u, ImageView i){
            url=u; 
            imageView=i;
        }
    }

    PhotosQueue photosQueue=new PhotosQueue();

    public void stopThread()
    {
        photoLoaderThread.interrupt();
    }

    //stores list of photos to download
    class PhotosQueue
    {
        private Stack<PhotoToLoad> photosToLoad=new Stack<PhotoToLoad>();

        //removes all instances of this ImageView
        public void Clean(ImageView image)
        {
            for(int j=0 ;j<photosToLoad.size();){
                if(photosToLoad.get(j).imageView==image)
                    photosToLoad.remove(j);
                else
                    ++j;
            }
        }
    }

    class PhotosLoader extends Thread {
        public void run() {
            try {
                while(true)
                {
                    //thread waits until there are any images to load in the queue
                    if(photosQueue.photosToLoad.size()==0)
                        synchronized(photosQueue.photosToLoad){
                            photosQueue.photosToLoad.wait();
                        }
                    if(photosQueue.photosToLoad.size()!=0)
                    {
                        PhotoToLoad photoToLoad;
                        synchronized(photosQueue.photosToLoad){
                            photoToLoad=photosQueue.photosToLoad.pop();
                        }
                        Bitmap bmp=getBitmap(photoToLoad.url);
                        cache.put(photoToLoad.url, bmp);
                        Object tag=photoToLoad.imageView.getTag();
                        if(tag!=null && ((String)tag).equals(photoToLoad.url)){
                            BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView);
                            Activity a=(Activity)photoToLoad.imageView.getContext();
                            a.runOnUiThread(bd);
                        }
                    }
                    if(Thread.interrupted())
                        break;
                }
            } catch (InterruptedException e) {
                //allow thread to exit
            }
        }
    }

    PhotosLoader photoLoaderThread=new PhotosLoader();

    //Used to display bitmap in the UI thread
    class BitmapDisplayer implements Runnable
    {
        Bitmap bitmap;
        ImageView imageView;
        public BitmapDisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}
        public void run()
        {
            if(bitmap!=null)
                imageView.setImageBitmap(bitmap);
            else
                imageView.setImageResource(stub_id);
        }
    }

    public void clearCache() {
        //clear memory cache
        cache.clear();

        //clear SD cache
        File[] files=cacheDir.listFiles();
        for(File f:files)
            f.delete();
    }

}

the custom list view adapter from the LazyList project:

public class LazyAdapter extends BaseAdapter {

    private Activity activity;
    private String[] data;
    private static LayoutInflater inflater=null;
    public ImageLoader imageLoader; 

    public LazyAdapter(Activity a, String[] d) {
        activity = a;
        data=d;
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader=new ImageLoader(activity.getApplicationContext());
    }

    public int getCount() {
        return data.length;
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    public static class ViewHolder{
        public TextView text;
        public ImageView image;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View vi=convertView;
        ViewHolder holder;
        if(convertView==null){
            vi = inflater.inflate(R.layout.item, null);
            holder=new ViewHolder();
            holder.text=(TextView)vi.findViewById(R.id.text);;
            holder.image=(ImageView)vi.findViewById(R.id.image);
            vi.setTag(holder);
        }
        else
            holder=(ViewHolder)vi.getTag();

        holder.text.setText("item "+position);
        holder.image.setTag(data[position]);
        imageLoader.DisplayImage(data[position], activity, holder.image);
        return vi;
    }
}

and here's my custom ListView adapter: *ProjectAdapter class*

public class ProjectAdapter extends ArrayAdapter<Project> {

    int resource;
    String response;
    Context context;
    private final static String TAG = "MediaItemAdapter";

    private ImageThreadLoader imageLoader = new ImageThreadLoader();

    //Initialize adapter
    public ProjectAdapter(Context context, int resource, List<Project> items) {
        super(context, resource, items);
        this.resource=resource;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        TextView textTitle;
        final ImageView image;

        Project pro = getItem(position);

        LinearLayout projectView;
      //Inflate the view
        if(convertView==null)
        {
            projectView = new LinearLayout(getContext());
            String inflater = Context.LAYOUT_INFLATER_SERVICE;
            LayoutInflater vi;
            vi = (LayoutInflater)getContext().getSystemService(inflater);
            vi.inflate(resource, projectView, true);
        }
        else
        {
            projectView = (LinearLayout) convertView;
        }

        try {
          textTitle = (TextView)projectView.findViewById(R.id.txt_title);
          image = (ImageView)projectView.findViewById(R.id.image);
        } catch( ClassCastException e ) {
          Log.e(TAG, "Your layout must provide an image and a text view with ID's icon and text.", e);
          throw e;
        }


        Bitmap cachedImage = null;
        try {
          cachedImage = imageLoader.loadImage(pro.smallImageUrl, new ImageLoadedListener() {
          public void imageLoaded(Bitmap imageBitmap) {
          image.setImageBitmap(imageBitmap);
          notifyDataSetChanged();                }
          });
        } catch (MalformedURLException e) {
          Log.e(TAG, "Bad remote image URL: " + pro.smallImageUrl, e);
        }

        textTitle.setText(pro.project_title);

        if( cachedImage != null ) {
          image.setImageBitmap(cachedImage);
        }

        return projectView;
    }

}

Thank you very much!!

EDIT

UPDATED: ProjectList Activity

    public class ProjectsList extends Activity {
        /** Called when the activity is first created. */
        //ListView that will hold our items references back to main.xml
        ListView lstTest;
        //Array Adapter that will hold our ArrayList and display the items on the ListView
        ProjectAdapter arrayAdapter;
        ProgressDialog dialog;
        //List that will  host our items and allow us to modify that array adapter
        ArrayList<Project> prjcts=null;
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.projects_list);
            //Initialize ListView
            lstTest= (ListView)findViewById(R.id.lstText);

             //Initialize our ArrayList
            prjcts = new ArrayList<Project>();
            //Initialize our array adapter notice how it references the listitems.xml layout
            arrayAdapter = new ProjectAdapter(ProjectsList.this, R.layout.listitems,prjcts,ProjectsList.this);

            //Set the above adapter as the adapter of choice for our list
        lstTest.setAdapter(arrayAdapter);

        if (isOnline())
        {
        //Instantiate the Web Service Class with he URL of the web service not that you must pass
        //WebService webService = new WebService("http://notalentrocks.com/myplaceapp/projects.json");
        WebService webService = new WebService("http://liebenwald.spendino.net/admanager/dev/android/projects.json");

        //Pass the parameters if needed , if not then pass dummy one as follows
        Map<String, String> params = new HashMap<String, String>();
        params.put("var", "");

        //Get JSON response from server the "" are where the method name would normally go if needed example
        // webService.webGet("getMoreAllerts", params);
        String response = webService.webGet("", params);

        try
        {
             dialog = ProgressDialog.show(ProjectsList.this, "", "Fetching Projects...", true);
             dialog.setCancelable(true);
             dialog.setCanceledOnTouchOutside(true);
             dialog.setOnCancelListener(new OnCancelListener() {
                public void onCancel(DialogInterface dialog) {

                }
             });
            //Parse Response into our object
            Type collectionType = new TypeToken<ArrayList<Project>>(){}.getType();

            //JSON expects an list so can't use our ArrayList from the lstart
            List<Project> lst= new Gson().fromJson(response, collectionType);


            //Now that we have that list lets add it to the ArrayList which will hold our items.
            for(Project l : lst)
            {
                prjcts.add(l);
                ConstantData.projectsList.add(l);
            }

            //Since we've modified the arrayList we now need to notify the adapter that
            //its data has changed so that it updates the UI
            arrayAdapter.notifyDataSetChanged();
            dialog.dismiss();
        }
        catch(Exception e)
        {
            Log.d("Error: ", e.getMessage());
        }
        }  
        lstTest.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {              
                Intent care = new Intent(ProjectsList.this, ProjectDetail.class);
                care.putExtra("spendino.de.ProjectDetail.position",position);
                startActivity(care);
            }
        });

    }

    protected boolean isOnline() {
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnected()) {
            return true;
        } else {
             AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
             alertbox.setTitle("spendino Helfomat");
             alertbox.setMessage ("Please check your internet connection");
             alertbox.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                 public void onClick(DialogInterface dialog, int id) {
                      //Main.this.finish();
                 }
             });
             alertbox.show();
            return false;
        }
    }



}

UPDATED Here's my stacktrace:

05-12 11:36:52.670: ERROR/AndroidRuntime(299): Caused by: java.lang.NullPointerException
05-12 11:36:52.670: ERROR/AndroidRuntime(299):     at android.content.ContextWrapper.getCacheDir(ContextWrapper.java:183)
05-12 11:38:29.386: ERROR/AndroidRuntime(324):     at spendino.de.ImageLoader.<init>(ImageLoader.java:41)
05-12 11:36:52.670: ERROR/AndroidRuntime(299):     at spendino.de.Main.<init>(Main.java:56)

ImageLoader 41 is: cacheDir=context.getCacheDir(); Main 56 is: private ImageLoaderCache imageLoader = new ImageLoaderCache(Main.this);

Main.java

public class Main extends Activity { /** Called when the activity is first created. */

ArrayList<Project> prjcts=null;
private final static String TAG = "MediaItemAdapter";
ImageLoader imageLoader;
private Activity activity;
ImageView image1;
ImageView image2;
ImageView image3;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    if (isOnline())
    {


    prjcts = new ArrayList<Project>();
    WebService webService = new WebService("http://liebenwald.spendino.net/admanager/dev/android/projects.json");
    Map<String, String> params = new HashMap<String, String>();
    params.put("var", "");
    String response = webService.webGet("", params);

    imageLoader = new ImageLoader(Main.this);
    try
    {
        Type collectionType = new TypeToken<ArrayList<Project>>(){}.getType();
        List<Project> lst= new Gson().fromJson(response, collectionType);
        for(Project l : lst)
        {
            prjcts.add(l);
            ConstantData.projectsList.add(l);
        }
    }
    catch(Exception e)
    {
        Log.d("Error: ", e.getMessage());
    }

    try {
        image1 = (ImageView)findViewById(R.id.top1);
        image2 = (ImageView)findViewById(R.id.top2);
        image3 = (ImageView)findViewById(R.id.top3);
      } catch( ClassCastException e ) {
        Log.e(TAG, "Your layout must provide an image and a text view with ID's icon and text.", e);
        throw e;
      }

      //randomize the index of image entry

      int max = prjcts.size();
      List<Integer> indices = new ArrayList<Integer>(max);
      for(int c = 1; c < max; ++c)
      {
          indices.add(c);
      }

      Random r = new Random();
      int arrIndex = r.nextInt(indices.size());
      int randomIndex1 = indices.get(arrIndex);
      indices.remove(arrIndex);

      int arrIndex2 = r.nextInt(indices.size());
      int randomIndex2 = indices.get(arrIndex2);
      indices.remove(arrIndex2);

      int arrIndex3 = r.nextInt(indices.size());
      int randomIndex3 = indices.get(arrIndex3);
      indices.remove(arrIndex3);


      imageLazy(image1, prjcts.get(randomIndex1));
      imageLazy(image2, prjcts.get(randomIndex2));
      imageLazy(image3, prjcts.get(randomIndex3));

      image1.setOnClickListener(new RandomClickListener(randomIndex1));
      image2.setOnClickListener(new RandomClickListener(randomIndex2));
      image3.setOnClickListener(new RandomClickListener(randomIndex3));
    } 

    final Button project = (Button) findViewById(R.id.btn_projectslist);
    final Button infos = (Button) findViewById(R.id.btn_infos);
    final Button contact = (Button) findViewById(R.id.btn_contact);
    project.setOnClickListener(project_listener);
    infos.setOnClickListener(infos_listener);
    contact.setOnClickListener(contact_listener);
}

/*
 * isOnline - Check if there is a NetworkConnection
 * @return boolean
 */
protected boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnected()) {
        return true;
    } else {
         AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
         alertbox.setTitle("spendino Helfomat");
         alertbox.setMessage ("Bitte überprüfen Sie Ihre Internetverbindung");
         alertbox.setPositiveButton("OK", new DialogInterface.OnClickListener() {
             public void onClick(DialogInterface dialog, int id) {
                  Main.this.finish();
             }
         });
         alertbox.show();
        return false;
    }
}

public static class ViewHolder{
    public ImageView image;
}

public void imageLazy(final ImageView image,Project pro)
{
    imageLoadery.displayImage(pro.smallImageUrl, activity, image);
}

public void setImage(Bitmap cachedImage, final ImageView image, Project pro)
{
    try {
        cachedImage = imageLoader.loadImage(pro.smallImageUrl, new ImageLoadedListener() 
        {
            public void imageLoaded(Bitmap imageBitmap)
            {
                image.setImageBitmap(imageBitmap);              
            }
        });
    } catch (MalformedURLException e) {
        Log.e(TAG, "Bad remote image URL: " + pro.smallImageUrl, e);
    }
    if( cachedImage != null ) {
        image.setImageBitmap(cachedImage);
      }
}

public class RandomClickListener implements View.OnClickListener
{
    private final int randomIndex;

    public RandomClickListener(final int randomIndex)
    {
        this.randomIndex = randomIndex;
    }
    @Override
    public void onClick(View v)
    {
        Intent top = new Intent(Main.this, ProjectDetail.class);
        top.putExtra("spendino.de.ProjectDetail.position", randomIndex);
        startActivity(top);
    }
}

Stacktrace:

05-12 13:48:12.606: ERROR/AndroidRuntime(433):     at spendino.de.ImageLoaderCache$PhotosLoader.run(ImageLoaderCache.java:244)

解决方案

Seems that you did not use any view holder in your adapter

I have made changes in your classes.Hope it will works for you with out any difficulties

The ImageThreadLoader class

 import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Stack;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;

public class ImageThreadLoader {

    //the simplest in-memory cache implementation. This should be replaced with something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
    /** The cache. */
    private HashMap<String, Bitmap> cache=new HashMap<String, Bitmap>();

    /** The cache dir. */
    private File cacheDir;

    /**
     * Instantiates a new image loader.
     *
     * @param context the context
     */
    public ImageThreadLoader(Context context){
        //Make the background thead low priority. This way it will not affect the UI performance
        photoLoaderThread.setPriority(Thread.NORM_PRIORITY-1);

        //Find the dir to save cached images
        if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
            cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"cache_dir_img");
        else
            cacheDir=context.getCacheDir();
        if(!cacheDir.exists())
            cacheDir.mkdirs();
    }
    //This is used for a stub when the user can not see the actual image..
    //this images will be seen
    final int stub_id =R.drawable.sample_image;


    /**
     * Display image.
     *
     * @param url the url
     * @param activity the activity
     * @param imageView the image view
     */
    public void displayImage(String url, Activity activity, ImageView imageView)
    {
        if(cache.containsKey(url))
            imageView.setImageBitmap(cache.get(url));
        else
        {
            queuePhoto(url, activity, imageView);
            imageView.setImageResource(stub_id);
        }    
    }

    /**
     * Queue photo.
     *
     * @param url the url
     * @param activity the activity
     * @param imageView the image view
     */
    private void queuePhoto(String url, Activity activity, ImageView imageView)
    {
        //This ImageView may be used for other images before. So there may be some old tasks in the queue. We need to discard them. 
        photosQueue.Clean(imageView);
        PhotoToLoad p=new PhotoToLoad(url, imageView);
        synchronized(photosQueue.photosToLoad){
            photosQueue.photosToLoad.push(p);
            photosQueue.photosToLoad.notifyAll();
        }

        //start thread if it's not started yet
        if(photoLoaderThread.getState()==Thread.State.NEW)
            photoLoaderThread.start();
    }

    /**
     * Gets the bitmap.
     *
     * @param url the url
     * @return the bitmap
     */
    private Bitmap getBitmap(String url) 
    {
        //I identify images by hashcode. Not a perfect solution, good for the demo.
        String filename=String.valueOf(url.hashCode());
        File f=new File(cacheDir, filename);

        //from SD cache
        Bitmap b = decodeFile(f);
        if(b!=null)
            return b;

        //from web
        try {
            Bitmap bitmap=null;
            InputStream is=new URL(url).openStream();
            OutputStream os = new FileOutputStream(f);
            copyStream(is, os);
            os.close();
            bitmap = decodeFile(f);
            return bitmap;
        } catch (Exception ex){
           ex.printStackTrace();
           return null;
        }
    }

    //decodes image and scales it to reduce memory consumption
    /**
     * Decode file.
     *
     * @param f the f
     * @return the bitmap
     */
    private Bitmap decodeFile(File f){
        try {
            //decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f),null,o);

            //Find the correct scale value. It should be the power of 2.
            final int REQUIRED_SIZE=70;
            int width_tmp=o.outWidth, height_tmp=o.outHeight;
            int scale=1;
            while(true){
                if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                    break;
                width_tmp/=2;
                height_tmp/=2;
                scale++;
            }

            //decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize=scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        } catch (FileNotFoundException e) {}
        return null;
    }

    //Task for the queue
    /**
     * The Class PhotoToLoad.
     */
    private class PhotoToLoad
    {

        /** The url. */
        public String url;

        /** The image view. */
        public ImageView imageView;

        /**
         * Instantiates a new photo to load.
         *
         * @param u the u
         * @param i the i
         */
        public PhotoToLoad(String u, ImageView i){
            url=u; 
            imageView=i;
        }
    }

    /** The photos queue. */
    PhotosQueue photosQueue=new PhotosQueue();

    /**
     * Stop thread.
     */
    public void stopThread()
    {
        photoLoaderThread.interrupt();
    }

    //stores list of photos to download
    /**
     * The Class PhotosQueue.
     */
    class PhotosQueue
    {

        /** The photos to load. */
        private Stack<PhotoToLoad> photosToLoad=new Stack<PhotoToLoad>();

        //removes all instances of this ImageView
        /**
         * Clean.
         *
         * @param image the image
         */
        public void Clean(ImageView image)
        {
            for(int j=0 ;j<photosToLoad.size();){
                if(photosToLoad.get(j).imageView==image)
                    photosToLoad.remove(j);
                else
                    ++j;
            }
        }
    }

    /**
     * The Class PhotosLoader.
     */
    class PhotosLoader extends Thread {

        /* (non-Javadoc)
         * @see java.lang.Thread#run()
         */
        public void run() {
            try {
                while(true)
                {
                    //thread waits until there are any images to load in the queue
                    if(photosQueue.photosToLoad.size()==0)
                        synchronized(photosQueue.photosToLoad){
                            photosQueue.photosToLoad.wait();
                        }
                    if(photosQueue.photosToLoad.size()!=0)
                    {
                        PhotoToLoad photoToLoad;
                        synchronized(photosQueue.photosToLoad){
                            photoToLoad=photosQueue.photosToLoad.pop();
                        }
                        Bitmap bmp=getBitmap(photoToLoad.url);
                        cache.put(photoToLoad.url, bmp);
                        if(((String)photoToLoad.imageView.getTag()).equals(photoToLoad.url)){
                            BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad.imageView);
                            Activity a=(Activity)photoToLoad.imageView.getContext();
                            a.runOnUiThread(bd);
                        }
                    }
                    if(Thread.interrupted())
                        break;
                }
            } catch (InterruptedException e) {
                //allow thread to exit
            }
        }
    }

    /** The photo loader thread. */
    PhotosLoader photoLoaderThread=new PhotosLoader();

    //Used to display bitmap in the UI thread
    /**
     * The Class BitmapDisplayer.
     */
    class BitmapDisplayer implements Runnable
    {

        /** The bitmap. */
        Bitmap bitmap;

        /** The image view. */
        ImageView imageView;

        /**
         * Instantiates a new bitmap displayer.
         *
         * @param b the b
         * @param i the i
         */
        public BitmapDisplayer(Bitmap b, ImageView i){bitmap=b;imageView=i;}

        /* (non-Javadoc)
         * @see java.lang.Runnable#run()
         */
        public void run()
        {
            if(bitmap!=null)
                imageView.setImageBitmap(bitmap);
            else
              imageView.setImageResource(stub_id);
        }
    }

    /**
     * Clear cache.
     */
    public void clearCache() {
        //clear memory cache
        cache.clear();

        //clear SD cache
        File[] files=cacheDir.listFiles();
        for(File f:files)
            f.delete();
    }

     public static void copyStream(InputStream is, OutputStream os) {
            final int buffer_size=1024;
            try
            {
                byte[] bytes=new byte[buffer_size];
                for(;;)
                {
                  int count=is.read(bytes, 0, buffer_size);
                  if(count==-1)
                      break;
                  os.write(bytes, 0, count);
                }
            }
            catch(Exception ex){}
        }


}

Now your ProjectAdapter class

import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class ProjectAdapter extends ArrayAdapter<Project> {

    int resource;
    String response;
    Context context;
    List<Project> items;
    private ImageThreadLoader imageLoader;
    LayoutInflater mInflater;
    Activity activity;

    // Initialize adapter
    public ProjectAdapter(Context context, int resource, List<Project> items,
            Activity activity) {
        super(context, resource, items);
        this.resource = resource;
        imageLoader = new ImageThreadLoader(context);
        this.items = items;
        mInflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        this.activity = activity;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder = null;

        // Inflate the view
        if (convertView == null) {

            convertView = mInflater.inflate(resource, null);
            holder = new ViewHolder();
            holder.image = (ImageView) convertView.findViewById(R.id.image);
            holder.textTitle = (TextView) convertView
                    .findViewById(R.id.txt_title);
            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Project project = items.get(position);

        holder.textTitle.setText(project.project_title);

        String imageurl = project.smallImageUrl;
        holder.image.setTag(imageurl);
        imageLoader.displayImage(imageurl, activity, holder.image);
        return convertView;

    }

    static class ViewHolder {

        TextView textTitle;

        ImageView image;
    }

And at last when you set the adapter in your ListView after getting the web data, use this

your_listview.setAdapter(your_ProjectAdapter_instance );
your_ProjectAdapter_instance .notifyDataSetChanged();