2

ImageViewリストのすべての行に1 つのリストを表示しています。

そのために、別の AsyncTask を使用してネットから画像をダウンロードし、Drawable.createFromStream それらを Drawable として保存し、BaseAdapterクラスArrayListを拡張する Adapter クラスに渡します。

ただし、画像は高解像度カメラで撮影されているため、サイズが非常に大きくなる場合があります。そして、私はOutOfMemoryエラーが発生しています。

だから私の質問:

  1. 画像をドローアブルとして保存するか、ビットマップまたはその他の形式として保存するのがより効率的ですか?

  2. すべての画像をメモリ(配列リスト)に保存することで、私は正しくやっていますか?つまり、画像を取得したら、それを ImageView に表示し、ArrayList には保存しないと考えています。

  3. ダウンロード後に画像を圧縮できるので、メモリ内のスペースが少なくて済みます。

私の合計コードはここにあります

4

3 に答える 3

1
  1. 高密度の画像をメモリに保存するのに効率が悪いと思います-大量の画像をビットマップとしてメモリに保存することはまったくお勧めできません(優れたデバイスをお持ちの場合は良いです;))
  2. p.1参照
  3. デバイスのニーズに合わせて画像を縮小してみてください。ただし、これは簡単な作業ではありません。また、View.setTag(Object tag)も参照してください。

アダプター

public class MyImageListAdapter extends BaseAdapter implements ImageLoadingNotifier {

private LayoutInflater inflater = null;

public MyImageListAdapter() {
    inflater = LayoutInflater)HomeActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

public int getCount() {
    return listImageInfo.size();
}

public Object getItem(int position) {
    return listImageInfo.get(position);
}

public long getItemId(int position) {
    return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
    View vi = convertView;
    if (convertView == null) {
        vi = inflater.inflate(R.layout.list_row, null);
    }

    TextView tvName = (TextView) vi.findViewById(R.id.tv_name);
    TextView tvTime = (TextView) vi.findViewById(R.id.tv_time);
    ImageView image = (ImageView) vi.findViewById(R.id.iv_image);
    final Button btnDelete = (Button) vi.findViewById(R.id.btn_delete);


    image.setImageDrawable(R.drawable.default_placeholder);//set default place-holder
    new GetDrawableFromUrl(listImageInfo.get(position), vi).execute();

    tvName.setText("Name: " + listImageInfo.get(position).getImage_name());
    tvTime.setText("Date: " + listImageInfo.get(position).getDate_created());

    btnDelete.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            final int position = listView.getPositionForView((View) v.getParent());
            positionOgBtnToDelete = position;
            Log.v("delete btn clicked", "delete btn no: " + position);
            Toast.makeText(HomeActivity.this, "Btn delete position: " + position, Toast.LENGTH_LONG).show();
            showAlertToConfirmDelete();
        }
    });
    return vi;
}

}

AsyncTaskGetDrawableFromUrl

public class GetDrawableFromUrl extends AsyncTask<Void, Void, Drawable> {
public ImageInfo imageInfoObj;
private ImageView view;


GetDrawableFromUrl(ImageInfo imageInfo, ImageView view) {
    imageInfoObj = imageInfo;
    this.view = view;
}

@Override
protected Drawable doInBackground(Void... params) {
    try {
        return Drawable.createFromStream(((java.io.InputStream) new java.net.URL(imageInfoObj.getImageUrl()).getContent()), "src_name");
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

protected void onPostExecute(Drawable drawable) {
    if (drawable != null) {
        //imageInfoObj.setImage(drawable);
        this.view.setImageDrawable(drawable);
        //listImageInfo.add(imageInfoObj); //this one is called when the json is parsed
        showImagesInList(); //don't know what it does (??)
    }
}

}

JSON解析

JSONArray jsonArray = jsonObj.getJSONArray("result");
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject jsonObjInner = jsonArray.getJSONObject(i);

                ImageInfo imageInfo = new ImageInfo();
                imageInfo.setImageUrl("http://www.dvimaytech.com/markphoto/" + jsonObjInner.getString("image"));

                //new GetDrawableFromUrl(imageInfo).execute(); //don't needed here

                imageInfo.setEmail(jsonObjInner.getString("emailid"));
                imageInfo.setImage_id(jsonObjInner.getString("image_id"));
                imageInfo.setImage_name(jsonObjInner.getString("image_name"));
                imageInfo.setAmount(jsonObjInner.getString("amount"));
                imageInfo.setImage_description(jsonObjInner.getString("image_description"));
                imageInfo.setDate_created(jsonObjInner.getString("date_created"));

                listImageInfo.add(imageInfo);
            }

そして、あらゆる種類のList画像の使用は不要になります:)

GetDrawableFromUrljsonオブジェクトを解析するときに非同期タスク()を開始する代わりに、getView(...)メソッドでタスクを開始できます。この方法では、画像のダウンロード後にArrayList変更するため、ドローアブルをその中に保存する必要はありません。ImageViewまた、デフォルトでは、画像がダウンロードされるまで(または、ネットワークエラーが発生した場合に備えて)、プレースホルダーを配置できます。

このようにしてgetView、その特定のアイテムに対してメソッドが呼び出されたときにのみ、画像のダウンロードが開始されます。

肝心なのは、からの各ビューは、そのListView特定のドローアブル(を使用して設定された)への参照を保持するということvi.setTag(image)です。

これが何らかの形で役立つ場合は、何をすべきかを知っています;)

于 2013-01-11T08:52:07.813 に答える
1

かなり良いライブラリ呼び出しがありAQueryます。2行のコードを書くだけで、メモリやファイルキャッシュなどのすべてのものを簡単に取得できます。したがって、ドローアブルを準備する必要さえなく、Adapter.getView()コールバックから直接呼び出すことができます。

AQuery aq = new AQuery(rowView);
aq.id(R.id.image).image(url, false, true);

それがあなたを助けることを願っています!

AQuery ドキュメントから:

ダウン サンプリング (巨大な画像の処理) ネットワークから巨大な画像を読み込んでいますが、必要なのは幅が 200 ピクセルを超える画像だけです。ターゲット幅 200 を渡すと、メモリを節約するために画像がダウンサンプリングされます。Aquery は、良好な画像品質と効率を得るために、2 の累乗 (2,4,8...) でのみダウンサンプルします。結果の画像幅は 200 の間になります。および 399 ピクセル

String imageUrl = "http://farm6.static.flickr.com/5035/5802797131_a729dac808_b.jpg";
aq.id(R.id.image1).image(imageUrl, true, true, 200, 0);

于 2013-01-11T07:51:20.763 に答える
1

Android のドキュメントには、Android アプリでビットマップを処理する方法を示す非常に良い例が用意されています。この例では、ディスク上とメモリ内のキャッシュを使用し、バックグラウンドで画像を読み込みます。そうすることで、メインの UI スレッドが画像の読み込みによって遅くなることはありません。

ビットマップの効果的な読み込み

この例では、画像は picasa から読み込まれます。ただし、この例を簡単に変更して、ローカルに保存された画像を使用できるようにします。「ImageResizer」から拡張する独自の ImageLoader を作成するだけです。

public class ImageLoader extends ImageResizer {
    public ImageLoader(Context context, int imageWidth, int imageHeight) {
        super(context, imageWidth, imageHeight);
    }
    public ImageLoader(Context context, int imageSize) {
        super(context, imageSize);
    }
    @Override
    protected Bitmap processBitmap(Object data) {
        return decodeSampledBitmapFromFile((String)data, imageWidth, imageHeight);
    }
}

しかし、あなたの質問に直接答えるには、画像をビットマップとしてロードしても問題ありません。ただし、画像が画面に表示されない場合に備えて画像をガベージ コレクションできるように、キャッシュと弱参照を使用する必要があります。それらをキャッシュし、読み込みにバックグラウンド タスクを使用すると、洗練された UI が可能になります。

于 2013-01-11T08:58:48.117 に答える