2012-12-16 194 views
0

在我的UI中,第一張圖片總是隨機的,起初我嘗試清理項目並擦除AVD中的個人數據,但這並沒有幫助。隨機只有第一張圖片,其他所有圖片都正確顯示。在活動開始的幾秒鐘內,圖片會發生多次變化。Listview顯示隨機圖片

請不要參考複製的Android ocasionally downloads images from url,因爲它是differenet(和解決)問題

enter image description here

public class ImageLoader { 

    MemoryCache memoryCache=new MemoryCache(); 
    FileCache fileCache; 
    private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>()); 
    ExecutorService executorService; 

    public ImageLoader(Context context){ 
     fileCache=new FileCache(context); 
     executorService=Executors.newFixedThreadPool(5); 
    } 

    int stub_id = R.drawable.ic_launcher; 
    public void DisplayImage(String uurl, int loader, ImageView imageView) 
    { 
     String url = uurl.replaceAll(" ", "%20"); 
     url = url.replaceAll("\n", "%20"); 
     stub_id = loader; 
     imageViews.put(imageView, url); 
     Bitmap bitmap=memoryCache.get(url); 
     if(bitmap!=null) 
      imageView.setImageBitmap(bitmap); 
     else 
     { 
      queuePhoto(url, imageView); 
      imageView.setImageResource(loader); 
     } 
    } 

    private void queuePhoto(String url, ImageView imageView) 
    { 
     PhotoToLoad p=new PhotoToLoad(url, imageView); 
     executorService.submit(new PhotosLoader(p)); 
    } 

    private Bitmap getBitmap(String url) 
    { 
     File f=fileCache.getFile(url); 

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

     //from web 
     /*try { 
      Bitmap bitmap=null; 
      URL imageUrl = new URL(url); 
      HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection(); 
      conn.setConnectTimeout(30000); 
      conn.setReadTimeout(30000); 
      conn.setInstanceFollowRedirects(true); 
      InputStream is=conn.getInputStream(); 
      OutputStream os = new FileOutputStream(f); 
      Utils.CopyStream(is, os); 
      os.close(); 
      bitmap = decodeFile(f); 
      return bitmap; 
     } catch (Exception ex){ 
      ex.printStackTrace(); 
      return null; 
     }*/ 
    } 
    Bitmap downloadBitmap(String url){ 
     Bitmap bmp = null; 
     URL url_1 = null; 
     try { 
      url_1 = new URL(url); 
      bmp = BitmapFactory.decodeStream(url_1.openConnection().getInputStream()); 
     } catch (Exception e) { 
      Log.v("Error while downloading bitmap from url", e.getMessage()); 
     } 
     return bmp; 
    } 

    //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; 
     } 
    } 

    class PhotosLoader implements Runnable { 
     PhotoToLoad photoToLoad; 
     PhotosLoader(PhotoToLoad photoToLoad){ 
      this.photoToLoad=photoToLoad; 
     } 

     public void run() { 
      if(imageViewReused(photoToLoad)) 
       return; 
      Bitmap bmp=getBitmap(photoToLoad.url); 
      memoryCache.put(photoToLoad.url, bmp); 
      if(imageViewReused(photoToLoad)) 
       return; 
      BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad); 
      Activity a=(Activity)photoToLoad.imageView.getContext(); 
      a.runOnUiThread(bd); 
     } 
    } 

    boolean imageViewReused(PhotoToLoad photoToLoad){ 
     String tag=imageViews.get(photoToLoad.imageView); 
     if(tag==null || !tag.equals(photoToLoad.url)) 
      return true; 
     return false; 
    } 

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

    public void clearCache() { 
     memoryCache.clear(); 
     fileCache.clear(); 
    } 

} 

filecash

public class FileCache { 

    private File cacheDir; 

    public FileCache(Context context){ 
     //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(),"TempImages"); 
     else 
      cacheDir=context.getCacheDir(); 
     if(!cacheDir.exists()) 
      cacheDir.mkdirs(); 
    } 

    public File getFile(String url){ 
     String filename=String.valueOf(url.hashCode()); 
     File f = new File(cacheDir, filename); 
     return f; 

    } 

    public void clear(){ 
     File[] files=cacheDir.listFiles(); 
     if(files==null) 
      return; 
     for(File f:files) 
      f.delete(); 
    } 

} 

內存現金

public class MemoryCache { 
    private Map<String, SoftReference<Bitmap>> cache=Collections.synchronizedMap(new HashMap<String, SoftReference<Bitmap>>()); 

    public Bitmap get(String id){ 
     if(!cache.containsKey(id)) 
      return null; 
     SoftReference<Bitmap> ref=cache.get(id); 
     return ref.get(); 
    } 

    public void put(String id, Bitmap bitmap){ 
     cache.put(id, new SoftReference<Bitmap>(bitmap)); 
    } 

    public void clear() { 
     cache.clear(); 
    } 
} 

public class Utils { 
    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){} 
    } 
} 

適配器

public class CandidateAdapter extends BaseAdapter{ 
    Context ctx; 
    LayoutInflater lInflater; 
    ArrayList<Candidate> objects; 
    CandidateAdapter(Context context, ArrayList<Candidate> candidates) { 
      ctx = context; 
      objects = candidates; 
      lInflater = (LayoutInflater) ctx 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      } 
    public int getCount() { 
     return objects.size(); 
     } 
    public Object getItem(int position) { 
     return objects.get(position); 
     } 
    public long getItemId(int position) { 
     return position; 
     } 
    Candidate getCandidate(int position) { 
     return ((Candidate) getItem(position)); 
     } 
    public View getView(int position, View convertView, ViewGroup parent) { 
     // используем созданные, но не используемые view 
     View view = convertView; 
     if (view == null) { 
      view = lInflater.inflate(R.layout.inbox_list_item, parent, false); 
     } 
     Candidate p = getCandidate(position); 
     ((TextView) view.findViewById(R.id.from)).setText(p.get_name()); 
     ((TextView) view.findViewById(R.id.subject)).setText(p.get_office()); 
     ((RatingBar) view.findViewById(R.id.rateindicator)).setRating(p.get_ranking()); 
     int loader = R.drawable.loader; 


     ImageView image = (ImageView) view.findViewById(R.id.photo); 


     String image_url = p.get_photograph(); 


     ImageLoader imgLoader = new ImageLoader(ctx); 


     imgLoader.DisplayImage(image_url, loader, image); 
     return view; 
    } 



} 

活性

public class InboxActivity extends ListActivity { 

    List<Candidate> candidates; 
    private DatabaseHandler db; 

    public void onDestroy(){ 
     if (db != null) 
      db.close(); 

     super.onDestroy(); 
     //db.close(); 
    } 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.inbox_list); 
     db = new DatabaseHandler(this); 
     candidates = db.getAllCandidates(1); 
     db.close(); 
     CandidateAdapter adapter = new CandidateAdapter(this,(ArrayList) candidates); 
     ListView lvMain = getListView(); 
     //String numofrows = "" + candidates.size(); 
     //Log.d("Number of candidates", numofrows); 
     lvMain.setAdapter(adapter); 
     lvMain.setOnItemClickListener(new OnItemClickListener() { 

      public void onItemClick(AdapterView<?> parent, View view, 
        int position, long id) { 
       // getting values from selected ListItem 
       String name = ((TextView) view.findViewById(R.id.from)).getText().toString(); 
       Log.d("Name ", name); 

       // Starting new intent 
       Intent in = new Intent(getApplicationContext(), SingleMenuItemActivity.class); 
       in.putExtra("name", name); 
       Log.d("Starting activity ", "Yeah "); 
       startActivity(in); 

      } 
     }); 
    } 





} 

logcat的警告

8月12日至16日:35:33.525:W /合子(33):接觸體繪製資源#0x1080093(res/drawable-hdpi/sym_def_app_icon.png)隨confi變化guration!

任何人都可以幫我解決這裏的問題嗎?

GETALL候選人功能

public List<Candidate> getAllCandidates(int status) { 
     List<Candidate> candidateList = new ArrayList<Candidate>(); 
     // Select All Query 
     String selectQuery = "SELECT * FROM " + TABLE_CANDIDATES; 

     db = this.getReadableDatabase(); 
     cursor = db.rawQuery(selectQuery, null); 

     // looping through all rows and adding to list 
     if (cursor.moveToFirst()) { 
      do { 
       Candidate candidate = new Candidate(); 
       if (status == Integer.parseInt(cursor.getString(5))) { 
        candidate.set_name(cursor.getString(0)); 
        candidate.set_office(cursor.getString(1)); 
        candidate.set_photograph(cursor.getString(2)); 
        candidate.set_promises(cursor.getString(3)); 
        candidate.set_statment(cursor.getString(4)); 
        candidate.set_active(Integer.parseInt(cursor.getString(5))); 
        candidate.set_ranking(Integer.parseInt(cursor.getString(6))); 
        // Adding candidate to list 
        candidateList.add(candidate); 
       } 
      } while (cursor.moveToNext()); 
     } 

     // return candidate list 
     db.close(); 
     cursor.close(); 
     return candidateList; 
    } 
+0

db = new DatabaseHandler(this); candidates = db.getAllCandidates(1);看起來有點懷疑。 你可以顯示getAllCandidates的查詢嗎?什麼是爭論? –

+0

尚未讀取所有代碼,但我的第一本能是imageview正在被列表重用,異步加載沒有考慮到這一點 – MrChaz

+0

參數只是選擇active = 1的候選 – Yarh

回答

0

你的ImageView可以通過列表視圖可以得到循環使用。您的問題可能是對傳遞給ImageLoader的圖像的陳舊引用。

您可以在調用DisplayImage之前檢查imageView的實例,然後在加載之後驗證此情況。

ImageLoader imgLoader = new ImageLoader(ctx); 


     imgLoader.DisplayImage(image_url, loader, image); 

你可能要考慮使用viewholder模式來保存你的ImageLoader的,而不是每一次,這也可能有助於創造一個新的。

ImageLoader imgLoader = (ImageLoader) view.getTag() 
if(imgLoader == null){ 
imgLoader = new ImageLoader(ctx); 
view.setTag(imgLoader); 
} 

這是它只是採取了刺。很難知道沒有運行它,但希望它可以幫助:) 祝你好運