Bonjour Je suis confronté à un problème particulier dans lequel je dois télécharger des images et les afficher sur une ListView
correspondant à leur TextView's
particulier. Le code que j'ai est en train d’afficher avec succès le TextView's
que j’ai besoin d’afficher, mais je ne sais pas comment afficher toutes ces images à côté de mes vues de texte dans ma ListView
.
Après avoir traversé de nombreuses discussions dans SO. Les réponses les plus fréquentes sont de résoudre ce problème en 1. Liste paresseuse 2. Chargeur d'image universel
J'ai passé en revue les deux solutions. J'ai téléchargé des codes Lazy List dans lesquels les URL sont des chaînes codées en dur stockées dans un tableau. Ce que je voudrais faire, c'est créer mes propres chaînes de manière dynamique. Stockez-les dans la mémoire cache et affichez toutes les images correspondantes.
Voici mon code:
public class Tools_ListItemActivity extends ListActivity
{
private Context context;
String s;
private static final String TAG_POSTS = "posts";
private static final String TAG_MDNAME = "mdname";
private static final String TAG_UTCOST = "utcost";
private static final String TAG_IIMG= "iimg";
JSONArray posts = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
s=getIntent().getExtras().getString("url");
new ProgressTask(Tools_ListItemActivity.this).execute();
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
}
ArrayList<HashMap<String, String>> jsonlist = new ArrayList<HashMap<String, String>>();
ListView lv ;
private class ProgressTask extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog;
public ProgressTask(ListActivity activity) {
Log.i("1", "Called");
context = activity;
dialog = new ProgressDialog(context);
}
/** progress dialog to show user that the backup is processing. */
/** application context. */
private Context context;
protected void onPreExecute() {
this.dialog.setMessage("Progress start");
this.dialog.show();
}
@Override
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
ListAdapter adapter = new SimpleAdapter(context, jsonlist,
R.layout.activity_toolsitem, new String[] { TAG_IIMG, TAG_MDNAME, TAG_UTCOST }, new int[] {
R.id.imageViewUrl, R.id.mdname, R.id.utcost });
setListAdapter(adapter);
// selecting single ListView item
lv = getListView();
}
protected Boolean doInBackground(final String... args) {
JSONParser jParser = new JSONParser();
// getting JSON string from URL
JSONObject json = jParser.getJSONFromUrl(s);
try {
posts = json.getJSONArray(TAG_POSTS);
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try
{
// looping through All Contacts
for(int i = 0; i < posts.length(); i++){
JSONObject c = posts.getJSONObject(i);
// Storing each json item in variable
String mdname = c.getString(TAG_MDNAME);
String utcost= c.getString(TAG_UTCOST);
String iimg=c.getString(TAG_IIMG);
//Forming the Url of the image to be shown in the list view
String imageUrl="My_App_URL"+iimg;
/* try {
String imageUrl="My_App_URL"+iimg;
ImageView imageView = (ImageView)findViewById(R.id.imageViewUrl);
Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(imageUrl).getContent());
imageView.setImageBitmap(bitmap);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} */
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_MDNAME, mdname);
map.put(TAG_UTCOST, utcost);
map.put(TAG_IIMG, iimg);
jsonlist.add(map);
} }catch (JSONException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
}
Ici, j'ai débogué et découvert que imageUrl
est formé correctement. Json
renvoie uniquement le nom de la jpg
, donc je l’ajoute à l’URL et je l’enregistre dans imageUrl
. Les deux autres vues textuelles sont correctement analysées et affichées. Si quelqu'un peut m'aider à afficher les images dans la vue d'image aussi, ce serait formidable. Merci.
Mise à jour: J'ai pu résoudre mon problème particulier avec l'aide du lien partagé par Pankaj ( https://github.com/AndroidBegin/Android-JSON-Parse-Images-and-Texts -Tutorial ) et la connaissance conceptuelle partagée par Raghunandan ci-dessous. Veuillez parcourir ces réponses pour une explication détaillée ainsi que la mise en œuvre du chargement paresseux. Je m'excuse de ne pas pouvoir récompenser une réponse par une prime, car j'étais absent pendant deux jours.
Chargement paresseux avec Universal Imageloader. Remplacez les URL codées en dur par des URL d’images.
Modifiez le ci-dessous en fonction de vos besoins
Qu'est-ce que LazyList? . Vérifiez ce lien pour plus de détails.
public class MainActivity extends Activity {
private String[] mStrings={
"http://a3.twimg.com/profile_images/670625317/aam-logo-v3-Twitter.png",
"http://a3.twimg.com/profile_images/740897825/AndroidCast-350_normal.png",
"http://a3.twimg.com/profile_images/121630227/Droid_normal.jpg",
"http://a1.twimg.com/profile_images/957149154/twitterhalf_normal.jpg",
"http://a1.twimg.com/profile_images/97470808/icon_normal.png",
"http://a3.twimg.com/profile_images/511790713/AG.png",
"http://a3.twimg.com/profile_images/956404323/androinica-avatar_normal.png",
"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",
"http://a3.twimg.com/profile_images/72774055/AndroidHomme-LOGO_normal.jpg",
"http://a1.twimg.com/profile_images/349012784/Android_logo_small_normal.jpg",
"http://a1.twimg.com/profile_images/841338368/ea-Twitter-icon.png",
"http://a3.twimg.com/profile_images/64827025/Android-wallpaper6_2560x160_normal.png",
"http://a3.twimg.com/profile_images/77641093/AndroidPlanet_normal.png",
"http://a1.twimg.com/profile_images/605536070/twitterProfilePhoto_normal.jpg",
"http://a1.twimg.com/profile_images/850960042/elandroidelibre-logo_300x300_normal.jpg",
"http://a1.twimg.com/profile_images/655119538/andbook.png",
"http://a3.twimg.com/profile_images/768060227/ap4u_normal.jpg",
"http://a1.twimg.com/profile_images/74724754/Android_logo_normal.png",
"http://a3.twimg.com/profile_images/681537837/SmallAvatarx150_normal.png",
"http://a1.twimg.com/profile_images/63737974/2008-11-06_1637_normal.png",
"http://a3.twimg.com/profile_images/548410609/icon_8_73.png",
"http://a1.twimg.com/profile_images/612232882/nexusoneavatar_normal.jpg",
"http://a1.twimg.com/profile_images/213722080/Bugdroid-phone_normal.png",
"http://a1.twimg.com/profile_images/645523828/OT_icon_090918_Android_normal.png",
"http://a3.twimg.com/profile_images/64827025/Android-wallpaper6_2560x160_normal.png",
"http://a3.twimg.com/profile_images/77641093/AndroidPlanet.png",
"http://a1.twimg.com/profile_images/605536070/twitterProfilePhoto_normal.jpg",
"http://a1.twimg.com/profile_images/850960042/elandroidelibre-logo_300x300_normal.jpg",
"http://a1.twimg.com/profile_images/655119538/andbook_normal.png",
"http://a3.twimg.com/profile_images/511790713/AG_normal.png",
"http://a3.twimg.com/profile_images/956404323/androinica-avatar.png",
"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",
"http://a3.twimg.com/profile_images/72774055/AndroidHomme-LOGO_normal.jpg",
"http://a1.twimg.com/profile_images/349012784/Android_logo_small_normal.jpg",
"http://a1.twimg.com/profile_images/841338368/ea-Twitter-icon_normal.png",
"http://a3.twimg.com/profile_images/64827025/Android-wallpaper6_2560x160_normal.png",
"http://a3.twimg.com/profile_images/77641093/AndroidPlanet.png",
"http://a1.twimg.com/profile_images/605536070/twitterProfilePhoto_normal.jpg",
"http://a3.twimg.com/profile_images/64827025/Android-wallpaper6_2560x160_normal.png",
"http://a3.twimg.com/profile_images/77641093/AndroidPlanet_normal.png",
"http://a1.twimg.com/profile_images/605536070/twitterProfilePhoto_normal.jpg",
"http://a1.twimg.com/profile_images/850960042/elandroidelibre-logo_300x300.jpg",
"http://a1.twimg.com/profile_images/655119538/andbook_normal.png",
"http://a3.twimg.com/profile_images/511790713/AG_normal.png",
"http://a3.twimg.com/profile_images/956404323/androinica-avatar_normal.png",
"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",
"http://a3.twimg.com/profile_images/121630227/Droid.jpg",
"http://a1.twimg.com/profile_images/957149154/twitterhalf_normal.jpg",
"http://a1.twimg.com/profile_images/97470808/icon_normal.png",
"http://a3.twimg.com/profile_images/511790713/AG_normal.png",
"http://a3.twimg.com/profile_images/956404323/androinica-avatar_normal.png",
"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man.png",
"http://a3.twimg.com/profile_images/72774055/AndroidHomme-LOGO_normal.jpg",
"http://a1.twimg.com/profile_images/349012784/Android_logo_small_normal.jpg",
"http://a1.twimg.com/profile_images/841338368/ea-Twitter-icon_normal.png",
"http://a3.twimg.com/profile_images/64827025/Android-wallpaper6_2560x160_normal.png",
"http://a3.twimg.com/profile_images/77641093/AndroidPlanet.png",
"http://a3.twimg.com/profile_images/670625317/aam-logo-v3-Twitter_normal.png",
"http://a3.twimg.com/profile_images/740897825/AndroidCast-350_normal.png",
"http://a3.twimg.com/profile_images/121630227/Droid_normal.jpg",
"http://a1.twimg.com/profile_images/957149154/twitterhalf_normal.jpg",
"http://a1.twimg.com/profile_images/97470808/icon.png",
"http://a3.twimg.com/profile_images/511790713/AG_normal.png",
"http://a3.twimg.com/profile_images/956404323/androinica-avatar_normal.png",
"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",
"http://a3.twimg.com/profile_images/72774055/AndroidHomme-LOGO_normal.jpg",
"http://a1.twimg.com/profile_images/349012784/Android_logo_small_normal.jpg",
"http://a1.twimg.com/profile_images/841338368/ea-Twitter-icon.png",
"http://a3.twimg.com/profile_images/64827025/Android-wallpaper6_2560x160_normal.png",
"http://a3.twimg.com/profile_images/77641093/AndroidPlanet_normal.png",
"http://a1.twimg.com/profile_images/605536070/twitterProfilePhoto_normal.jpg",
"http://a1.twimg.com/profile_images/850960042/elandroidelibre-logo_300x300_normal.jpg",
"http://a1.twimg.com/profile_images/655119538/andbook_normal.png",
"http://a3.twimg.com/profile_images/768060227/ap4u_normal.jpg",
"http://a1.twimg.com/profile_images/74724754/Android_logo.png",
"http://a3.twimg.com/profile_images/681537837/SmallAvatarx150_normal.png",
"http://a1.twimg.com/profile_images/63737974/2008-11-06_1637_normal.png",
"http://a3.twimg.com/profile_images/548410609/icon_8_73_normal.png",
"http://a1.twimg.com/profile_images/612232882/nexusoneavatar_normal.jpg",
"http://a1.twimg.com/profile_images/213722080/Bugdroid-phone_normal.png",
"http://a1.twimg.com/profile_images/645523828/OT_icon_090918_Android.png",
"http://a3.twimg.com/profile_images/64827025/Android-wallpaper6_2560x160_normal.png",
"http://a3.twimg.com/profile_images/77641093/AndroidPlanet_normal.png",
"http://a1.twimg.com/profile_images/605536070/twitterProfilePhoto_normal.jpg",
"http://a1.twimg.com/profile_images/850960042/elandroidelibre-logo_300x300_normal.jpg",
"http://a1.twimg.com/profile_images/655119538/andbook.png",
"http://a3.twimg.com/profile_images/511790713/AG_normal.png",
"http://a3.twimg.com/profile_images/956404323/androinica-avatar_normal.png",
"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",
"http://a3.twimg.com/profile_images/72774055/AndroidHomme-LOGO_normal.jpg",
"http://a1.twimg.com/profile_images/349012784/Android_logo_small_normal.jpg",
"http://a1.twimg.com/profile_images/841338368/ea-Twitter-icon.png",
"http://a3.twimg.com/profile_images/64827025/Android-wallpaper6_2560x160_normal.png",
"http://a3.twimg.com/profile_images/77641093/AndroidPlanet_normal.png",
"http://a1.twimg.com/profile_images/605536070/twitterProfilePhoto_normal.jpg",
"http://a3.twimg.com/profile_images/64827025/Android-wallpaper6_2560x160_normal.png",
"http://a3.twimg.com/profile_images/77641093/AndroidPlanet_normal.png",
"http://a1.twimg.com/profile_images/605536070/twitterProfilePhoto.jpg",
"http://a1.twimg.com/profile_images/850960042/elandroidelibre-logo_300x300_normal.jpg",
"http://a1.twimg.com/profile_images/655119538/andbook_normal.png",
"http://a3.twimg.com/profile_images/511790713/AG_normal.png",
"http://a3.twimg.com/profile_images/956404323/androinica-avatar_normal.png",
"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",
"http://a3.twimg.com/profile_images/121630227/Droid_normal.jpg",
"http://a1.twimg.com/profile_images/957149154/twitterhalf.jpg",
"http://a1.twimg.com/profile_images/97470808/icon_normal.png",
"http://a3.twimg.com/profile_images/511790713/AG_normal.png",
"http://a3.twimg.com/profile_images/956404323/androinica-avatar_normal.png",
"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",
"http://a3.twimg.com/profile_images/72774055/AndroidHomme-LOGO_normal.jpg",
"http://a1.twimg.com/profile_images/349012784/Android_logo_small.jpg",
"http://a1.twimg.com/profile_images/841338368/ea-Twitter-icon_normal.png",
"http://a3.twimg.com/profile_images/64827025/Android-wallpaper6_2560x160_normal.png",
"http://a3.twimg.com/profile_images/77641093/AndroidPlanet_normal.png"
};
ListView lv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv= (ListView) findViewById(R.id.lv);
lv.setAdapter(new LazyAdapter(this,mStrings));
}
}
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:tools="http://schemas.Android.com/tools"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:paddingBottom="@dimen/activity_vertical_margin"
Android:paddingLeft="@dimen/activity_horizontal_margin"
Android:paddingRight="@dimen/activity_horizontal_margin"
Android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<ListView
Android:id="@+id/lv"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:background="#000000"
Android:focusableInTouchMode="false"
Android:listSelector="@Android:color/transparent"
Android:layout_weight="2.0"
Android:divider="#000000"
Android:headerDividersEnabled="false"
Android:footerDividersEnabled="false"
Android:dividerHeight="8dp"
Android:drawSelectorOnTop="false"
/>
</RelativeLayout>
public class LazyAdapter extends BaseAdapter {
private Activity activity;
private String data[];
private LayoutInflater inflater=null;
public ImageLoader imageLoader;
DisplayImageOptions options;
public LazyAdapter(Activity a, String[] d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
File cacheDir = StorageUtils.getOwnCacheDirectory(a, "MyFolderCache");
// Get singletone instance of ImageLoader
imageLoader = ImageLoader.getInstance();
// Create configuration for ImageLoader (all options are optional)
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(a)
// You can pass your own memory cache implementation
.discCacheExtraOptions(1024, 1024, CompressFormat.PNG, 100)
.discCache(new UnlimitedDiscCache(cacheDir)) // You can pass your own disc cache implementation
.discCacheFileNameGenerator(new HashCodeFileNameGenerator())
.enableLogging()
.build();
// Initialize ImageLoader with created configuration. Do it once.
imageLoader.init(config);
//imageLoader.init(ImageLoaderConfiguration.createDefault(a));
// imageLoader=new ImageLoader(activity.getApplicationContext());
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.ic_launcher)
.cacheInMemory()
.cacheOnDisc()
.displayer(new RoundedBitmapDisplayer(20))
.build();
}
public int getCount() {
return data.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
ViewHolder vh = new ViewHolder();;
if(convertView==null)
{
vi = inflater.inflate(R.layout.row, null);
vh.iv=(ImageView)vi.findViewById(R.id.ivv);
vh.pb= (ProgressBar)vi.findViewById(R.id.pb);
vh.tv = (TextView) vi.findViewById(R.id.textView1);
vh.tv1= (TextView) vi.findViewById(R.id.textView2);
}
vh.tv.setText("Image in postion =");
vh.tv1.setText(""+position);
display(vh.iv, data[position], vh.pb);
//imageLoader.displayImage(data.get(position).toString(), image,options);
return vi;
}
public void display(ImageView img, String url, final ProgressBar spinner)
{
imageLoader.displayImage(url, img, options, new ImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
spinner.setVisibility(View.VISIBLE);
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
spinner.setVisibility(View.GONE);
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
spinner.setVisibility(View.GONE);
}
@Override
public void onLoadingCancelled(String imageUri, View view) {
}
});
}
public static class ViewHolder
{
ImageView iv;
TextView tv,tv1;
ProgressBar pb;
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical" >
<ImageView
Android:id="@+id/imageView1"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_centerHorizontal="true"
Android:layout_centerVertical="true"
Android:src="@drawable/ic_launcher" />
<ProgressBar
Android:id="@+id/pb"
Android:layout_centerInParent="true"
Android:layout_gravity="center"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"/>
<TextView
Android:id="@+id/textView1"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_above="@+id/textView2"
Android:layout_alignParentLeft="true"
Android:layout_marginBottom="21dp"
Android:layout_marginLeft="31dp"
Android:text="TextView" />
<TextView
Android:id="@+id/textView2"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_alignLeft="@+id/textView1"
Android:layout_alignParentBottom="true"
Android:text="TextView" />
</RelativeLayout>
Ajouter une autorisation dans le manifeste
<uses-permission Android:name="Android.permission.INTERNET"/>
Essayez ceci avec le chargeur d'images universel
public class DetailsListViewAdapter extends ArrayAdapter<Entry>{
private Context context;
private List<Entry> detailList;
DisplayImageOptions options;
public ImageLoader imageLoader;
public DetailsListViewAdapter(Context context, int textViewResourceId,List<Entry> detailList) {
super(context, textViewResourceId,detailList);
this.detailList = detailList;
this.context = context;
imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(context));
options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.blankimage)
.showImageOnFail(R.drawable.blankimage)
.resetViewBeforeLoading()
.cacheOnDisc()
.imageScaleType(ImageScaleType.IN_SAMPLE_INT)
.bitmapConfig(Bitmap.Config.RGB_565)
.displayer(new FadeInBitmapDisplayer(300))
.build();
}
static class ViewHolder{
private TextView popupDetails;
private TextView pubDate;
private ImageView image;
private ProgressBar progress;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
ViewHolder holder;
if (v == null) {
LayoutInflater vi = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.details_list_item, null);
holder = new ViewHolder();
holder.popupDetails=(TextView)v.findViewById(R.id.detailHeading);
holder.pubDate = (TextView)v.findViewById(R.id.pubDate);
holder.image = (ImageView)v.findViewById(R.id.listImg);
holder.progress = (ProgressBar)v.findViewById(R.id.progressBar);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
Entry value = detailList.get(position);
holder.popupDetails.setText(value.getTitle());
holder.pubDate.setText(value.getPubDate());
String url = value.getImageLink();
try {
if(url.length() > 5) {
holder.image.setVisibility(View.VISIBLE);
loadImage(holder.image,url,holder.progress);
} else {
if(url.equals("NO")) {
holder.image.setVisibility(View.INVISIBLE);
} else {
holder.image.setVisibility(View.GONE);
}
}
} catch (Exception e) {
Logger.show(e);
}
v.setBackgroundColor(Color.WHITE);
return v;
}
public void loadImage(ImageView imageView, String loadURL,final ProgressBar progress) {
imageLoader.displayImage(loadURL, imageView, options, new SimpleImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
progress.setVisibility(View.VISIBLE);
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
String message = null;
switch (failReason) {
case IO_ERROR:
message = "Input/Output error";
break;
case OUT_OF_MEMORY:
message = "Out Of Memory error";
break;
case NETWORK_DENIED:
message = "Downloads are denied";
break;
case UNSUPPORTED_URI_SCHEME:
message = "Unsupported URI scheme";
break;
case UNKNOWN:
message = "Unknown error";
break;
}
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
@Override
public void onLoadingComplete(final String imageUri, View view, final Bitmap loadedImage) {
progress.setVisibility(View.INVISIBLE);
}
});
}
}
Voici comment je charge et met en cache des images dans une ListView
qui crée une liste de contacts pour l'utilisateur. Alors imaginez une image de profil sur la gauche, quelques vues de texte sur la droite (ce qui semble proche du problème que vous rencontrez. Ignorez les tags de débogage laids et probablement un formatage médiocre (désolé). Je suppose que cela ressemble à LazyList mais une explication détaillée au cas où quelqu'un serait confus.
Étape 1: Configurez votre cache
private LruCache<String, Bitmap> memoryCache;
private HashMap<String, String> idPairs = new HashMap<String, String>();
Dans mon approche, j'utilise une LruCache
et une HashMap
pour suivre les images d'utilisateur que j'ai téléchargées. Vous verrez comment sa mise en œuvre plus tard, mais l'idée est d'éviter de télécharger des choses à partir du serveur sauf si vous devez le faire. Ensuite, dans votre onCreate()
ou une méthode associée, initialisez votre cache.
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
memoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap){
return (bitmap.getRowBytes() * bitmap.getHeight()) / 1024; //don't use getByteCount for API < 12
}
};
Ma prochaine étape consiste à ajouter le bitmap "image vide" par défaut au cache au cas où j'aurais atteint une entrée sans image associée. De cette façon, je n'ai qu'à traiter et ajouter ce bitmap une fois
Bitmap defaultPicture = BitmapFactory.decodeResource(getResources(), R.drawable.default_user_picture);
addBitmapToMemoryCache("default", defaultPicture);
Ensuite, il est temps d'obtenir les données dont vous avez besoin pour la liste!
Étape 2: Récupérer les données
private class GetPeopleData extends AsyncTask<JSONArray, Void, Void> {
@Override
protected Void doInBackground(JSONArray...lists) {
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost();
ResponseHandler <String> responseHandler = new BasicResponseHandler();
if(DEBUG) Log.d("GET PEOPLE DATA TASK", lists[0].length() + " users");
getUsers(lists[0], httpClient, httpPost, responseHandler);
return null;
}
@Override
protected void onPostExecute(Void result){
updateUserListView();
}
}
Voici une variable AsyncTask
qui prend comme argument une JSONArray
de données utilisateur. J'ai omis cette partie car il ne s'agit en fait que d'un téléchargement HTTP de base qui n'a pas besoin d'explication. La méthode getUsers est l'endroit où je commence à rassembler ce qui sera ajouté à ma ListView
. Ce que je fais ensuite est de traiter le fichier JSON téléchargé à partir du serveur pour créer des objets utilisateur qui seront ajoutés à la liste des utilisateurs à afficher.
private void getUsers(JSONArray userArray, HttpClient httpClient, HttpPost httpPost, ResponseHandler<String> responseHandler){
if(DEBUG) Log.d("USERS ARRAY", userArray.length() + " users");
try{
users = new ArrayList<User>();
if(DEBUG) Log.d("User Array -START", "" + users.size());
//Go through userArray and get information needed for list
for(int i = 0; i < userArray.length(); i++){
User u = new User();
if(DEBUG) Log.d("User Array - ADD USER", "" + users.size());
String profileId = userArray.getJSONObject(i).getString("profileid");
u.setId(userArray.getJSONObject(i).getString("id"));
u.setDisplayName(userArray.getJSONObject(i).getString("displayname"));
u.setStatus(userArray.getJSONObject(i).getString("status"));
//check HashMap for sender/profileid pair
if(idPairs.containsKey(profileId)){
if(DEBUG) Log.d("idPairs", "User in HashMap");
profileId = idPairs.get(profileId);
} else {
if(DEBUG) Log.d("idPairs", "User not in HashMap. Add profileId");
idPairs.put("profileId", profileId);
}
u.setProfilePicture(getProfilePictureFromCache(profileId, httpClient, httpPost, responseHandler)); //check cache for image
users.add(u);
if(DEBUG) Log.d("User info", u.toString());
}
} catch (Exception e) {
Log.e("BACKGROUND_PROC", e.getMessage());
}
}
J'associe l'image à l'objet utilisateur qui sera éventuellement affiché. Je suppose que ce n'est pas une perte de temps totale puisque l'image est extraite du cache bitmap
private Bitmap getProfilePictureFromCache(String profileId, HttpClient httpClient, HttpPost httpPost, ResponseHandler<String> responseHandler){
Bitmap defaultPicture = getBitmapFromMemCache("default");
Bitmap profilePicture = getBitmapFromMemCache(profileId);
if(profilePicture != null){
return profilePicture;
} else {
String pictureString = getProfilePic(profileId, httpClient, httpPost, responseHandler);
if(!pictureString.isEmpty()){
byte[] decodedString = Base64.decode(pictureString, Base64.DEFAULT);
profilePicture = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
addBitmapToMemoryCache(profileId, profilePicture);
if(DEBUG) Log.d("MEMCACHE", "Download and store picture for " + profileId);
return profilePicture;
} else if (defaultPicture != null && pictureString.equals(null)) {
if(DEBUG) Log.d("MEMCACHE", "Load default picture");
return defaultPicture;
}
}
return defaultPicture;
}
Si une image existe dans le cache, elle est renvoyée, sinon elle est téléchargée. Pour moi, lors de l'affichage des utilisateurs, chaque image est mise en cache en fonction de l'ID utilisateur. Même si une personne devait apparaître plusieurs fois dans la liste, une seule image serait stockée dans le cache pour cet utilisateur.
ImageView profile_picture = (ImageView) v.findViewById(R.id.profile_picture);
if(profile_picture != null){
profile_picture.setImageBitmap(u.getProfilePicture());
}
La seule chose qui reste à faire est de trouver la ImageView
dans votre adaptateur et de définir cette vue sur l'image que vous avez associée à l'objet dans votre liste.
Voulez-vous quelque chose de facile à utiliser? Avec s'occuper de la mise en cache des fichiers, la suppression du cache, libérer lorsque la mémoire est à la frontière?
Essayez LazyList, allez y:
https://github.com/nicolasjafelle/LazyList
Comme il est expliqué, il vous suffit de créer le Singleton dans votre classe Application ou dans toute autre activité ou fragment:
//To use the default external folder, this folder will be deleted when the app no longe exists.
ImageLoader.getInstance().init(getApplicationContext());
//Or to use another folder, use...
//ImageLoader.getInstance().init(getApplicationContext(), "MyExternalFolder");
Ensuite, dans votre vue qui contient ImageView pour afficher l'image, vous devez implémenter l'interface ImageProcessingCallback:
public class MyItemView extends LinearLayout implements ImageProcessingCallback {
...
//Do what you need in methods onImagePreProcessing() and onImageProcessing(Bitmap bitmap)
...
ImageLoader.getInstance().displayImage(data[position], myView);
Enfin, vous devez ajouter cette autorisation dans votre androidManifest.xml
<uses-permission Android:name="Android.permission.INTERNET"/>
<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/>
Et c'est tout. Vous disposez ensuite de méthodes pour effacer le cache pour le cache ram ou le cache de disque, ou les deux.
Je ne sais pas comment stocker les images, car mon application utilise des images de l'APK . Cependant, je crois que pour afficher ces images, vous souhaitez un Arrayadapter personnalisé.
Cela gonfle une mise en page pour chaque élément et le place dans une liste. Cette disposition est définie par une disposition XML que vous créez et spécifiez dans sa construction. Vous devriez essayer d'étendre l'adaptateur que vous utilisez actuellement pour votre affichage sous forme de liste avec un adaptateur personnalisé qui définit l'affichage d'image en fonction de l'élément.
Je le fais avec ImageView.setImageResource (ID de ressource); Mais votre kilométrage peut varier. J'ai mes images dans l'APK pas sûr de savoir comment les afficher à partir d'une source externe