2013-03-29 38 views
0

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

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; 

} 

}

我在哪里可以阅读和获取的图像用于执行速度更快,而不是内存泄漏?

回答

1

您已经使用了ViewHolder。

使用LazyList或通用图像装载机

懒列表

图像可以被缓存到本地SD卡或手机mmeory。网址被认为是关键。如果密钥存在于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

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

它基于Lazy List(基于相同原理)。但它有很多其他配置。我宁愿使用通用图像加载程序,因为它提供了更多的配置选项。如果downlaod失败,您可以显示错误图像。可以显示圆角的图像。可以缓存在光盘或内存上。可以压缩图像。

在您的自定义适配器构造

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. 

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

+0

我从JSON获取网址。那么如何根据我的代码初始化ImageLoader? – emrerme

+0

imageLoader.displayImage(imageurl,image,options);如果您使用的是图像加载器,请使用上面的图像加载器。传递图像网址到你的cusotm适配器,并提供URL像url [position] – Raghunandan

+0

No no。我怎样才能初始化ImageLoader类。它需要一些参数ImageLoader imageloader = new ImageLoader(?);在我的代码中,我可以放什么?在您的适配器构造函数中感谢 – emrerme