【发布时间】:2015-02-12 19:15:41
【问题描述】:
我一直在编写一个 Listview,其中显示一个图像以及一些文本,同时创建一个新项目,当您按下同一个 xml 中的按钮时。模拟我的应用程序会导致垃圾收集器“发疯”,并且我的应用程序不断跳帧。如标题所述,它甚至在 S3 上崩溃(拍照后)。尽管我一直在网上搜索可能的改进 (ViewHolder),但它们无济于事,甚至会导致错误。
所以这是我工作中的 MainActivity,其中我得到了最好的改进:
<!-- language: lang-java -->
public class MainActivity extends Activity {
List<FavImages> FavImages = new ArrayList<FavImages>();
ListView favImageListView;
Bitmap bitmap;
final Context context = this;
private SharedPreferences mPrefs;
private SharedPreferences.Editor mEditor;
//label logs
private static String logtag = "CameraApp";
//use main camera
private static int TAKE_PICTURE = 1;
private Uri imageUri;
public Uri imagePath = Uri.parse("android.resource://com.adrianopaulus/drawable/no_picture.png");
DataBaseHandler dbHandler;
int longClickedItemIndex;
ArrayAdapter<FavImages> favImagesAdapter;
private static final int EDIT = 0, DELETE = 1;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
favImageListView = (ListView) findViewById(R.id.listView);
dbHandler = new DataBaseHandler(getApplicationContext());
mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
mEditor = mPrefs.edit();
//enter an Item
registerForContextMenu(favImageListView);
//maybe without long
favImageListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
//position of Item
longClickedItemIndex = position;
return false;
}
});
if (dbHandler.getFavCount() != 0) {
FavImages.addAll(dbHandler.getAllFav());
}
//List<FavImages> addableFavs = dbHandler.getAllFav();
//if (!addableFavs.isEmpty())
populateList();
//Button Action
Button cameraButton = (Button)findViewById(R.id.button_camera);
cameraButton.setOnClickListener(cameraListener);
}
private OnClickListener cameraListener = new OnClickListener(){
public void onClick(View v){
takePhoto(v);
}
};
//launch native camera app
private void takePhoto(View v){
final Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//save Image and create file
// in Progress
LayoutInflater factory = LayoutInflater.from(this);
final View textEntryView = factory.inflate(R.layout.text_entry, null);
final EditText input1 = (EditText) textEntryView.findViewById(R.id.pictureName);
final AlertDialog.Builder alert = new AlertDialog.Builder(this);
//create Dialog
alert
.setTitle("Bitte bennenen Sie Ihr Bild!")
.setView(textEntryView)
.setPositiveButton(R.string.alert_dialog_ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
Log.i("AlertDialog","TextEntry 1 Entered "+input1.getText().toString());
/* User clicked OK so do some stuff */
String inputText = input1.getText().toString();
mEditor.putString("pictureName", inputText);
mEditor.commit();
File photo = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), replaceChars(mPrefs.getString("pictureName", "picture")) + ".jpg");
//access information of file
imageUri = Uri.fromFile(photo);
//save image path information
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
//for favImages
imagePath = imageUri;
mEditor.putString("picturePath", imagePath.toString());
mEditor.commit();
//
startActivityForResult(intent, TAKE_PICTURE);
//
Log.e("Dateipfad", imagePath.toString());
FavImages favImages = new FavImages(dbHandler.getFavCount(), mPrefs.getString("pictureName", "Bild"), imagePath);
dbHandler.createFav(favImages);
}
});
//show Dialog
alert.show();
}
public String replaceChars (String inputText){
inputText = inputText.replace("ä","ae");
inputText = inputText.replace("ö","oe");
inputText = inputText.replace("ü","ue");
inputText = inputText.replace("ß","ss");
return inputText;
}
//deal with output
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent){
super.onActivityResult(requestCode, resultCode, intent);
//user hits ok button (picture accepted)
if(resultCode == Activity.RESULT_OK){
//Uri selectedImage = imageUri;
//communication between apps
getContentResolver().notifyChange(imageUri, null);
/*get Image
//ImageView imageView = (ImageView)findViewById(R.id.image_camera);
//hold Image data
ContentResolver cr = getContentResolver();
Bitmap bitmap;
//get bitmap data
try {
bitmap = MediaStore.Images.Media.getBitmap(cr, selectedImage);
//set Image
imageView.setImageBitmap(bitmap);
//notify user of success
Toast.makeText(MainActivity.this, selectedImage.toString(), Toast.LENGTH_LONG).show();
}catch (Exception e){ //catch exceptions along the way
Log.e(logtag, e.toString());
} */
List<FavImages> addableFavs = dbHandler.getAllFav();
int favCount = dbHandler.getFavCount();
//for(int i = 0; i < favCount; i++){
FavImages.add(addableFavs.get(favCount-1));
if (!addableFavs.isEmpty())
populateList();
}
}
//
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo){
super.onCreateContextMenu(menu, view, menuInfo);
menu.setHeaderTitle("Favorit bearbeiten");
menu.add(Menu.NONE, DELETE, menu.NONE, "Favorit löschen");
}
public boolean onContextItemSelected (MenuItem item){
switch (item.getItemId()){
case EDIT:
//TODO: edit Favorite
break;
case DELETE:
//delete Favorite
dbHandler.deleteFav(FavImages.get(longClickedItemIndex));
FavImages.remove(longClickedItemIndex);
favImagesAdapter.notifyDataSetChanged();
break;
}
return super.onContextItemSelected(item);
}
private void populateList(){
//ArrayAdapter<FavImages> adapter = new favImagesListAdapter();
//favImageListView.setAdapter(adapter);
favImagesAdapter = new favImagesListAdapter();
favImageListView.setAdapter(favImagesAdapter);
}
static class ViewHolder {
private TextView imageTextView;
private ImageView favImageView;
}
//Constructor for List Items
private class favImagesListAdapter extends ArrayAdapter<FavImages>{
public favImagesListAdapter(){
super (MainActivity.this, R.layout.listview_item, FavImages);
}
@Override
public View getView (int position, View view, ViewGroup parent){
if (view == null) {
view = getLayoutInflater().inflate(R.layout.listview_item, parent, false);
}
FavImages currentFav = FavImages.get(position);
TextView favName = (TextView) view.findViewById(R.id.favName);
favName.setText(currentFav.getImageName());
ImageView ivFavsImage = (ImageView) view.findViewById(R.id.favImage);
//hold Image data
ContentResolver cr = getContentResolver();
try {
bitmap = MediaStore.Images.Media.getBitmap(cr, currentFav.getImagePath());
//set Image
ivFavsImage.setImageBitmap(bitmap);
}catch (Exception e){ //catch exceptions along the way
Log.e(logtag, e.toString());
}
return view;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
}
总结一下: 如何使我的应用程序占用更少的内存?
编辑:来自 logcat 的部分堆栈跟踪
02-12 20:00:19.945 948-948/com.adrianopaulus.favoriten I/AlertDialog﹕ TextEntry 1 Entered b
02-12 20:00:20.095 948-948/com.adrianopaulus.favoriten E/Dateipfad﹕ file:///mnt/sdcard/Pictures/b.jpg
02-12 20:00:23.295 948-948/com.adrianopaulus.favoriten W/IInputConnectionWrapper﹕ showStatusIcon on inactive InputConnection
02-12 20:00:29.335 948-948/com.adrianopaulus.favoriten D/dalvikvm﹕ GC_FOR_ALLOC freed 1337K, 6% free 23771K/25287K, paused 31ms, total 49ms
02-12 20:00:29.436 948-948/com.adrianopaulus.favoriten D/dalvikvm﹕ GC_FOR_ALLOC freed 1311K, 7% free 23693K/25287K, paused 31ms, total 48ms
02-12 20:00:29.526 948-948/com.adrianopaulus.favoriten D/dalvikvm﹕ GC_FOR_ALLOC freed 1239K, 7% free 23686K/25287K, paused 29ms, total 30ms
02-12 20:00:29.616 948-948/com.adrianopaulus.favoriten D/dalvikvm﹕ GC_FOR_ALLOC freed 1232K, 7% free 23687K/25287K, paused 28ms, total 29ms
02-12 20:00:29.766 948-948/com.adrianopaulus.favoriten W/EGL_emulation﹕ eglSurfaceAttrib not implemented
02-12 20:00:29.865 948-948/com.adrianopaulus.favoriten D/dalvikvm﹕ GC_FOR_ALLOC freed 1233K, 7% free 23687K/25287K, paused 97ms, total 101ms
02-12 20:00:30.075 948-948/com.adrianopaulus.favoriten D/dalvikvm﹕ GC_FOR_ALLOC freed 1233K, 7% free 23690K/25287K, paused 35ms, total 38ms
02-12 20:00:30.175 948-948/com.adrianopaulus.favoriten D/dalvikvm﹕ GC_FOR_ALLOC freed 32K, 2% free 24895K/25287K, paused 28ms, total 29ms
02-12 20:00:30.275 948-948/com.adrianopaulus.favoriten D/dalvikvm﹕ GC_FOR_ALLOC freed 32K, 2% free 26099K/26503K, paused 31ms, total 32ms
02-12 20:00:30.345 948-948/com.adrianopaulus.favoriten I/Choreographer﹕ Skipped 64 frames! The application may be doing too much work on its main thread.
编辑 2:新的 ListAdapter :
static class ViewHolder {
TextView imageTextView;
ImageView favImageView;
}
//Constructor for List Items
private class favImagesListAdapter extends ArrayAdapter<FavImages>{
private LayoutInflater mInflater = LayoutInflater.from(context);
public favImagesListAdapter(){
super (MainActivity.this, R.layout.listview_item, FavImages);
}
@Override
public View getView (int position, View convertView, ViewGroup parent){
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.listview_item, parent, false);
holder = new ViewHolder();
holder.imageTextView = (TextView) convertView.findViewById(R.id.favName);
holder.favImageView = (ImageView) convertView.findViewById(R.id.favImage);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
FavImages currentFav = FavImages.get(position);
holder.imageTextView.setText(currentFav.getImageName());
ContentResolver cr = getContentResolver();
try {
holder.favImageView.setImageBitmap(MediaStore.Images.Media.getBitmap(cr, currentFav.getImagePath()));
} catch (IOException e) {
e.printStackTrace();
}
return convertView;
}
}
【问题讨论】:
-
至少从 logcat 发布堆栈跟踪。
-
好的,只需再次运行应用程序 - 片刻
-
您发布的Logcat中没有错误。 “崩溃”在哪里?
-
崩溃发生在 Android 设备上,目前不可用,发布的日志来自模拟设备。
-
如果您的标题显示“崩溃”,请从“崩溃”发布堆栈跟踪
标签: android performance listview