gpt4 book ai didi

java - ListView 内存泄漏

转载 作者:太空狗 更新时间:2023-10-29 15:30:00 25 4
gpt4 key购买 nike

我有一个带适配器的简单 ListView 。我动态创建了 10 多个 listviewitems。然后我一次又一次地上下滚动....我可以看到可用内存不断下降...

我需要释放什么?注意 - 有一个 imageview - 但在我的测试中我没有使用任何图像所以它是 View.GONE。

此外 - 我可以使用哪个工具分析 android 上的内存使用情况。我找到了你的工具包,但是如何为 android 配置它(我在设备上运行应用程序)/

Activity 类

package org.BJ.Food4All.Activities.NewRecipe;


import org.BJ.Food4All.R;
import org.BJ.Food4All.Recipe;
import org.BJ.Food4All.Recipe.Instruction;
import org.BJ.Food4All.Activities.RecipeBook.RecipeInstructionsListViewAdapter;
import org.BJ.Food4All.Activities.RecipeBook.SharedData;
import org.BJ.Food4All.utils.CameraUtil;
import org.BJ.Food4All.utils.ImageUploadItem;

import android.app.ListActivity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.EditText;

public class Instructions extends ListActivity implements OnClickListener
{
private final static String mTAG = "Instructions";
private EditText mInstructionEditText = null;
private RecipeInstructionsListViewAdapter mListViewAdapter = null;
private Recipe mEditRecipe = PrivateResources.GetRecipe();

private CameraUtil mCameraUtil = new CameraUtil(this);

private int mSelectedEntryIndex = -1;

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

mInstructionEditText = (EditText)findViewById(R.id.newRecipeInstructionEditTextId);
View addInstructionButton = findViewById(R.id.naddInstructionButtonId);

// Sanity check
if(mInstructionEditText == null || addInstructionButton == null)
{
Log.e(mTAG, "NULL pointers");
// secure exit
finish();
}

// Set up click listeners for all the buttons
addInstructionButton.setOnClickListener(this);

mListViewAdapter = new RecipeInstructionsListViewAdapter(this, R.layout.recipes_instruction_list_single_view_entry, mEditRecipe.GetInstructions());

setListAdapter(mListViewAdapter);

registerForContextMenu(getListView());
}

public void onClick(View v)
{
switch(v.getId())
{
case R.id.naddInstructionButtonId:
AddInstructionToRecipe(v);
break;

default:
Log.e(mTAG, "Invalid ID:" + v.getId());
// secure exit
finish();

}
}

private void AddInstructionToRecipe(View v)
{
String instructionText = mInstructionEditText.getText().toString();

if(instructionText == null)
{
return;
}

Instruction newInstruction = new Instruction( mEditRecipe.GetInstructions().size() + 1, // Index
instructionText, // The instruction
null,
true);

if( mEditRecipe.AddInstruction(newInstruction) != true)
{
// TODO - ERROR
}
else
{
mListViewAdapter.notifyDataSetChanged();
}
}

/*
* (non-Javadoc)
* @see android.app.Activity#onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo)
*/
@Override
public void onCreateContextMenu(ContextMenu menu,
View v,
ContextMenuInfo menuInfo)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.instructions_ctx_menu, menu);

super.onCreateContextMenu(menu, v, menuInfo);
}

/*
* (non-Javadoc)
* @see android.app.Activity#onContextItemSelected(android.view.MenuItem)
*/
@Override
public boolean onContextItemSelected(MenuItem item)
{
super.onContextItemSelected(item);

AdapterView.AdapterContextMenuInfo menuInfo;
menuInfo = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
mSelectedEntryIndex = menuInfo.position;

switch(item.getItemId())
{
case R.id.deleteId:
mEditRecipe.RemoveInstruction(mSelectedEntryIndex);
mListViewAdapter.notifyDataSetChanged();
return true;

case R.id.takePictureId:
mCameraUtil.TakePicture();
return true;
}

return false;
}

/*
* (non-Javadoc)
* @see android.app.Activity#onActivityResult(int, int, android.content.Intent)
*/
@Override
protected void onActivityResult(int requestCode,
int resultCode,
Intent data)
{
// String imageLocation = mCameraUtil.onActivityResult(requestCode, resultCode, data);
Bitmap imageBitmap = mCameraUtil.onActivityResult(requestCode, resultCode, data);
// TODO - switch to parameter passed in the intent!!!! like TakePicture(index);
// mEditRecipe.GetInstructions().get( mSelectedEntryIndex ).SetBitmap( imageBitmap ); //SetInstructionImageLocation(imageLocation);
mSelectedEntryIndex = -1;

// Update the listviewitem with the picture
mListViewAdapter.notifyDataSetChanged();
}
}

适配器类

package org.BJ.Food4All.Activities.RecipeBook;

import java.util.ArrayList;

import org.BJ.Food4All.R;
import org.BJ.Food4All.Recipe.Instruction;
import org.BJ.Food4All.utils.GlobalDefs;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Typeface;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class RecipeInstructionsListViewAdapter extends ArrayAdapter<Instruction>
{
private Context mContext;
private ArrayList<Instruction> mItems;
private LayoutInflater mInflater;

public RecipeInstructionsListViewAdapter(Context context, int textViewResourceId, ArrayList<Instruction>items)
{
super(context, textViewResourceId, items);

mContext = context;
mItems = items;

mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

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

if (convertView == null)
{
convertView = mInflater.inflate(R.layout.recipes_instruction_list_single_view_entry, null);
}

if(super.getItem(position) != null)
{
holder.instructionIndex = (TextView) convertView.findViewById( R.id.listUp_RecipeInstructionNumberTextBoxId);
holder.instructionText = (TextView) convertView.findViewById( R.id.listUp_RecipeInstructionTextTextBoxId);
holder.instructionImage = (ImageView)convertView.findViewById( R.id.listUp_RecipeInstructionImageViewId);

Typeface tf = Typeface.createFromAsset(mContext.getAssets(), "Eras_Bold.ttf");
holder.instructionIndex.setTypeface(tf);
holder.instructionIndex.setTextSize(30);
holder.instructionIndex.setTextColor(GlobalDefs.GetHeadlineColor());
holder.instructionIndex.setText( Integer.toString(mItems.get(position).getIndex()));

tf = Typeface.createFromAsset(mContext.getAssets(), "Arial.ttf");
holder.instructionText.setTypeface(tf);
holder.instructionText.setTextSize(14);
holder.instructionText.setTextColor(Color.BLACK);
holder.instructionText.setText(mItems.get(position).getText());

Bitmap imageBitmap = mItems.get(position).GetBitmap();
// String imageLocation = mItems.get(position).GetInstructionImageLocation();
if(imageBitmap != null)
{
holder.instructionImage.setImageBitmap(imageBitmap);// setImageURI( Uri.parse(imageLocation ));
holder.instructionImage.setVisibility(View.VISIBLE);
}
else
{
holder.instructionImage.setVisibility(View.GONE);
}

convertView.setTag(holder);
convertView.setLayoutParams(new ListView.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
}
else
{
}

return convertView;
}

@Override
public boolean isEnabled(int position)
{
return true;
}

static class ViewHolder
{
TextView instructionIndex;
TextView instructionText;
ImageView instructionImage;
}
}

最佳答案

我不确定将其归类为错误是否正确,但每次您使用 Typeface.createFromAsset if 都会创建新的字体 Assets 并且不会发布它。参见 this .

您可以做的是在加载应用程序时加载字体并静态引用它们。我将我的字体放在应用程序中。

public class YourApp extends android.app.Application {
public void onCreate() {
super.onCreate();

// typeface caching
initializeTypefaces();
}

public static class Fonts {
public static Typeface THEOREM;
}

private void initializeTypefaces(){
Fonts.THEOREM = Typeface.createFromAsset(getAssets(), "fonts/theorem.otf");
}
}

然后我在我的适配器中执行此操作:

textView.setTypeface(YourApp.Fonts.THEOREM);

你可以去here查看如何在 Android 中使用应用程序。

最后,看起来您每次仍在创建 ViewHolder,而不是仅在 convertView 为 null 时才创建。我会查看此视频以了解全貌。 http://www.google.com/events/io/2010/sessions/world-of-listview-android.html

这是我如何使用 ViewHolder 方法的示例:

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

if(convertView == null || convertView.getTag() == null){
convertView = inflater.inflate(R.layout.list_item, parent, false);
holder = new ViewHolder();

holder.text1 = (TextView)convertView.findViewById(R.id.list_item_text1);
holder.text2 = (TextView)convertView.findViewById(R.id.list_item_text2);
holder.text1.setTypeface(YourApp.Fonts.THEOREM); // only happens once when recycling!

convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}

holder.text1.setText("someText");
holder.text2.setText("someText");
return convertView;
}

关于java - ListView 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8057010/

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