package com.justsystems.hpb.pad.marketplace; import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import com.justsystems.hpb.pad.R; import com.justsystems.hpb.pad.util.Debug; import org.wordpress.android.WordPress; import org.wordpress.android.task.MultiAsyncTask; import org.wordpress.android.util.DeviceUtils; public class MarketPlaceAdapter extends BaseAdapter { private boolean usePreinPicture = true; private static final int[] PREIN_IDS = { R.drawable.mp_top1, R.drawable.mp_top2 }; private Context context; /** テンプレートのリスト。keyはposition */ private final SparseArray<Template> templates = new SparseArray<Template>(); /** テンプレートのサムネイルのキャッシュ。keyはposition */ private final SparseArray<Drawable> cache = new SparseArray<Drawable>(); private ThumbnailGetTask task; public MarketPlaceAdapter(Context context) { this.context = context; setItem(); } public void setItem() { this.templates.clear(); Template[] templates = WordPress.wpDB.getTemplates(); if (templates.length == 0) { usePreinPicture = true; } else { SparseArray<Template> noImageTemplates = null; for (int i = 0; i < templates.length; i++) { Template template = templates[i]; this.templates.put(i, template); File image = new File(template.getThumbnailFullPath(context)); Debug.logd(template.getThumbnailFullPath(context) + " " + image.exists()); if (!image.exists()) { if (noImageTemplates == null) { noImageTemplates = new SparseArray<Template>(); } noImageTemplates.put(i, template); } } if (noImageTemplates != null) { if (this.task != null && !this.task.isCancelled()) { this.task.cancel(true); } this.task = new ThumbnailGetTask(context, this, noImageTemplates); this.task.executeOnMultiThread(); } usePreinPicture = false; } notifyDataSetChanged(); } @Override public int getCount() { return usePreinPicture ? PREIN_IDS.length : templates.size(); } @Override public Template getItem(int position) { return usePreinPicture ? null : templates.get(position); } @Override public long getItemId(int position) { return usePreinPicture ? PREIN_IDS[position] : templates.get(position) .getId(); } @Override public View getView(int position, View convertView, ViewGroup parent) { ImageView image = (ImageView) convertView; if (image == null) { LayoutInflater inflater = LayoutInflater.from(context); image = (ImageView) inflater.inflate(R.layout.mp_item, null); } if (usePreinPicture) { final int resId = (int) getItemId(position); final Drawable d = this.context.getResources().getDrawable(resId); image.setImageDrawable(d); } else { Template template = templates.get(position); String filePath = template.getThumbnailFullPath(context); if (!filePath.equals(image.getTag())) { //画像を更新する場合orViewが再利用される場合 Drawable d = this.cache.get(position); if (d == null) { //画像を更新する場合 if (new File(filePath).exists()) { d = new BitmapDrawable(context.getResources(), filePath); this.cache.put(position, d); } else { //画像がない場合orまだ取得できていない場合 //nullをsetImageDrawableするので古い画像は消える。 } } if (d != null) { image.setTag(filePath); image.setImageDrawable(d); } else { image.setTag(null); image.setImageDrawable(null); } } } return image; } private static final class ThumbnailGetTask extends MultiAsyncTask<Void, Void, Void> { private Context context; private MarketPlaceAdapter adapter; private SparseArray<Template> urls; private final int templateWidth; public ThumbnailGetTask(Context context, MarketPlaceAdapter adapter, SparseArray<Template> urls) { this.context = context; this.adapter = adapter; this.urls = urls; this.templateWidth = DeviceUtils.getSmallestWidthPixcel(context .getResources()); } @Override protected Void doInBackground(Void... params) { for (int i = 0; i < this.urls.size(); i++) { if (isCancelled()) { return null; } int key = this.urls.keyAt(i); Template template = this.urls.get(key); //以前の画像は消す removeOldFile(key, template); adapter.cache.remove(key); getImage(template); publishProgress(); } return null; } @Override protected void onProgressUpdate(Void... values) { super.onProgressUpdate(values); adapter.notifyDataSetInvalidated(); } private void removeOldFile(int key, Template template) { File dir = new File(Template.getThumbnailDir(context)); if (!dir.exists()) { return; } File[] files = dir.listFiles(); for (File file : files) { if (file.getName().startsWith(String.valueOf(key)) && !file.getAbsolutePath().equals( template.getThumbnailFullPath(context))) { file.delete(); } } } private boolean getImage(Template template) { BufferedInputStream in; try { in = new BufferedInputStream((InputStream) (new URL( template.getThumbnail()).getContent())); Bitmap rawBitmap; try { Options opt = new Options(); opt.inPreferredConfig = Config.RGB_565; rawBitmap = BitmapFactory.decodeStream(in, null, opt); } catch (OutOfMemoryError e) { Debug.logd("OOM", "decodeStream"); return false; } in.close(); if (rawBitmap == null) { return false; } File dir = new File(Template.getThumbnailDir(context)); if (!dir.exists()) { dir.mkdir(); } final int orginWidth = rawBitmap.getWidth(); final int orginHeight = rawBitmap.getHeight(); Bitmap bmp = null; if (orginWidth > templateWidth) { final float scale = templateWidth / (float) orginWidth; //通常は縦横比が1:1となるように final int templateHeight = Math.min( (int) (orginHeight * scale), templateWidth); try { bmp = Bitmap.createBitmap(templateWidth, templateHeight, Bitmap.Config.RGB_565); } catch (OutOfMemoryError e) { //GCしてもう一回トライする System.gc(); } if (bmp == null) { try { bmp = Bitmap.createBitmap(templateWidth, templateHeight, Bitmap.Config.RGB_565); } catch (OutOfMemoryError e) { return false; } } Canvas canvas = new Canvas(bmp); canvas.save(); canvas.scale(scale, scale); canvas.drawBitmap(rawBitmap, 0, 0, null); canvas.restore(); } else if (orginHeight > templateWidth) { //横は画面幅以下だが縦長 try { //縦横比が1:1となるように bmp = Bitmap.createBitmap(orginWidth, orginWidth, Bitmap.Config.RGB_565); } catch (OutOfMemoryError e) { //GCしてもう一回トライする System.gc(); } if (bmp == null) { try { bmp = Bitmap.createBitmap(orginWidth, orginWidth, Bitmap.Config.RGB_565); } catch (OutOfMemoryError e) { return false; } } Canvas canvas = new Canvas(bmp); canvas.save(); canvas.drawBitmap(rawBitmap, 0, 0, null); canvas.restore(); } else { bmp = rawBitmap; } final FileOutputStream out = new FileOutputStream( template.getThumbnailFullPath(context)); bmp.compress(CompressFormat.PNG, 100, out); out.close(); rawBitmap.recycle(); bmp.recycle(); return true; } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return false; } } }