gpt4 book ai didi

java - Android 应用内存泄漏还是正常现象?

转载 作者:行者123 更新时间:2023-12-02 04:26:39 24 4
gpt4 key购买 nike

我有一个非常占用内存的应用程序,这确实不是我想要的。平均而言,它的大小约为 90Mb,介于 90Mb 和 120Mb 之间。这很奇怪,因为前几天晚上它只占用了 40Mb 左右,这显然更容易接受。当我简单地运行该应用程序时,我的第一个问题就出现了。第二个问题是,当我滚动 ListView 时,我可以看到内存一次填满了大块。SOoo 现在我开始寻找内存泄漏了。我开始使用新的 Android Studio 功能/按钮“转储 Java 堆”进行堆转储。因此,在显示堆转储的所有内容时,我时不时地注意到非常大的数字,特别是在涉及 LinkedHashMap 和 HashMap 时。

/image/HmaFA.png

对于应用程序在进入 ListView 之前所做的工作量,它实际上不应该已经使用那么多内存(我相信),除非它是我怀疑的每个应用程序的标准配置。

看着这张图片,我如何知道哪个是真正的内存泄漏以及如何从这里找到它们?

好吧,我会在 ListView 显示之前插入调用的前 2 个函数。

请记住,我的所有图像都是从内部存储中加载毕加索的,因为速度非常快,所以我也切换了内存缓存。

此函数准备适配器并发送 objectID,以便新 Intent 可以自行从 SQLite DB 获取数据。

public void DisplayList(final List<ListData> DL)
{

ListAdapter listAdapter = new ParseAdapter(this,DL);
ListView listView = (ListView) findViewById(R.id.Parse_list);
listView.setAdapter(listAdapter);

listView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
String food = String.valueOf(parent.getItemAtPosition(position));
//setContentView(R.layout.deal_showcase);

Intent i = new Intent(getApplicationContext(),Deal_Showcase.class);

i.putExtra("objectid",DL.get(position).getObjectID());
//Intent intent = new Intent(this,DL.class);
startActivity(i);

}
}

);
}

//Adapter class
public class ParseAdapter extends ArrayAdapter<ListData>
{

ParseAdapter(Context context, List<ListData> adapResource) {
super(context, R.layout.parse_list_layout, adapResource);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
View customView = layoutInflater.inflate(R.layout.parse_list_layout, parent, false);

//PLease note that after implementing a ViewHolder is did not really do anything for me
//Also the ViewHolder implementation is not here at the moment but this is the version of //the code right before the ViewHolder got implemented.
String singleItem = getItem(position).getName();
TextView rText = (TextView) customView.findViewById(R.id.pName);

TextView yText = (TextView) customView.findViewById(R.id.pDistance);
ImageView image = (ImageView) customView.findViewById(R.id.imageView);


rText.setText(getItem(position).getName());
yText.setText(Integer.toString(getItem(position).getDistance()));
Picasso.with(this.getContext()).load("file://"+getItem(position).getArt_work_uri())
.resize(200,200)
.into(image);

return customView;
}

}

代码编辑1:

public class ParseAdapter extends ArrayAdapter<DealListData>
{
//Inner static class ViewHolder
static class ViewHolder
{
TextView Distance;
TextView DealName;
ImageView image;
}


ParseAdapter(Context context, List<DealListData> adapResource) {
super(context, R.layout.parse_list_layout, adapResource);
}
View convertView;

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



if (convertView==null)
{

LayoutInflater layoutInflater = LayoutInflater.from(getContext());
convertView = layoutInflater.inflate(R.layout.parse_list_layout, parent, false);
//ViewHolder holder setup
holder = new ViewHolder();
holder.DealName = (TextView) convertView.findViewById(R.id.pName);
holder.Distance = (TextView) convertView.findViewById(R.id.pDistance);
holder.image = (ImageView) convertView.findViewById(R.id.imageView);

//Store the holder in the view
convertView.setTag(holder);
}
else
{
//Get the holder if it already exists
holder = (ViewHolder) convertView.getTag();
}

customView.findViewById(R.id.imageView);

holder.DealName.setText(getItem(position).getName());
holder.Distance.setText(Integer.toString(getItem(position).getDistance()));
Picasso.with(this.getContext()).load("file://"+getItem(position).getArt_work_uri())
//.memoryPolicy(MemoryPolicy.NO_CACHE )
.networkPolicy(NetworkPolicy.NO_CACHE)
.resize(200,200)
.into(holder.image);

return convertView;
}

}

最佳答案

我通常认为泄漏是指应该被释放但没有的内存,并且外人很难知道您的应用程序属于该类别的内容。对于您的情况,如果您查看列表顶部附近,您会看到 Picasso 的 LruCache。 Picasso的缓存包含一个LinkedHashMap,其中包含一堆Entries(紧邻LruCache之上的东西),在本例中包含一堆位图。

默认情况下,Picasso 将使用最多最大内存的 1/8 作为缓存,这样您就不会一直访问磁盘。在大型设备上,您的应用程序可能有几百 MB,因此这可能相当大。这通常是可取的,因为它可以让您的应用程序感觉很快。您可能认为这是一次泄漏,因为它“浪费”内存并且不会消失,但这是有意为之的。

<小时/>

那么!继续使用该工具。

如果单击左侧类列表中的某个条目,然后查看右侧的 Pane ,您将看到该类型的实例列表。单击其中之一。在底部 Pane 中,您将看到该对象为何位于内存中。如果您继续扩展内容,您通常会找到您识别的代码(例如,您会找到使用位图的 View ,或 Picasso 的 LruCache 条目)。希望您不会看到不在屏幕上的 Activity,因为这通常意味着严重的泄漏。

底部的引用链向您显示了到“GC root”的最短路径(它位于内存中的最终原因,例如线程或静态变量)。通常这是最相关的,但不幸的是并非总是如此。某些内容保留在内存中可能还有其他原因,例如它可能位于缓存中并且当前正在被 View 使用。所以它很有用,但不如 MAT 有用。 ,它向您显示所有路径,并且具有更强大的查询工具等等。希望工具团队最终能够添加更多功能,这个功能有点像最小可行版本。

举个例子,这是我正在开发的一个应用程序,我在应用程序中保留了毕加索正在使用的缓存。如果您执行类似的操作,并且您确实希望在用户离开应用程序时释放内存,则可以在获得例如以下内容时清除缓存: TRIM_MEMORY_UI_HIDDEN : Example heap dump

关于java - Android 应用内存泄漏还是正常现象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32063550/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com