Buforowanie obrazów i wyświetlanie
Witam stoję przed konkretnym problemem, w którym muszę pobrać obrazy i wyświetlić je na ListView
odpowiadającej ich konkretnej TextView's
. Kod, który mam pomyślnie wyświetla TextView's
, który muszę wyświetlić, ale nie wiem, jak wyświetlić wszystkie te różne obrazy obok moich widoków tekstowych w moim ListView
.
Po przejściu przez wiele wątków w SO. Najważniejsze odpowiedzi to rozwiązać to przez 1. Leniwa Lista 2. Universal Image Loader
Przeszedłem przez oba rozwiązania. Pobrałem kody leniwej listy, w których adresy URL są zakodowanymi ciągami przechowywanymi w tablicy. Chciałbym dynamicznie tworzyć własne ciągi. Przechowuj je w pamięci podręcznej i wyświetl wszystkie odpowiednie obrazy.
Oto Mój kod:
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;
}
}
}
Tutaj debugowałem i dowiedziałem się, że imageUrl
powstaje poprawnie. Json
zwraca tylko nazwę jpg
, więc dołączam ją do adresu URL i przechowuję w imageUrl
. Pozostałe dwa widoki tekstu są odpowiednio przetwarzane i wyświetlane. Jeśli ktoś może mi pomóc w wyświetlaniu obrazów w widoku obrazu to byłoby świetnie. Dzięki.
Aktualizacja: Udało mi się rozwiązać mój konkretny problem za pomocą linku udostępnionego przez Pankaj ( https://github.com/AndroidBegin/Android-JSON-Parse-Images-and-Texts-Tutorial ) i wiedzy pojęciowej podzielonej przez Raghunandana poniżej. Proszę przejrzeć te odpowiedzi, aby uzyskać szczegółowe wyjaśnienie, a także implementację leniwego ładowania. My przepraszam, że nie byłem w stanie nagrodzić odpowiedzi bounty, ponieważ nie było mnie dwa dni.
5 answers
Leniwe ładowanie za pomocą uniwersalnego Imageloadera. Zastąp zakodowane na twardo adresy URL obrazków.
Zmodyfikuj poniższy tekst zgodnie z Twoimi wymaganiami
Co To jest LazyList?. Sprawdź ten link, aby uzyskać szczegóły.
Główna aktywność.java
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));
}
}
Activity_main.xml
<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>
LazyAdapter.java
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;
}
}
Wiersz.xml
<?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>
Dodaj uprawnienia w manifeście
<uses-permission android:name="android.permission.INTERNET"/>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:09
Proszę spróbować z universal image loader
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);
}
});
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-11 14:25:29
Oto jak Ładuję i buforuję obrazy w ListView
, który tworzy listę kontaktów dla użytkownika. Wyobraź sobie zdjęcie profilowe po lewej stronie, kilka widoków tekstowych po prawej stronie (co brzmi blisko problemu, z którym masz do czynienia. Zignoruj brzydkie znaczniki debugowania i prawdopodobnie słabe formatowanie (przepraszam). Myślę, że to trochę jak LazyList, ale tutaj jest szczegółowe wyjaśnienie na wypadek, gdyby ktoś był zdezorientowany.
Krok 1: Skonfiguruj Swoją Pamięć Podręczną
private LruCache<String, Bitmap> memoryCache;
private HashMap<String, String> idPairs = new HashMap<String, String>();
W moim podejściu używam LruCache
i HashMap
aby śledzić, które obrazy użytkownika pobrałem. Zobaczysz, jak jego zaimplementowane później, ale chodzi o to, aby uniknąć pobierania rzeczy z serwera, chyba że trzeba. Następnie w swojej onCreate()
lub innej powiązanej metodzie zainicjuj swoją pamięć podręczną.
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
}
};
Moim następnym krokiem jest dodanie domyślnej bitmapy "empty image" do pamięci podręcznej na wypadek, gdybym dotarł do wpisu, który nie ma powiązanego z nim obrazu. W ten sposób muszę tylko przetworzyć i dodać tę bitmapę raz
Bitmap defaultPicture = BitmapFactory.decodeResource(getResources(), R.drawable.default_user_picture);
addBitmapToMemoryCache("default", defaultPicture);
Wtedy nadszedł czas, aby uzyskać dane potrzebne do listy!
Krok 2: Pobierz Dane
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();
}
}
Oto borring AsyncTask
, który pobiera JSONArray
danych użytkownika jako argument. Pominąłem tę część, ponieważ jest to w zasadzie tylko podstawowe pobieranie HTTP, które nie wymaga wyjaśnienia. Metoda getUsers to miejsce, w którym zaczynam układać to, co zostanie dodane do mojej ListView
. Następnie przetwarzam JSON pobrany z serwera, aby utworzyć obiekty użytkownika, które zostaną dodane do listy użytkowników, którzy będą wyświetlane.
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());
}
}
Kojarzę obrazek z obiektem user, który ostatecznie zostanie wyświetlony. Domyślam się, że nie jest to całkowita strata czasu, ponieważ obraz jest pobierany z pamięci podręcznej bitmapy
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;
}
Jeśli obrazek istnieje w pamięci podręcznej jest zwracany, jeśli nie jest pobierany. Dla mnie, wyświetlając użytkowników, każde zdjęcie jest buforowane zgodnie z userid, więc nawet jeśli ktoś pojawiłby się więcej niż raz na liście, w pamięci podręcznej dla tego użytkownika byłby tylko jeden obraz.
ImageView profile_picture = (ImageView) v.findViewById(R.id.profile_picture);
if(profile_picture != null){
profile_picture.setImageBitmap(u.getProfilePicture());
}
Pozostało tylko znaleźć ImageView
w adapterze i ustawić ten widok na obrazek powiązany z obiektem na liście.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-05 19:20:27
Chcesz coś łatwego w użyciu? Z dbać o pliki buforowania, usuwanie pamięci podręcznej, zwolnić, gdy pamięć jest w linii granicznej?
Spróbuj LazyList, sprawdź to:
Https://github.com/nicolasjafelle/LazyList
Jak to jest wyjaśnione, wystarczy utworzyć Singleton w swojej klasie aplikacji lub innej aktywności lub fragmencie:
//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");
Następnie w widoku, który ma ImageView, aby wyświetlić obraz de, musisz zaimplementować ImageProcessingCallback interfejs:
public class MyItemView extends LinearLayout implements ImageProcessingCallback {
...
//Do what you need in methods onImagePreProcessing() and onImageProcessing(Bitmap bitmap)
...
ImageLoader.getInstance().displayImage(data[position], myView);
Na koniec musisz dodać to pozwolenie w androidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
I to wszystko. Następnie masz metody czyszczenia pamięci podręcznej pamięci ram lub pamięci podręcznej dysku lub obu.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-06 14:32:14
Nie wiem o przechowywaniu obrazów, ponieważ moja aplikacja używa obrazów z APK. Jednak wierzę, że do wyświetlania tych obrazów chcesz niestandardową Arrayadapter.
To nadmuchuje układ dla każdego elementu i umieszcza go na liście. Ten układ jest zdefiniowany przez układ XML, który tworzysz i określasz w jego konstrukcji. Spróbuj rozszerzyć adapter, którego aktualnie używasz w widoku listy, o niestandardowy, który ustawia widok obrazu zgodnie z pozycją.
Robię to z ImageView.setImageResource (resource ID); ale przebieg może się różnić. Mam moje obrazy w APK Nie wiem, jak wyświetlić je z zewnętrznego źródła
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-05 18:55:20