0

我写了一个从 JSON 获取图像的类。它正在工作,但内存有问题。当我向下滚动应用程序时,它在内存中泄漏。这是我的代码。

package com.nexum.senddata;

public class MainActivity extends Activity {

private ListView list;
private MyAdapter adapter;

    private final String parsingUrl = "http://sametdede.com/expo/data.json";
private String tag_coord = "Coord";
private String tag_lat = "Lat";
private String tag_lon = "Lon";// Double
private String tag_image = "Image";
private String tag_InIzmir = "InIzmir";
private String tag_name = "Name";

private ProgressDialog pDialog;

private static int clickedItemPosition = -1;
private final int REQUEST_CODE_DETAIL = 1;

ArrayList<CoordItem> items;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    items = new ArrayList<CoordItem>();
    adapter = new MyAdapter(this, R.layout.list_item, items);

    list = (ListView) findViewById(R.id.exampList);
    list.setAdapter(adapter);

    pDialog = new ProgressDialog(this);
    pDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    pDialog.setMessage("Veriler alınıyor...");

    new ListViewLoad().execute();

    list.setOnItemClickListener(new OnItemClickListener() {

        @SuppressLint("ShowToast")
        @Override
        public void onItemClick(AdapterView<?> a, View v, int position,
                long id) {
            /*
             * String bulunma = ""; if (items.get(position).inIzmir) {
             * bulunma+="İzmir de bulundu."; }else{
             * bulunma+="İzmir de bulunmadı."; } String
             * s="Name:"+items.get(position).name+"\nInIzmir:"+bulunma;
             * Toast.makeText(getApplicationContext(), s,
             * Toast.LENGTH_LONG).show();
             */

            clickedItemPosition = position;
            Intent myIntent = new Intent(MainActivity.this,
                    DetailActivity.class);
            Bundle bundle = new Bundle();
            bundle.putParcelable(
                    "parcelable_key",
                    new CoordItem(items.get(position).name, items
                            .get(position).img, items.get(position).lat,
                            items.get(position).lon,
                            items.get(position).inIzmir));
            myIntent.putExtras(bundle);
            // Güncelleme olayı burada başlıyor
            // startActivityForResult(myIntent, REQUEST_CODE_DETAIL);

            startActivityForResult(myIntent, REQUEST_CODE_DETAIL);

        }

    });

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // TODO Auto-generated method stub
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == REQUEST_CODE_DETAIL && resultCode == RESULT_OK
            && data != null) {
        CoordItem coorditem = new CoordItem(data.getStringExtra("name"),
                items.get(clickedItemPosition).img, Double.parseDouble(data
                        .getStringExtra("lat")), Double.parseDouble(data
                        .getStringExtra("lon")),
                items.get(clickedItemPosition).inIzmir);

        items.set(clickedItemPosition, coorditem);
        adapter.notifyDataSetChanged();
        Toast.makeText(getApplicationContext(), "Guncelleme yapıldı.",
                Toast.LENGTH_SHORT).show();
    }
    /*
     * CoordItem coorditem = new CoordItem(data.getStringExtra("name"),
     * items.get(clickedItemPosition).img,
     * Double.parseDouble(data.getStringExtra("lat")),Double.parseDouble(
     * data.getStringExtra("lon")), items.get(clickedItemPosition).inIzmir);
     * 
     * items.set(clickedItemPosition, coorditem);
     * adapter.notifyDataSetChanged();
     * Toast.makeText(getApplicationContext(), "Guncelleme yapıldı.",
     * Toast.LENGTH_SHORT).show();
     */

}

private class ListViewLoad extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog.show();
    }

    @Override
    protected Void doInBackground(Void... params) {

        String json = getStringFromURL(parsingUrl);
        try {
            final JSONArray jArray = new JSONArray(json);

            for (int i = 0; i < jArray.length(); i++) {
                JSONObject c = jArray.getJSONObject(i);
                JSONObject coord = c.getJSONObject(tag_coord);
                double lat = coord.getDouble(tag_lat);
                double lon = coord.getDouble(tag_lon);
                String image = c.getString(tag_image);
                boolean InIzmir = c.getBoolean(tag_InIzmir);
                String name = c.getString(tag_name);

                CoordItem item = new CoordItem(name, image, lat, lon,
                        InIzmir);
                items.add(item);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);

        adapter.notifyDataSetChanged();

        pDialog.dismiss();
    }

}

private class MyAdapter extends ArrayAdapter<CoordItem> {

    private LayoutInflater inflater;

    public MyAdapter(Context context, int textViewResourceId,
            ArrayList<CoordItem> objects) {
        super(context, textViewResourceId, objects);

        this.inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
        if (items != null)
            return items.size();
        else
            return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder viewholder = null;

        if (convertView == null) {
            viewholder = new ViewHolder();

            convertView = inflater.inflate(R.layout.list_item, parent,
                    false);
            viewholder.listItemImage = (ImageView) convertView
                    .findViewById(R.id.listItemImage);

            viewholder.listItemName = (TextView) convertView
                    .findViewById(R.id.listItemName);
            viewholder.listItemInIzmir = (TextView) convertView
                    .findViewById(R.id.listItemInIzmir);
            viewholder.listItemLatitude = (TextView) convertView
                    .findViewById(R.id.listItemLatitude);
            viewholder.listItemLongitude = (TextView) convertView
                    .findViewById(R.id.listItemLongitude);
            convertView.setTag(viewholder);
        } else {
            viewholder = (ViewHolder) convertView.getTag();
        }

        viewholder.listItemName.setText(items.get(position).name);
        if (items.get(position).inIzmir) {
            viewholder.listItemInIzmir.setText("Izmirde.");
        } else {
            viewholder.listItemInIzmir.setText("Izmirde degil.");
        }

        try {
            viewholder.listItemImage
                    .setImageDrawable(getDrawableFromUrl(new URL(items.get(
                            position).getImg())));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return convertView;
    }

    public Drawable getDrawableFromUrl(URL url) {
        try {
            InputStream is = (InputStream) url.getContent();
            Drawable d = Drawable.createFromStream(is, "src");
            return d;
        } catch (Exception e) {
            return null;
        }
    }

}

/**
 * Burada layoutinflater da kullandığımız layoutun componentlerini
 * yazıyoruz.Bu da bizim list_item.xml imizdir.
 */
static class ViewHolder {
    ImageView listItemImage;
    TextView listItemName, listItemInIzmir, listItemLatitude,
            listItemLongitude;
}

public String getStringFromURL(String url) {

    // Making HTTP request
    String json = "";
    InputStream is = null;
    try {
        // defaultHttpClient
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        is = httpEntity.getContent();

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                is, "UTF-8"), 8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        is.close();
        json = sb.toString();
    } catch (Exception e) {
        e.printStackTrace();
    }

    // return JSON String
    return json;

}

}

我在哪里可以读取和获取图像以更快地执行而不是内存泄漏?

4

1 回答 1

1

您已经使用了 ViewHolder。

使用 LazyList 或通用图像加载器

懒惰列表

图像可以缓存到本地sd卡或手机内存。Url 被认为是关键。如果密钥存在于 sdcard 中,则显示来自 sd 卡的图像,否则通过从服务器下载显示图像并将其缓存到您选择的位置。可以设置缓存限制。您还可以选择自己的位置来缓存图像。缓存也可以清除。

而不是用户等待下载大图像然后显示惰性列表按需加载图像。由于图像区域缓存,您可以离线显示图像。

https://github.com/thest1/LazyList。懒惰列表

在你的 getview

imageLoader.DisplayImage(imageurl, imageview);

ImageLoader 显示方法

public void DisplayImage(String url, ImageView imageView) //url and imageview as parameters
{
imageViews.put(imageView, url);
Bitmap bitmap=memoryCache.get(url);   //get image from cache using url as key
if(bitmap!=null)         //if image exists
    imageView.setImageBitmap(bitmap);  //dispaly iamge
 else   //downlaod image and dispaly. add to cache.
 {
    queuePhoto(url, imageView);
    imageView.setImageResource(stub_id);
 }
 }

   

通用图像加载器

https://github.com/nostra13/Android-Universal-Image-Loader

可以在本地或从服务器加载图像。

它基于惰性列表(工作原理相同)。但它还有很多其他配置。我更喜欢使用 Universal Image Loader,因为它为您提供了更多配置选项。如果下载失败,您可以显示错误图像。可以显示带圆角的图像。可以缓存在磁盘或内存上。可以压缩图像。

在您的自定义适配器构造函数中

 File cacheDir = StorageUtils.getOwnCacheDirectory(activity context, "your folder");//for caching

// 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
.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);
 options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.stub_id)//display stub image untik image is loaded
.cacheInMemory()
.cacheOnDisc()
.displayer(new RoundedBitmapDisplayer(20))
.build();

在你的 getView()

 ImageView image=(ImageView)vi.findViewById(R.id.imageview); 
 imageLoader.displayImage(imageurl, image,options);//provide imageurl, imageview and options.

您可以配置其他选项以满足您的需求。

于 2013-03-29T07:48:30.837 回答