androidでの画像ダウンロードツール類AsyncImageLoader分析
この时间は多くの人がlistview(例えばアナログ新浪クライアント)をしてこの画像をダウンロードしたクラスを见て、私もこのクラスがいったいどの大神が书いたのか分かりません.どうせ私がこのクラスを使った时に他の人を引き継いだのです.最初は、このクラスの书き方がいいと感じました.私が书いたAsyncImageTaskより.JAvaはだいぶよくなりました.まず私が最初に書いたことを話しましょう.レンガを投げて玉を引いたのです.
このクラスでは、画像を表示するImageViewと画像のネットアドレスを入力するだけで、画像のダウンロードが完了したら、表示することができます.それから私の責任者はそれを交換して、AsyncImageLoaderを使いました.JAvaというクラスは、よく見ると、確かによく書けています.くだらないことを言わないで、まずこのクラスのコードを貼ってください(AsyncImageLoader.java):
インプリメンテーション:ピクチャのネットワークアドレスとImageCallback動作を実現するオブジェクトを転送することによって、imageCacheがこのピクチャが存在する場合、このピクチャを返し、imageCacheがこのピクチャが存在しない場合、インスタンスの非同期スレッドがピクチャをダウンロードし、nullに戻り、最後にピクチャのダウンロードが完了すると、imageLoadedメソッドを呼び出す.
このデザインの長所を話しましょう.戦略モデルを採用した.2.SoftReferenceキーワードの使用
まず戦略モードについてお話しします.プログラムでは、ダウンロード画像が完了するたびに行われる操作をImageCallback抽象クラスにカプセル化し、システムをより柔軟にし、拡張しやすくします.
Javaではメモリ管理、リファレンスは4つのクラスに分けられ、強リファレンスHardReference、弱リファレンスWeakReference、ソフトリファレンスSoftReference、虚リファレンスPhantomReferenceがあります.それらの違いも明らかで、HardReferenceオブジェクトは仮想マシンのメモリがきつくてOOMを投げ出してもこのリファレンスのオブジェクトが回収されることはありませんが、WeakReferenceなどは数は多くありませんが、体積が少し大きいオブジェクトに適しており、この4つのリファレンスの中で最もゴミ回収されやすいものです.一方、Android MarketのようなアプリケーションごとのApp Iconを表示する場合、ソフトリファレンスはソフトリファレンスを使用してメモリを迅速に回収することはなく、メモリ不足がJava VMのクラッシュに直面してOOMを投げ出す前に強制的に回収することを考慮することができ、最後の虚リファレンスは実用的ではなく、GCのアクティビティ状態を観察するだけで、テストに対して実用的であると同時にReferenceQueueと一緒に使用する必要があります.データのセットについては、SaftReferenceオブジェクトのセットをHashMapで追加し、ネットワークを介して取得した変更が頻繁でないコンテンツについては、ローカルのファイルシステムまたはデータベースを介してキャッシュを格納することができます.
最後の一言は正しいが、実際には多くの場合もそうだ.
その使い方を話しましょう.通常、adapterの変数として使われています.
しかし、20以上の画像を同時にダウンロードするスレッド(さらに多く)をもたらす可能性があり、スレッドの数に制限はありません.では、固定データのスレッドプールを使用しましょう.例えば、1つの画像に繰り返し追加されたらどう処理しますか.スレッドプールのスレッドの優先度の手配はどうしますか.(例えば、最近追加したいスレッドの優先度が最も高いです.現在のインタフェースの内容を最初に見たいので、インタフェースをスキップした内容がいつ終わるか気にしないでください.ここでは多すぎますが、実際には多くのアプリケーションに対応することができます)
- public class AsyncImageTask extends AsyncTask<String, Void, InputStream>{
-
- private ImageView imageView;
-
- public AsyncImageTask(ImageView imageView){
-
- this.imageView = imageView;
-
- }
-
- @Override
-
- protected InputStream doInBackground(String... params) {
-
-
-
- InputStream inputStream = null;
-
- try {
-
- URL url = new URL(params[0]);
-
- inputStream = url.openStream();
-
- } catch (IOException e) {
-
- e.printStackTrace();
-
- }
-
- return inputStream;
-
- }
-
- @Override
-
- protected void onPostExecute(InputStream result) {
-
- if(imageView!=null && result!=null){
-
- Bitmap bmp = BitmapFactory.decodeStream(result);
-
- imageView.setImageBitmap(bmp);
-
- }
-
- super.onPostExecute(result);
-
- }
-
- }
このクラスでは、画像を表示するImageViewと画像のネットアドレスを入力するだけで、画像のダウンロードが完了したら、表示することができます.それから私の責任者はそれを交換して、AsyncImageLoaderを使いました.JAvaというクラスは、よく見ると、確かによく書けています.くだらないことを言わないで、まずこのクラスのコードを貼ってください(AsyncImageLoader.java):
- public class AsyncImageLoader {
-
-
-
- private HashMap<String, SoftReference<Drawable>> imageCache;
-
-
-
- public AsyncImageLoader() {
-
- imageCache = new HashMap<String, SoftReference<Drawable>>();
-
- }
-
-
-
- public Drawable loadDrawable(final String imageUrl, final ImageCallback imageCallback) {
-
- if (imageCache.containsKey(imageUrl)) {
-
- SoftReference<Drawable> softReference = imageCache.get(imageUrl);
-
- Drawable drawable = softReference.get();
-
- if (drawable != null) {
-
- return drawable;
-
- }
-
- }
-
- final Handler handler = new Handler() {
-
- public void handleMessage(Message message) {
-
- imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
-
- }
-
- };
-
- new Thread() {
-
- @Override
-
- public void run() {
-
- Drawable drawable = loadImageFromUrl(imageUrl);
-
- imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
-
- Message message = handler.obtainMessage(0, drawable);
-
- handler.sendMessage(message);
-
- }
-
- }.start();
-
- return null;
-
- }
-
-
-
- public static Drawable loadImageFromUrl(String url) {
-
- URL m;
-
- InputStream i = null;
-
- try {
-
- m = new URL(url);
-
- i = (InputStream) m.getContent();
-
- } catch (MalformedURLException e1) {
-
- e1.printStackTrace();
-
- } catch (IOException e) {
-
- e.printStackTrace();
-
- }
-
- Drawable d = Drawable.createFromStream(i, "src");
-
- return d;
-
- }
-
-
-
- public interface ImageCallback {
-
- public void imageLoaded(Drawable imageDrawable, String imageUrl);
-
- }
-
-
-
- }
インプリメンテーション:ピクチャのネットワークアドレスとImageCallback動作を実現するオブジェクトを転送することによって、imageCacheがこのピクチャが存在する場合、このピクチャを返し、imageCacheがこのピクチャが存在しない場合、インスタンスの非同期スレッドがピクチャをダウンロードし、nullに戻り、最後にピクチャのダウンロードが完了すると、imageLoadedメソッドを呼び出す.
このデザインの長所を話しましょう.戦略モデルを採用した.2.SoftReferenceキーワードの使用
まず戦略モードについてお話しします.プログラムでは、ダウンロード画像が完了するたびに行われる操作をImageCallback抽象クラスにカプセル化し、システムをより柔軟にし、拡張しやすくします.
Javaではメモリ管理、リファレンスは4つのクラスに分けられ、強リファレンスHardReference、弱リファレンスWeakReference、ソフトリファレンスSoftReference、虚リファレンスPhantomReferenceがあります.それらの違いも明らかで、HardReferenceオブジェクトは仮想マシンのメモリがきつくてOOMを投げ出してもこのリファレンスのオブジェクトが回収されることはありませんが、WeakReferenceなどは数は多くありませんが、体積が少し大きいオブジェクトに適しており、この4つのリファレンスの中で最もゴミ回収されやすいものです.一方、Android MarketのようなアプリケーションごとのApp Iconを表示する場合、ソフトリファレンスはソフトリファレンスを使用してメモリを迅速に回収することはなく、メモリ不足がJava VMのクラッシュに直面してOOMを投げ出す前に強制的に回収することを考慮することができ、最後の虚リファレンスは実用的ではなく、GCのアクティビティ状態を観察するだけで、テストに対して実用的であると同時にReferenceQueueと一緒に使用する必要があります.データのセットについては、SaftReferenceオブジェクトのセットをHashMapで追加し、ネットワークを介して取得した変更が頻繁でないコンテンツについては、ローカルのファイルシステムまたはデータベースを介してキャッシュを格納することができます.
最後の一言は正しいが、実際には多くの場合もそうだ.
その使い方を話しましょう.通常、adapterの変数として使われています.
- class BookAdapter extends ArrayAdapter<BookInfo>{
-
- AsyncImageLoader asyncImageLoader;
-
- Context mContext;
-
-
-
- BookAdapter(Context context,List<BookInfo> data){
-
- super(context, 0, data);
-
- asyncImageLoader = new AsyncImageLoader();
-
- mContext = context;
-
- }
-
- @Override
-
- public View getView(int position, View convertView, ViewGroup parent) {
-
- ViewCache holder ;
-
- if(convertView==null){
-
- LayoutInflater inflate = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- convertView = inflate.inflate(com.slider.cn.R.layout.list_item , null);
-
- holder = new ViewCache();
-
- holder.icon = (ImageView)convertView.findViewById(com.slider.cn.R.id.note_icon);
-
- holder.name = (TextView)convertView.findViewById(com.slider.cn.R.id.note_name);
-
- holder.date = (TextView)convertView.findViewById(com.slider.cn.R.id.note_date);
-
- convertView.setTag(holder);
-
- }else{
-
- holder = (ViewCache)convertView.getTag();
-
- }
-
- final BookInfo bookInfo = getItem(position);
-
- holder.name.setText(bookInfo.getName().toString());
-
- holder.date.setText(bookInfo.getInfo());
-
- holder.icon.setTag(bookInfo.getUri());
-
- //
-
- Drawable drawable = asyncImageLoader.loadDrawable(bookInfo.getUri(), new ImageCallback() {
-
-
-
- @Override
-
- public void imageLoaded(Drawable imageDrawable, String imageUrl) {
-
- ImageView imageViewByTag = (ImageView) BookListView.this.findViewWithTag(bookInfo.getUri());
-
- if (imageViewByTag!=null) {
-
- imageViewByTag.setImageDrawable(imageDrawable);
-
- }else {
-
- //load image failed from Internet
-
- }
-
-
-
- }
-
- });
-
- if(drawable==null){
-
- holder.icon.setImageDrawable(drawable_waiting);
-
- }else{
-
-
-
- holder.icon.setImageDrawable(drawable);
-
- }
-
- return convertView;
-
- }
-
- }
-
- static class ViewCache{
-
- ImageView icon;
-
- TextView name;
-
- TextView date;
-
- }
しかし、20以上の画像を同時にダウンロードするスレッド(さらに多く)をもたらす可能性があり、スレッドの数に制限はありません.では、固定データのスレッドプールを使用しましょう.例えば、1つの画像に繰り返し追加されたらどう処理しますか.スレッドプールのスレッドの優先度の手配はどうしますか.(例えば、最近追加したいスレッドの優先度が最も高いです.現在のインタフェースの内容を最初に見たいので、インタフェースをスキップした内容がいつ終わるか気にしないでください.ここでは多すぎますが、実際には多くのアプリケーションに対応することができます)