Riscrivere il codice che carica in una ImageView un'immagine scalata mediante InJustDecodeBounds, quindi farla elaborare nel contesto di un AsyncTask.
Riscrivo il codice che carica un'immagine scalata, scelta fra le immagini in memoria, in un ImageView:
public class MainActivity extends Activity { ImageView immagine; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); immagine=(ImageView)findViewById(R.id.imageView1); Intent intent=new Intent(); intent.setAction(Intent.ACTION_PICK); intent.setData(Uri.parse("content://media/external/images/media")); startActivityForResult(intent, 0); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ if(resultCode==RESULT_OK){ BitmapFactory.Options opzioni=new BitmapFactory.Options(); opzioni.inJustDecodeBounds=true; BitmapFactory.decodeFile(getPathFromUri(data.getData()),opzioni); int fattore=1; while(opzioni.outWidth/fattore>200 && opzioni.outHeight/fattore>200){ fattore*=2; } opzioni.inSampleSize=fattore; opzioni.inJustDecodeBounds=false; Bitmap bitmap=BitmapFactory.decodeFile(getPathFromUri(data.getData()),opzioni); immagine.setImageBitmap(bitmap); } } private String getPathFromUri(Uri uri){ Cursor cursor=getContentResolver().query(uri, null, null, null, null); cursor.moveToFirst(); int indice=cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); String s=cursor.getString(indice); return s; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }Bene: tutto il codice in rosso l'ho scritto a memoria, commettendo solo un errore di distrazione (una maiuscola al posto di una minuscola).
Adesso riaffrontiamo l'AsyncTask...
Come si estende AsyncTask?
Ecco: scrivo
private class asyncTask extends AsyncTask{ed Eclipse mi dà automaticamente l'indicazione di scrivere i metodi non implementati.
Li aggiungo automaticamente e ottengo questo:
private class asyncTask extends AsyncTask{ @Override protected Object doInBackground(Object... params) { // TODO Auto-generated method stub return null; } }ottengo il solo metodo Object doInBackground, che dovrebbe riferirsi all'attività da svolgere in modo asincrono, al di fuori dell'UI.
Quell'Object come tipo del metodo doInBackground e quell'Object riferito ai parametri dello stesso metodo mi ricordano qualcosa: quando ho usato AsyncTask in precedenza, se non usavo i Generics nella dichiarazione della classe ottenevo Object automaticamente.
Vado a rivedere il codice di quando ho usato questa classe in precedenza:
class MyAsync extends AsyncTask<String,Void,Bitmap>{ private WeakReference<ImageView> riferimento; public MyAsync(ImageView immagine){ riferimento=new WeakReference<ImageView>(immagine); } @Override protected Bitmap doInBackground(String... params) { BitmapFactory.Options opzioni=new BitmapFactory.Options(); opzioni.inJustDecodeBounds=true; BitmapFactory.decodeFile(params[0],opzioni); int imageHeight=opzioni.outHeight; int imageWidth=opzioni.outWidth; opzioni.inJustDecodeBounds=false; int altezza=imageHeight/2; int larghezza=imageWidth/2; int reqHeight=riferimento.get().getLayoutParams().height; int reqWidth=riferimento.get().getLayoutParams().width; int inSampleSize=1; while(altezza/inSampleSize>reqHeight || larghezza/inSampleSize>reqWidth){ inSampleSize*=2; } opzioni.inSampleSize=inSampleSize; Bitmap bmp=BitmapFactory.decodeFile(params[0],opzioni); return bmp; } @Override protected void onPostExecute(Bitmap bmp){ if(riferimento!=null && bmp!=null){ ImageView immagine=(ImageView)riferimento.get(); if(immagine!=null){ immagine.setImageBitmap(bmp); } } } }Ricordo che quello di mezzo era spesso impostato a Void. Il primo corrisponde al tipo dei parametri mentre il secondo corrisponde al tipo del metodo doInBackground.
Proviamo... il metodo dovrebbe restituire una Bitmap da inserire nell'immagine, mentre dovrebbe "ingoiare" una String che sarebbe il Path, quindi i generics dovrebbero essere <String, Void, Bitmap>, ossia prima quello che si deve dare in pasto al metodo doInBackground, quindi come ultimo il risultato dello stesso metodo.
Se metto questo, il tipo e i parametri del metodo dovrebbero generarmisi automaticamente con l'addizione automatica dei metodi non implementati:
private class asyncTask extends AsyncTask<String,Void,Bitmap>{ @Override protected Bitmap doInBackground(String... params) { // TODO Auto-generated method stub return null; } }Ottimo!
Poi nel corpo del metodo ho inserito tutto il codice per l'elaborazione dell'immagine scalata...
Su questo non ci sono problemi. Il metodo "ingoia" il Path dell'immagine e "sputa fuori" l'immagine scalata e impacchettata da mettere nell'ImageView.
C'è poi il metodo onPostExecute, che dovrebbe fare ciò che viene dopo l'attività eseguita fuori dalla UI.
Cosa fa questo metodo?
Ecco! Ottenuto il Path e restituita l'immagine, la deve mettere nell'ImageView.
E l'ImageView viene ricevuta in pasto dal costruttore.
@Override protected void onPostExecute(Bitmap bmp){ if(riferimento!=null && bmp!=null){ ImageView immagine=(ImageView)riferimento.get(); if(immagine!=null){ immagine.setImageBitmap(bmp); } } }Ecco.
Il costruttore ha "impacchettato" il controllo ImageView in una variabile.
Qui lo restituisce come metodo get() della variabile, per attaccarci la bitmap, dopo essersi assicurato che la bitmap esista e che la variabile non sia nulla e che l'oggetto restituito dalla variabile non sia nullo.
Quante paranoie!
Il costruttore prende come argomento l'ImageView.
Prima dichiara la variabile di tipo WeakReference.
private WeakReferenceIn effetti questa variabile è un po' particolare: va istanziata con il Generic del tipo ImageView, e quindi vi va conservata l'ImageView fornita come parametro.riferimento; public MyAsync(ImageView immagine){ riferimento=new WeakReference (immagine); }
A questo punto mi riscrivo tutto: ricomponiamo il mandala
public class MainActivity extends Activity { ImageView immagine; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); immagine=(ImageView)findViewById(R.id.imageView1); Intent intent=new Intent(); intent.setAction(Intent.ACTION_PICK); intent.setData(Uri.parse("content://media/external/images/media")); startActivityForResult(intent,0); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ if(resultCode==RESULT_OK){ asyncTask async=new asyncTask(immagine); async.execute(getPathFromUri(data.getData())); Log.d("uri",data.getData()+" "); } } private String getPathFromUri(Uri uri){ Cursor cursor=getContentResolver().query(uri, null, null, null, null); cursor.moveToFirst(); int index=cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); String s=cursor.getString(index); return s; } class asyncTask extends AsyncTaskScritto tutto il codice marcato. Piccolo errore di distrazione: un true al posto di un false, corretto il quale funziona perfettamente!!!{ WeakReference }riferimento; public asyncTask(ImageView i){ riferimento=new WeakReference (i); } @Override protected Bitmap doInBackground(String... params) { BitmapFactory.Options opzioni=new BitmapFactory.Options(); opzioni.inJustDecodeBounds=true; BitmapFactory.decodeFile(params[0],opzioni); int fattore=1; while(opzioni.outWidth/fattore>200 && opzioni.outHeight>200){ fattore*=2; } opzioni.inJustDecodeBounds=false; opzioni.inSampleSize=fattore; Bitmap bitmap=BitmapFactory.decodeFile(params[0],opzioni); return bitmap; } @Override protected void onPostExecute(Bitmap bitmap){ if(bitmap!=null && riferimento!=null){ if(bitmap!=null){ ImageView i=(ImageView)riferimento.get(); i.setImageBitmap(bitmap); } } }
Nessun commento:
Posta un commento