Autore Topic: problema con lo scroll che va a scatti nella GridView  (Letto 2041 volte)

Offline antony10

  • Nuovo arrivato
  • *
  • Post: 8
  • Respect: 0
    • Mostra profilo
problema con lo scroll che va a scatti nella GridView
« il: 26 Maggio 2010, 17:40:14 CEST »
0
Salve ragazzi!
Volevo chiedervi aiuto riguardo un pezzo di codice ke ho implementato per realizzare una galleria di immagini. Succede ke una volta ke faccio partire il tutto sull'emulatore, la griglia di immagini viene visualizzata correttamente, ma purtroppo nello scorrere la griglia va scatti. Ora posto il pezzo di codice ke io ritengo sia la causa del problema. Qualcuno mi può aiutare ad identificare l'errore?


 
Codice (Java): [Seleziona]
 public View getView(int position, View convertView, ViewGroup parent) {
            ImageView picturesView;
           
            if (convertView==null){
                picturesView = new ImageView(context);
                picturesView.setLayoutParams(new GridView.LayoutParams(85, 85));
                picturesView.setScaleType(ImageView.ScaleType.CENTER_CROP);
                picturesView.setPadding(8, 8, 8, 8);
            }
              else picturesView=(ImageView)convertView;
               
                cursor.moveToPosition(position);  
                int imageID = cursor.getInt(columnIndex);
                picturesView.setImageURI(ContentUris.withAppendedId(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,imageID));
               
                   
                return picturesView;
               
           
        }
    }
}

Offline dodopepper

  • Utente junior
  • **
  • Post: 124
  • Respect: +4
    • Mostra profilo
  • Dispositivo Android:
    HTC Magic 32a black
Re:problema con lo scroll che va a scatti nella GridView
« Risposta #1 il: 26 Maggio 2010, 23:42:47 CEST »
0
Antò ho rivisto il codice, secondo me la parte problematica non sta tanto nella getView quanto piuttosto nel come gestiamo la query. Ragazzi vi posto il codice intero nella speranza che ci possiate dare una mano.
Codice (Java): [Seleziona]
 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.maingalleria);
       
       
       
        String  []projection={MediaStore.Images.Thumbnails._ID};
       
        cursor=managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,projection,null,null,MediaStore.Images.Thumbnails._ID);
        columnIndex=cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID);
       
        GridView sdCard=(GridView)findViewById(R.id.GridView01);
        sdCard.setAdapter(new ImageAdapter(this));
       
        sdCard.setOnItemClickListener(new OnItemClickListener() {
                public void onItemClick(AdapterView parent,View v,int position,long id) {
                                String []projection={MediaStore.Images.Thumbnails.DATA};
                                cursor=managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,projection,null,null,null);
                       
                                columnIndex=cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.DATA);
                                cursor.moveToPosition(position);
                               
                                }
               
                });
    }
   
    private class ImageAdapter extends BaseAdapter {

        private Context context;

        public ImageAdapter(Context localContext) {
            context = localContext;
        }

        public int getCount() {
            return cursor.getCount();
        }
        public Object getItem(int position) {
            return position;
        }
        public long getItemId(int position) {
            return position;
        }
        public View getView(int position, View convertView, ViewGroup parent) {
            ImageView picturesView=(ImageView)convertView;
            if (convertView == null) {
                picturesView = new ImageView(context);
                picturesView.setLayoutParams(new GridView.LayoutParams(85, 85));
                picturesView.setScaleType(ImageView.ScaleType.CENTER_CROP);
                picturesView.setPadding(8, 8, 8, 8);
                }
            else picturesView = (ImageView) convertView;
           
                cursor.moveToPosition(position);            
                int imageID = cursor.getInt(columnIndex);
                picturesView.setImageURI(ContentUris.withAppendedId(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,imageID));


            return picturesView;
        }
    }
}


Si potrebbe approfondire anche da qui
      [android-developers] Re: GridView ImageView and performance - msg#02375 - AndroidDevelopers      
oppure anche da qui Android Sample Codes: How to Display  Thumbnails of Images Stored in the SD Card dove usa la bitmapfactory citata nella precedente discussione. Bisogna analizzare a fondo il codice e capire i problemi
« Ultima modifica: 26 Maggio 2010, 23:52:10 CEST da dodopepper »

Offline Qlimax

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 757
  • Respect: +202
    • Google+
    • _Qlimax
    • Mostra profilo
    • www.egsolutions.ch
  • Dispositivo Android:
    Galaxy Nexus - Nexus One - Wildfire - Magic
  • Play Store ID:
    egsolutions.ch
  • Sistema operativo:
    Ubuntu 12.04, Windows 7
Re:problema con lo scroll che va a scatti nella GridView
« Risposta #2 il: 27 Maggio 2010, 15:57:29 CEST »
0
Ciao antony10 e dopopepper,

la lentezza di cui parlate è data dal fatto che ogni volta che dev'essere caricata una view: viene fatta una query, l'immagine viene caricata in memoria e successivamente viene fatto uno scaling per adattarsi alla ImageView.

Meglio magari caricare le immagini in memoria così da riempire la gridview (anche a runtime) senza "stressare" i content providers

ecco come:

Codice (Java): [Seleziona]
public class Demo extends Activity {
        Cursor idsCursor;
        int idIndex;
        GridView sdCardGv;
        ProgressBar progressBar;
        Bitmap[] bitmaps;

        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);      
                String  []projection={MediaStore.Images.Thumbnails._ID};      
                idsCursor=managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,projection,null,null,null);
                startManagingCursor(idsCursor);      
                idIndex=idsCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID);
                setUpViews();  
        }

        private void setUpViews(){
                setContentView(R.layout.main);
                progressBar=(ProgressBar)findViewById(R.id.ProgressBar01);
                sdCardGv=(GridView)findViewById(R.id.imagesGv);

                sdCardGv.setOnItemClickListener(new OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> parent,View v,int position,long id) {

                                idsCursor.moveToPosition(position);
                                Intent i=new Intent(Intent.ACTION_VIEW);
                                Uri uri=ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,idsCursor.getInt(idIndex));
                                i.setData(uri);
                                startActivity(i);

                        }

                });

                new LoadImages().execute((Void)null);

        }

        @Override
        public void onConfigurationChanged(Configuration newConfig) {
                setUpViews();
                super.onConfigurationChanged(newConfig);
        }

        private class LoadImages extends AsyncTask<Void, Integer, Void>{

                @Override
                protected void onPreExecute() {
                        progressBar.setVisibility(View.VISIBLE);
                        super.onPreExecute();
                }


                @Override
                protected Void doInBackground(Void... params) {
                        if(bitmaps==null){ // se non è null, inutile ricaricare tutto...
                                Options opts=new Options();
                                opts.inSampleSize=4; //evitiamo OutOfMemoryException
                                bitmaps=new Bitmap[idsCursor.getCount()];

                                if(idsCursor.moveToFirst()){
                                        do{

                                                try {
                                                        InputStream is = getContentResolver().openInputStream(ContentUris.withAppendedId(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,idsCursor.getInt(idIndex)));
                                                        bitmaps[idsCursor.getPosition()]=BitmapFactory.decodeStream(is, null, opts);
                                                } catch (FileNotFoundException e) {
                                                       
                                                        e.printStackTrace();
                                                }


                                        }while(idsCursor.moveToNext());
                                }
                        }
                        publishProgress(View.GONE);

                        return null;
                }

                @Override
                protected void onProgressUpdate(Integer... values) {
                        progressBar.setVisibility(values[0]);
                        super.onProgressUpdate(values);
                }
                @Override
                protected void onPostExecute(Void result) {
                        sdCardGv.setAdapter(new ImageAdapter(getApplicationContext()));
                        super.onPostExecute(result);
                }

        }

        private class ImageAdapter extends BaseAdapter {

                private Context context;
                public ImageAdapter(Context localContext) {
                        context = localContext;        
                }

                public int getCount() {
                        return idsCursor.getCount();
                }
                public Object getItem(int position) {
                        return position;
                }
                public long getItemId(int position) {
                        return position;
                }
                @Override
                public View getView(int position, View convertView, ViewGroup parent) {
                        ImageView picturesView;
                        if (convertView == null) {
                                picturesView = new ImageView(context);
                                picturesView.setLayoutParams(new GridView.LayoutParams(85, 85));
                                picturesView.setScaleType(ImageView.ScaleType.CENTER_CROP);
                                picturesView.setPadding(8, 8, 8, 8);
                        }else{
                                picturesView = (ImageView) convertView;
                        }

                        picturesView.setImageBitmap(bitmaps[position]);

                        return picturesView;
                }

        }
}

ho fatto anche in modo di non ricaricare tutto quando si gira lo schermo, come descritto al punto 2. di questo tutorial : http://www.anddev.it/index.php/topic,123.0.html
ed ho usato un asynctask per caricare le immagini, di modo da non bloccare la UI, come descritto in questo tutorial : http://www.anddev.it/index.php/topic,29.0.html

Sul mio nexus scorre che è una favola :D
vi allego anche uno zip del progetto O:-)

Saluti.
Qlimax

Offline dodopepper

  • Utente junior
  • **
  • Post: 124
  • Respect: +4
    • Mostra profilo
  • Dispositivo Android:
    HTC Magic 32a black
Re:problema con lo scroll che va a scatti nella GridView
« Risposta #3 il: 27 Maggio 2010, 17:48:38 CEST »
0
Dire  che sei un mito è dir poco, avevo intuito la ragione del problema, il difficile era risolverlo :D Senti ma da dove studi queste cose approfondite? Io sto studiando dal libro di Carli ma tratta argomenti basilari e ad esempio degli AsyncTask non parla proprio infatti ogni volta che ho da aggiornare la UI ho necessità di usare handler...ora con l'async task penso di poter semplificare di molto le cose!

Offline antony10

  • Nuovo arrivato
  • *
  • Post: 8
  • Respect: 0
    • Mostra profilo
Re:problema con lo scroll che va a scatti nella GridView
« Risposta #4 il: 27 Maggio 2010, 18:59:53 CEST »
0
grazie mille!! sei stato davvero gentilissimo e di grandissimo aiuto!! ;-)

Offline Qlimax

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 757
  • Respect: +202
    • Google+
    • _Qlimax
    • Mostra profilo
    • www.egsolutions.ch
  • Dispositivo Android:
    Galaxy Nexus - Nexus One - Wildfire - Magic
  • Play Store ID:
    egsolutions.ch
  • Sistema operativo:
    Ubuntu 12.04, Windows 7
Re:problema con lo scroll che va a scatti nella GridView
« Risposta #5 il: 02 Giugno 2010, 20:45:28 CEST »
0
Dire  che sei un mito è dir poco, avevo intuito la ragione del problema, il difficile era risolverlo :D Senti ma da dove studi queste cose approfondite? Io sto studiando dal libro di Carli ma tratta argomenti basilari e ad esempio degli AsyncTask non parla proprio infatti ogni volta che ho da aggiornare la UI ho necessità di usare handler...ora con l'async task penso di poter semplificare di molto le cose!
uh... mito esageriamo...
diciamo che queste cose le ho imparate col tempo e con la necessità di usarle . leggendo vari blog (fino a poco tempo fa quello ufficiale di android era molto tecnico), cercando su google :P e da alcuni mesi mi son comprato un libro che devo dire è veramente approfondito (Amazon.com: Professional Android 2 Application Development (Wrox…) scritto da un ingegnere(reto meier) che lavora alla google. poi una cosa fondamentale è l'interesse e la passione per java/android; quando hai questo riesci a scavare dappertutto per trovare le informazioni.
« Ultima modifica: 05 Giugno 2010, 09:51:32 CEST da Qlimax »

Offline dodopepper

  • Utente junior
  • **
  • Post: 124
  • Respect: +4
    • Mostra profilo
  • Dispositivo Android:
    HTC Magic 32a black
Re:problema con lo scroll che va a scatti nella GridView
« Risposta #6 il: 02 Giugno 2010, 20:53:54 CEST »
0
Avevo sentito parlare di quel libro infatti avevo già fatto un giretto su amazon...sono troppo tentato di comprarlo, il libro di carli è ottimo ma tante cose non sono trattate e altre sono trattate in modo superficiale tanto che trovo più chiara la documentazione online.
Mi sei stato davvero di ispirazione tanto che ho modificato anche un pochino l'activity che fa da galleria, ho aggiunto una nuova query che prende il geotag della foto quando la seleziono a schermo dato che la mando ad una mia activity per l'applicazione che stiamo facendo. Poi ho aggiunto anche un ProgressDialog orizzontale che mostra il progresso indicando sia il numero di foto totali e quelle caricate con annessa percentuale. L'asyncTask è davvero comodissimo per queste cose. Che dire spero di poter dare una mano anche io quanto prima possibile ( e spero di portare a compimento anche l'applicazione "etilometro" per cui JD è stato di grande aiuto, appena mi libero un po' dagli impegni universitari la completo).