À l'aide de AsyncTask pour charger les Images dans la ListView
J'ai une ListView qui peut contenir une image. Cela dépend si l'image existe ou pas dans SDCARD.
Voici mon code d'exemple:
public class MainActivity extends Activity {
ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mListView = new ListView(this);
setContentView(mListView);
String[] arr = new String[] {
"/example/images/1.jpg", "/example/images/2.jpg",
"/example/images/3.jpg", "/example/images/4.jpg",
"/example/images/5.jpg", "/example/images/6.jpg",
"/example/images/7.jpg", "/example/images/8.jpg",
"/example/images/9.jpg", "/example/images/1.jpg",
"/example/images/2.jpg", "/example/images/3.jpg",
"/example/images/4.jpg", "/example/images/5.jpg",
"/example/images/6.jpg", "/example/images/7.jpg",
"/example/images/8.jpg", "/example/images/9.jpg",
"/example/images/1.jpg", "/example/images/2.jpg",
"/example/images/3.jpg", "/example/images/4.jpg",
"/example/images/5.jpg", "/example/images/6.jpg",
"/example/images/7.jpg", "/example/images/8.jpg",
"/example/images/9.jpg", "/example/images/1.jpg",
"/example/images/2.jpg", "/example/images/3.jpg",
"/example/images/4.jpg", "/example/images/5.jpg",
"/example/images/6.jpg", "/example/images/7.jpg",
"/example/images/8.jpg", "/example/images/9.jpg"};
List<String> list = Arrays.asList(arr);
MyAdapter adapter = new MyAdapter(this, R.layout.listitem_imv, list);
mListView.setAdapter(adapter);
}
class MyAdapter extends ArrayAdapter<String>{
List<String> mList;
LayoutInflater mInflater;
int mResource;
public MyAdapter(Context context, int resource,
List<String> objects) {
super(context, resource, objects);
mResource = resource;
mInflater = getLayoutInflater();
mList = objects;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if(convertView == null){
view = mInflater.inflate(mResource, null);
}else{
view = convertView;
}
ImageView imageView = (ImageView) view.findViewById(R.id.imv);
TextView textView = (TextView) view.findViewById(R.id.txv);
imageView.setTag(mList.get(position));//tag of imageView == path to image
new LoadImage().execute(imageView);
textView.setText(mList.get(position).toString());
return view;
}
}
class LoadImage extends AsyncTask<Object, Void, Bitmap>{
private ImageView imv;
private String path;
@Override
protected Bitmap doInBackground(Object... params) {
imv = (ImageView) params[0];
path = imv.getTag().toString();
Bitmap bitmap = null;
File file = new File(
Environment.getExternalStorageDirectory().getAbsolutePath() + path);
if(file.exists()){
bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
if(result != null && imv != null){
imv.setVisibility(View.VISIBLE);
imv.setImageBitmap(result);
}else{
imv.setVisibility(View.GONE);
}
}
}
}
'Sdcard/exemple/les images d'un répertoire a les images: 1.jpg, 2.jpg, 3.jpg, 4.jpg, 6.jpg, 7.jpg et 9.jpg.
le résultat attendu est:
Mais, si j'ai faites défiler la liste rapidement, certaines images sont insérées dans les articles faux.
Il se produit en raison de l'utilisation de convertView dans getView ().
Si j'utilise le code suivant, le code fonctionne:
//if(convertView == null){
// view = mInflater.inflate(mResource, null);
//}else{
// view = convertView;
//}
view = mInflater.inflate(mResource, null);
Lorsque la liste défile rapidement, deux asyncTasks peut faire référence à un même point de Vue, en raison de l'utilisation de convertView.
Comment puis-je annuler AsyncTask lorsque la Vue n'est plus visible?(et est useb par un autre élément de la Liste)
modifier
@Override
protected void onPostExecute(Bitmap result) {
if(result != null && imv != null){
if(imv.getTag().equals(path)){
imv.setVisibility(View.VISIBLE);
imv.setImageBitmap(result);
}else{
imv.setVisibility(View.GONE);
}
}else{
imv.setVisibility(View.GONE);
}
}
OriginalL'auteur Rodrigo | 2011-10-11
Vous devez vous connecter pour publier un commentaire.
Vous pouvez envoyer en l'ImageView à la tâche de constructeur et de conserver une référence vers le chemin de l'image. Maintenant à onPostExecute, vérifier si la balise courante de l'ImageView est le même que celui que vous avez commencé avec. Si oui, puis régler l'image. Si non, ne pas faire n'importe quoi.
Toutefois, cela signifie que l'image sera téléchargée dans tous les cas. Vous aurez juste pas mis la mauvaise image de la vue.
EDIT:
Les premiers à passer à l'ImageView à la tâche constructeur:
Puis enregistrer une référence à la ImageView et le chemin de l'image dans LoadImage constructeur. Il est important d'enregistrer le chemin d'accès dans le constructeur et pas dans doInBackground afin de nous assurer de ne pas courir dans des problèmes de threading. Puis à onPostExecute nous vérifier le chemin d'accès actuel.
Veuillez voir mon edit. Espérons que cette aide.
Oui @Droider, mais regardez le post date.
cette solution n'est pas correct, je ne comprends pas les upvotes. La liste ne fonctionnent pas comme cela, il utilise toujours le même point de vue, les éléments de l'affichage du contenu, et lors du défilement, il utilise recyclé vues pour afficher les nouveaux éléments. Cette solution est FAUSSE.
Vérifiez le grand commentaire dans onPostExecute. Cette observation explique comment afficher le recyclage est manipulé.
OriginalL'auteur shabyasachi
Ce Les Développeurs Android post de Blog va vous donner la référence complète de ce projet complet avec mise en cache. Il suffit de remplacer le Http code d'accès avec carte SD lectures de fichier.
OriginalL'auteur Jeff Axelrod
J'espère que cette aide.
Après beaucoup de recherche j'ai cette solution de travail.
}
OriginalL'auteur Amit
Peut-être que vous devriez essayer:
Consultez ce blog, il explique la même question:
http://www.doubleencore.com/2013/05/layout-inflation-as-intended/
OriginalL'auteur Munawwar Hussain Shelia
Ce que je voudrais faire (sauf si vous avez des milliers d'images):
1. créer une structure de données - une classe simple contenant une Chaîne de caractères nom à afficher une image bitmap
2. créer un adaptateur pour elle
3. dans la méthode getView affecter la bonne image bitmap à la bonne ImageView.
Dans votre cas, si vous pouvez créer une structure de données similaires, mais qui détiennent un bitmap, mais une AsyncTask. De toute façon vous avez besoin de lier l'asynctask à la chaîne dans un seul élément. Un tableau (ou une liste de tableaux) de ces articles seront nourris à votre carte. Affiche sera une imageview et un textview.
AsyncTask peut être annulée à annuler().
OriginalL'auteur Yar
Hey j'ai trouvé la solution à ce problème simplement utiliser la fonction suivante à la place de votre fonction
Ici la liste est l'objet de la liste. Il suffit de passer votre vue de la liste d'objet à votre carte et collez cette fonction à la place de votre onPostExecute fonction.
OriginalL'auteur Sandeep