Страница 1 из 1

Загрузка изображения из сети, в адаптере GridView

Добавлено: 05 янв 2014, 01:36
sanu0074
Есть адаптер, в котором открывается новый поток и грузится изображение из сети, в загружающий класс передается ссылка и данные, проблема в том что загрузка изображений не останавливается, где то допустил ошибку, помогите разобраться:

адаптер:

Код: Выделить всё

public class GridViewAdapter extends BaseAdapter {
	 
    private static class ViewHolder {
        TextView name,count_download;
        ImageView icon;
        Main m;
        
        String id,url_id,script,icon_lnk,icon_name;
        
        

    }
 
    private Context context;
    private List<HashMap<String, String>> arrayList;
    private LayoutInflater layoutInflater;
 
 
    GridViewAdapter(Context context, List<HashMap<String, String>> data) {
        this.context = context;
        this.arrayList = data;
        layoutInflater = LayoutInflater.from(context);
    }
 
    @Override
    public int getCount() {
        return arrayList.size();
    }
 
    @Override
    public Object getItem(int position) {
        return arrayList.get(position);
    }
 
    @Override
    public long getItemId(int position) {
        return position;
    }
    
    String getName(String s){
        int dotIdx = s.lastIndexOf('.');
        int bslashIdx = s.lastIndexOf('.');
        if (dotIdx != -1 && bslashIdx != -1) {
            return s.substring(bslashIdx + 1, dotIdx);
        }
        return s;
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder viewHolder;
 
        if(convertView == null) {
            convertView = layoutInflater.inflate(R.layout.main_activity_item, null);
            viewHolder = new ViewHolder();
            viewHolder.name = (TextView)convertView.findViewById(R.id.name);
            viewHolder.icon = (ImageView)convertView.findViewById(R.id.icon);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder)convertView.getTag();
        }
 
        Animation animation = AnimationUtils.loadAnimation(context, R.anim.rotate); 
		
        viewHolder.name.setText(arrayList.get(position).get("name"));
        viewHolder.icon.startAnimation(animation);
        viewHolder.script = arrayList.get(position).get("script");
        viewHolder.url_id = arrayList.get(position).get("url_id");
        viewHolder.id = arrayList.get(position).get("id");
        viewHolder.icon_lnk = arrayList.get(position).get("icon");
        viewHolder.icon_name = "name12";
        
        new Thread() {	//открываем новый поток
    		@Override
            public void run() {
               
    			

	            	   DownloadImage di = (DownloadImage) new DownloadImage(viewHolder.icon,viewHolder.script,viewHolder.id,viewHolder.icon_name).execute("http://192.168.0.20/"+viewHolder.icon_lnk);
	            	   try {
            		   	for(;;Thread.sleep(500)){	//ждем немного  (беконечный цикл ожиданий)
            		   		if(di.fin==true){Log.d("MyLog", "Упешная загрузка картинки #"+viewHolder.icon_lnk); break;}	//если картинка загружена то выходим из этого цикла
            		   		else{Log.d("MyLog", "Попытка загрузки картинки #"+viewHolder.icon_lnk);}
						}} catch (InterruptedException e) {e.printStackTrace();}

            }
	}.start();
        
        return convertView;
    }


}
Загрузчик:

Код: Выделить всё

public class DownloadImage extends AsyncTask<String, Void, Bitmap> { 
	public String ROOT_DIR="FolderName";
	public String FileName;
    ImageView bmImage; //сама картинка
    boolean fin=false; //окончание таска
    String contentType, id;

    DownloadImage(ImageView bmImage, String contentType, String id, String FileName) { 
        this.bmImage = bmImage; 
        this.contentType = contentType; 
        this.id = id; 
        this.FileName = FileName+".webp"; 
    } 
    

    protected Bitmap doInBackground(String... url) { 
        String urldisplay = url[0]; 
        Bitmap image = null; 
        try { 
            InputStream in = new java.net.URL(urldisplay).openStream(); 
            image = BitmapFactory.decodeStream(in); 
        } catch (Exception e) { 
            Log.e("Error", e.getMessage()); 
            e.printStackTrace(); 
        } 
        
        String root = Environment.getExternalStorageDirectory().toString();
        File Dir = new File(root + File.separator + ROOT_DIR + File.separator + contentType + id);    
        Dir.mkdirs();


        Log.d("FILE_IMAGE", FileName);
        File file = new File (Dir, FileName);
        if (file.exists ()) file.delete (); 
        try {
               FileOutputStream out = new FileOutputStream(file);
               image.compress(Bitmap.CompressFormat.WEBP, 90, out);
               out.flush();
               out.close();

        } catch (Exception e) {
               e.printStackTrace();
        }
        
        return image; 
    } 
    

    protected void onPostExecute(Bitmap result) {
    	bmImage.clearAnimation();
        bmImage.setImageBitmap(result); 
        bmImage.setScaleType(ScaleType.FIT_CENTER);
        fin=true; 
    } 
}
p.s. В адаптере, есть функция getName(), которая из пути возвращает имя файла, если я её использую, то приложение вылетает....

Re: Загрузка изображения из сети, в адаптере GridView

Добавлено: 06 янв 2014, 15:07
altwin
Че то я не заметил, чтобы вы после создания объекта DownloadImage di - вызвали для него свой метод doInBackground, который по сути запустит фоновый поток и по завершении вызовет onPostExecute, в котором вы присваиваете fin=true. Вы же используете метод Http клиента execute, который по сути никогда не сделает fin==true, соответственно fin==false всегда и цикл бесконечный. В детали я не вдавался потому будет оно работать или нет если просто заменить execute на doInBackground, не знаю. но если ошибок нет - то должно.

Re: Загрузка изображения из сети, в адаптере GridView

Добавлено: 07 янв 2014, 03:41
sanu0074
altwin писал(а):заменить execute на doInBackground
я пробовал не получилось...
Сделал так:

Код: Выделить всё

 
//...
Download gu = new Download(viewHolder.icon,viewHolder.script,viewHolder.id,viewHolder.icon_name,"http://192.168.0.20/"+viewHolder.icon_lnk);
	    gu.start();													//обращаясь к серверу
    	try {
			gu.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
        
        return convertView;
    }

    class Download extends Thread{
    	Download(ImageView icon,String script,String id,String icon_name,String icon_lnk){
    		DownloadImage di = (DownloadImage) new DownloadImage(icon,script,id,icon_name).execute(icon_lnk);
    	 	  
    	}
//...
Загружает несколько изображений и выдает ошибку:

Код: Выделить всё

01-07 02:38:49.189: A/libc(6397): Fatal signal 11 (SIGSEGV) at 0x92be77bd (code=1), thread 6397 (ru.homeandroid)

Re: Загрузка изображения из сети, в адаптере GridView

Добавлено: 07 янв 2014, 11:46
altwin
Не получилось, значит метод реализован не правильно.
А ошибка - ого... это уметь надо(особенно без использования NDK). Вы получили ошибку, поскольку пытаетесь получить доступ к памяти, к которой доступа у вас нет. Это ошибка в "куче" dalvik, т.е. каким то образом вы туда передали null или как то перезаписали то, что dalvik использует. Это может быть связанно с потоками, тут нужно ставить "точки остановы" и смотреть, что и куда передается.

P.S> по сути, вашему приложению нужно перестать лезть в память за пределами своего доступа. Но как вы получили SIGSEGV... это ошибка из нативного кода. т.е. A/libc - это реализация стандартной libc, от google для Android. Скорее всего проблема в "потоко не безопасном коде"... Т.е. сейчас вы не делаете синхронизацию потоков и обращаетесь к полю, которое не было создано/уничтожено/занято. Стоит попробовать запустить на других устройствах/эмуляторах, желательно на Nexus с оригинальным ROM, вполне возможно, что это баг прошивки либо самого Android.

Но вообще первым делом нужно проверить, что изображения действительно загружаются в папку assets и проверить то что у вас нет проблем с памятью в устройстве из за того, что вы грузите сразу много изображений в нее.

Re: Загрузка изображения из сети, в адаптере GridView

Добавлено: 07 янв 2014, 17:57
sanu0074
с устройством проблем нет, и картинки грузятся в нужную папку. Вот есть пример в котором всё работает (когда-то давно делал, исп этот же класс):

Код: Выделить всё

    public void StartDIm()	 
    {
    	 
    	if(counterIm>=cursor){Log.d(STAG, "Картинки закончелись, грузить нечего больше!"); return;}
    	
    	new Thread() {	 
	    		@Override
	            public void run() {
	               for(; counterIm<cursor; counterIm++){	 
	            	   									 
	            	   if(paused==true){Log.d(STAG, "Пауза, открылось новое активити!"); return;}
	            	   									 
	            	   fileExist=new ShowPictureInSD(PointersName[counterIm],PointersContentType[counterIm],PointersId[counterIm],Pointers[counterIm],Main.this);
	            	   try {
						for(;;Thread.sleep(100)){	 
							if(fileExist.fin==true){Log.d(STAG, "Файл проверен в классе ShowPictureInSD"); break;}	 
							else{Log.d(STAG, "Жду проверки файла на существование");}
						}} catch (InterruptedException e) {e.printStackTrace();}
	            	   
	            	   Log.d(STAG, "fileExist.flag="+fileExist.flag);
	            	   
	            	   if(fileExist.flag==false)
	            	   {
	            		   Log.d(STAG, "Картинки нет в памяти, посылаю запрос на сервер");
		            	   DownloadImage di = (DownloadImage) new DownloadImage(Pointers[counterIm],PointersContentType[counterIm],PointersId[counterIm],PointersName[counterIm]).execute(Links[counterIm]);
		            	   try {
	            		   	for(;;Thread.sleep(500)){	 
	            		   		if(di.fin==true){Log.d(STAG, "Упешная загрузка картинки #"+counterIm); break;}	 
	            		   		else{Log.d(STAG, "Попытка загрузки картинки #"+counterIm);}
							}} catch (InterruptedException e) {e.printStackTrace();}
	               		}
	               	  }
	            }
    	}.start();
    }

Re: Загрузка изображения из сети, в адаптере GridView

Добавлено: 07 янв 2014, 18:55
altwin
а если загрузить меньше картинок? вполне может быть, что они не помещаются в память вот и ругается на то, что в "куче" нет для вас больше места.

Re: Загрузка изображения из сети, в адаптере GridView

Добавлено: 08 янв 2014, 10:31
sanu0074
altwin писал(а):а если загрузить меньше картинок? вполне может быть, что они не помещаются в память вот и ругается на то, что в "куче" нет для вас больше места.
пробовал.... Сделал другим способом, вот вызов:

Код: Выделить всё

ImageManager.fetchImage(viewHolder.icon_lnk, viewHolder.icon);
И сам класс (взял на хабре):

Код: Выделить всё

public class ImageManager {
  private final static String TAG = "ImageManager";
 
  /** Private constructor prevents instantiation from other classes */
  private ImageManager () {}
 
  public static void fetchImage(final String iUrl, final ImageView iView) {
    if ( iUrl == null || iView == null )
      return;
 
    final Handler handler = new Handler() {
      @Override
      public void handleMessage(Message message) {
        final Bitmap image = (Bitmap) message.obj;
        iView.setImageBitmap(image);
      }
    };
 
    final Thread thread = new Thread() {
      @Override
      public void run() {
        final Bitmap image = downloadImage(iUrl);
        if ( image != null ) {
          Log.v(TAG, "Got image by URL: " + iUrl);
          final Message message = handler.obtainMessage(1, image);
          handler.sendMessage(message);
        }
      }
    };
    iView.setImageResource(R.drawable.wait);
    thread.setPriority(3);
    thread.start();
  }
 
  public static Bitmap downloadImage(String iUrl) {
    Bitmap bitmap = null;
    HttpURLConnection conn = null;
    BufferedInputStream buf_stream = null;
    try {
      Log.v(TAG, "Starting loading image by URL: " + iUrl);
      conn = (HttpURLConnection) new URL(iUrl).openConnection();
      conn.setDoInput(true);
      conn.setRequestProperty("Connection", "Keep-Alive");
      conn.connect();
      buf_stream = new BufferedInputStream(conn.getInputStream(), 8192);
      bitmap = BitmapFactory.decodeStream(buf_stream);
      buf_stream.close();
      conn.disconnect();
      buf_stream = null;
      conn = null;
    } catch (MalformedURLException ex) {
      Log.e(TAG, "Url parsing was failed: " + iUrl);
    } catch (IOException ex) {
      Log.d(TAG, iUrl + " does not exists");
    } catch (OutOfMemoryError e) {
      Log.w(TAG, "Out of memory!!!");
      return null;
    } finally {
      if ( buf_stream != null )
        try { buf_stream.close(); } catch (IOException ex) {}
      if ( conn != null )
        conn.disconnect();
    }
    return bitmap;
  }
}
Вот лог:

Код: Выделить всё

01-08 09:30:01.230: D/SThemeManager(7987): Load theme icons for theme
01-08 09:30:01.260: D/dalvikvm(7987): GC_FOR_ALLOC freed 1511K, 18% free 11610K/14156K, paused 16ms, total 16ms
01-08 09:30:01.260: I/dalvikvm-heap(7987): Grow heap (frag case) to 13.418MB for 1127536-byte allocation
01-08 09:30:01.275: D/dalvikvm(7987): GC_FOR_ALLOC freed 0K, 11% free 12711K/14156K, paused 14ms, total 14ms
01-08 09:30:01.290: D/AbsListView(7987): Get MotionRecognitionManager
01-08 09:30:01.320: D/AbsListView(7987): Get MotionRecognitionManager
01-08 09:30:01.895: D/MyLog(7987): data.size();  *** 31
01-08 09:30:01.895: D/AbsListView(7987): onVisibilityChanged() is called, visibility : 4
01-08 09:30:01.895: D/AbsListView(7987): unregisterIRListener() is called 
01-08 09:30:01.895: D/AbsListView(7987): onVisibilityChanged() is called, visibility : 4
01-08 09:30:01.895: D/AbsListView(7987): unregisterIRListener() is called 
01-08 09:30:01.900: D/AbsListView(7987): onVisibilityChanged() is called, visibility : 0
01-08 09:30:01.900: D/AbsListView(7987): unregisterIRListener() is called 
01-08 09:30:01.900: D/AbsListView(7987): onVisibilityChanged() is called, visibility : 0
01-08 09:30:01.900: D/AbsListView(7987): unregisterIRListener() is called 
01-08 09:30:01.915: V/ImageManager(7987): Starting loading image by URL: http://192.168.0.20/content/apps/1843/icon/icon_mini_230_1382955953.webp
01-08 09:30:01.920: V/ImageManager(7987): Starting loading image by URL: http://192.168.0.20/content/apps/1843/icon/icon_mini_230_1382955953.webp
01-08 09:30:02.050: D/dalvikvm(7987): GC_FOR_ALLOC freed 468K, 11% free 13106K/14616K, paused 23ms, total 23ms
01-08 09:30:02.075: A/libc(7987): Fatal signal 11 (SIGSEGV) at 0xed970f63 (code=1), thread 8035 (Thread-562)
Не пойму, в какую сторону копать чтоб избежать ошибки(