Mit AsyncTask für das laden von Bildern in ListView
Ich habe eine ListView, die Platz für ein Bild. Es hängt davon ab, ob Bild existiert oder nicht, in SDCARD.
Hier mein Beispiel-code:
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/Beispiel/images' Verzeichnis die Bilder: 1.jpg, 2.jpg, 3.jpg, 4.jpg, 6.jpg, 7.jpg und 9.jpg.
das erwartete Ergebnis ist:
Aber, wenn ich durch die Liste scrollen, schnell, manche Bilder sind eingefügt in die falschen Artikel.
Es geschieht aufgrund der Nutzung der convertView in der getView () - Methode.
Wenn ich den folgenden code verwenden, der code funktioniert einwandfrei:
//if(convertView == null){
// view = mInflater.inflate(mResource, null);
//}else{
// view = convertView;
//}
view = mInflater.inflate(mResource, null);
Wenn die Liste gescrollt schnell, zwei asyncTasks können, die auf eine gleiche Ansicht, durch die Benutzung der convertView.
Wie Kann ich stornieren, AsyncTask, wenn der Blick nicht mehr sichtbar ist?(und useb durch ein anderes item der ListView)
Bearbeiten
@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);
}
}
InformationsquelleAutor der Frage Rodrigo | 2011-10-11
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie in der Bildansicht, um den task-Konstruktor und halten eine Referenz auf das Bild Weg. Jetzt im onPostExecute, prüfen, ob der aktuelle tag der Bildansicht ist die gleiche wie die, die Sie angefangen haben. Wenn ja, dann legen Sie das Bild. Wenn Nein, nichts tun.
Dies bedeutet jedoch, dass das Bild heruntergeladen, auf jeden Fall. Sie werden einfach nur nicht das falsche Bild auf der Ansicht.
EDIT:
Zunächst übergeben Sie die Bildansicht, um die Aufgabe Konstruktor:
Speichern Sie einen Verweis auf die Bildansicht und image-Pfad in der LoadImage-Konstruktor. Es ist wichtig, speichern Sie den Pfad im Konstruktor und nicht in der doInBackground, um sicherzustellen, dass wir don ' T run in multi-threading-Probleme. Dann an onPostExecute-wir überprüfen den aktuellen Pfad.
InformationsquelleAutor der Antwort shabyasachi
Diese Android-Entwickler-Blog-post wird Ihnen eine komplette Referenz-Projekt für dieses komplett mit caching. Ersetzen Sie einfach den Http-Zugriff-code, mit SD-Karte-Datei liest.
InformationsquelleAutor der Antwort Jeff Axelrod
Ich hoffe, das hilft.
Nach viel suchen habe ich diese funktionierende Lösung.
}
InformationsquelleAutor der Antwort Amit
Vielleicht solltest du mal versuchen:
Überprüfen dieses blog ist es, erklärt das ähnliche Problem:
http://www.doubleencore.com/2013/05/layout-inflation-as-intended/
InformationsquelleAutor der Antwort Munawwar Hussain Shelia
Was ich tun würde (es sei denn, Sie haben Tausende von Bildern):
1. erstellen Sie eine Daten-Struktur - eine einfache Klasse hält eine String name angezeigt werden und eine bitmap
2. erstellen Sie einen adapter für Sie
3. in der getView-Methode weisen Sie die richtige bitmap, um die korrekte Bildansicht.
In Ihrem Fall wenn Sie können eine ähnliche Daten-Struktur, aber hält nicht eine bitmap, aber einen AsyncTask. Wie auch immer Sie zu binden, müssen die asynctask, um die Zeichenfolge in eine Position. Ein array (oder arraylist) solche Gegenstände eingezogen werden, um den adapter. Angezeigt wird eine Bildansicht und eine textview.
AsyncTask kann abgebrochen werden, mit cancel().
InformationsquelleAutor der Antwort Yar
Hey, ich fand die Lösung für dieses problem benutzen Sie einfach folgenden Funktion, anstatt Ihre Funktion
Hier Liste ist das Objekt der listview. Geben Sie einfach Ihre Liste an view-Objekt an den adapter, und fügen Sie diese Funktion, anstatt Ihre onPostExecute-Funktion.
InformationsquelleAutor der Antwort Sandeep