2014-02-22 122 views
0

我使用从数据库接收游标结果集的自定义游标适配器填充ListView。最多可能需要10-12秒才能显示20个视图!使用CursorAdder的非常缓慢的ListView

这里是CursorAdater类光标所在提供字符串和一个底座64的图像表示为一系列的文本视图以及对于每个视图图像的视图

public void bindView(View v, Context context, Cursor c) { 
      String diveSite = c.getString(c.getColumnIndexOrThrow(diveDataBase.KEY_DIVESITE)); 
      String date = c.getString(c.getColumnIndexOrThrow(diveDataBase.KEY__DIVEDATE)); 
      String diveNumber= c.getString(c.getColumnIndexOrThrow(diveDataBase.KEY__DIVENUMBER)); 
      String diveImagePath = c.getString(c.getColumnIndex(diveDataBase.KEY_DIVEPICTURE)); 
      String rating = c.getString(c.getColumnIndexOrThrow(diveDataBase.KEY_DIVERATING)); 

      c.moveToLast(); 
      noOfRows = Integer.parseInt(c.getString(c.getColumnIndex(diveDataBase.KEY__DIVENUMBER))); 


      /** 
      * Next set the dive site name 
      */ 

      TextView title_text = (TextView) v.findViewById(R.id.tv_DiveSiteListView); 
      if (title_text!= null) { 
       title_text.setText(diveSite); 
      } 

      /** 
      * Set Date of dive in smaller textView font 
      */ 

      TextView date_text = (TextView) v.findViewById(R.id.tv_diveDateList); 
      if (date_text!= null) { 
       date_text.setText(date); 
      }  

      /** 
      * Display the dive number in larger red font 
      */ 

      TextView dive_no = (TextView) v.findViewById(R.id.tv_diveNumberListView); 
      if (diveNumber!= null ) { 
       dive_no.setText(diveNumber+"/"+noOfRows);//+1 as rows start at zero 
      } 


      /* 
      * Display the rating of the dive 
      */ 
      RatingBar bar = (RatingBar) v.findViewById(R.id.ratingBarListView); 
      bar.setNumStars(5); 

      bar.setRating(Float.parseFloat(rating)); 
      /** 
      * Display the image only of image not null 
      * First get image from Strimg pathname as a file, then convert to Bitmap and resize 
      * 
      */ 

      ImageView displayImage = (ImageView) v.findViewById(R.id.iv_list_image); 

//set image here once taken form external string path, and resized bitmap conversion 

      imagePathFile = new File(diveImagePath); 
      try { 
       FileInputStream streamIn = new FileInputStream(imagePathFile); 
       Bitmap bitmap = BitmapFactory.decodeStream(streamIn);//retrun null if can't convert 

       if(bitmap!=null){ 
        displayImage.setBackground(null); 
        resizedImage = reSizeImage(bitmap); 

        displayImage.setImageBitmap(resizedImage); 


       }else{ 

        displayImage.setBackgroundResource(R.drawable.logdive3); 
       } 

      } 

      catch (FileNotFoundException e) { 
       e.printStackTrace(); 


      }//end try catch 

      }//end newView 

而在列表视图类中,光标在异步类的后台处理方法中获得,并且适配器在后执行中设置:

@Override 
     protected Cursor doInBackground(Void... params) { 
      // get the cursor from database 

         ViewListOfDives.data = new diveDataBase(ViewListOfDives.this); 
         ViewListOfDives.data.open(); 
         // get cursor object holding all data, use a asynch inner class to load 
         cursor = data.getCursorData(); 


         //ViewListOfDives.data.close(); 
      return cursor; 
     } 

//set the adapter to list view 

@Override 
     protected void onPostExecute(Cursor cursor) { 

         //check if data available 
         if(cursor!=null && cursor.getCount()>0){ 
         // get customised array adoater list 
         adapter = new ItemAdapter(ViewListOfDives.this, cursor); 
         }else{ 

           //display o dives in data base message and finish this activity 
           displayDialog(); 

         } 
         ViewListOfDives.this.setListAdapter(adapter); 
         ViewListOfDives.data.close(); 
      super.onPostExecute(cursor); 
      // dispose dialog 
         if(pd.isShowing()){ 
            pd.dismiss(); 
         } 
     } 

一直在研究配线上找不到太多的性能优化光标适配器,所以任何输入将不胜感激!

编辑:包括方法我使用来调整图像:

public Bitmap reSizeImage(Bitmap bitmapImage) { 
      // resize bitmap image passed and rerun new one 
      Bitmap resizedImage = null; 
      float factorH = h/(float) bitmapImage.getHeight(); 
      float factorW = w/(float) bitmapImage.getWidth(); 
      float factorToUse = (factorH> factorW)? factorW : factorH; 
      try { 
       resizedImage = Bitmap.createScaledBitmap(bitmapImage, 
         (int) (bitmapImage.getWidth() * factorToUse), 
         (int) (bitmapImage.getHeight() * factorToUse), false); 
      } catch (IllegalArgumentException e) { 
       Log.d(TAG, "Problem resizing Image @Line 510+"); 
       e.printStackTrace(); 
      } 
      Log.d(TAG, 
        "in resixed, value of resized image: " 
          + resizedImage.toString()); 
      return resizedImage; 
     }// end reSize 

其中h和w:

// for image resizing 
     static int w = 250; 
     static int h = 280; 

编辑:有wriiten一个非同步类来处理底座64的转换为位图,然后在后执行图像视图设置为位图。这个内部类被称为形式cursoradpter类的bindView方法。问题现在只有最后一个视图是充满机智的图像!

//asynch class to load nase 64 image and convert to bitmap and set imageview 

      private class getBitmapImage extends AsyncTask<String, Void, Bitmap>{ 

       @Override 
       protected Bitmap doInBackground(String... imagePath) { 

        // get image path and decode to bitmap 
        String diveImagePath = imagePath[0]; 
        //String diveImagePath = c.getString(c.getColumnIndex(diveDataBase.KEY_DIVEPICTURE)); 
        File imagePathFile = new File(diveImagePath); 
        try { 
          FileInputStream streamIn = new FileInputStream(imagePathFile); 
          bitmap = BitmapFactory.decodeStream(streamIn);//retrun null if cant convert 
       }catch (FileNotFoundException e) { 

        e.printStackTrace(); 
        //Toast.makeText(context, "No Image Found!! Usimng default", Toast.LENGTH_LONG).show(); 

       }//end try catch 

        return bitmap; 

       }//end do in background 


       @Override 
       protected void onPostExecute(Bitmap bitmap) { 

        if(bitmap!=null){ 
         displayImage.setBackground(null); 
         resizedImage = reSizeImage(bitmap); 

         displayImage.setImageBitmap(resizedImage); 


        }else{ 
         //Toast.makeText(context, "No Image Found!! Usimng default", Toast.LENGTH_LONG).show(); 
         displayImage.setBackgroundResource(R.drawable.logdive3); 
        } 

       }//end onPOstExecute 
      }//end getBitmap asynch 

此内部类就是所谓的CursorAdpter类的bindView方法:

//get bitmap image from base 64 string, and set to image view using asynch class thread 
      new getBitmapImage().execute(diveImagePath); 
+1

您正在加载位图的UI线程它会导致您的列表视图性能slow..load在其他线程。 –

回答

2
  1. 把文字在屏幕上第一。也许默认的drawables显示的东西正在加载。

  2. 从文件中加载20个位图至少需要几秒钟的时间。你应该加载这些异步(从填充你的列表视图的线程)。只有你的UI线程可以设置imageview,但你可以在工作线程中加载位图,这是最重要的工作。

  3. 您还应该使用采样加载位图,因此您不会以比所显示的分辨率更高的分辨率加载它们,否则您正在读取的数据超出您的需要。

有关加载大型位图的信息,请参见android tutorial

+0

不能评论,因为我看不到的代码,但我看到你的编辑,包括你的调整大小功能的bitamps。读取文件时应该进行采样,而不是在加载之后进行采样。你可能会跳过所有这些字节的初始阅读。 – NameSpace

+0

嗨,我写了一个同步内部类来处理base 64到位图的转换,它被传递给onPOstExceute,它被设置为imagvview。它现在是快5倍,但唯一列表视图更新与图像是最后的名单!病后邮编可以ü检查吗? – dancingbush

+0

看不到所有的代码,但它可能所有的异步任务都指向相同的全局,并且由于图像加载器需要一段时间,它们都加载到最后一个加载的视图中。尝试将引用传递给不是全局的iv,然后将其设置为post执行。 – NameSpace