Search code examples
androidandroid-listviewandroid-edittextcustom-adapter

android listview with custom adapter freezes activity


I want to do something similar to the EditContact activity (add various numbers to contact with a simple add button).

My first approach was to create custom layouts which I dynamically add to the activitie layout ( Activity with dynamicly added components freezes ) The user Budius mentioned to use listview with custom adapter to achieve a solution. So i tried it, but the behavior ends like my first try.

After adding 3-4 entries the activity freezes. (on a galaxy s3 and the emulator)

Maybe you have an idea?

Logcat:

11-01 15:42:33.214: D/dalvikvm(712): GC_CONCURRENT freed 148K, 3% free 8283K/8519K, paused 74ms+102ms, total 242ms
11-01 15:42:33.733: I/Choreographer(712): Skipped 93 frames!  The application may be doing too much work on its main thread.
11-01 15:42:42.293: I/Choreographer(712): Skipped 49 frames!  The application may be doing too much work on its main thread.
11-01 15:42:44.946: D/dalvikvm(712): GC_CONCURRENT freed 72K, 2% free 8672K/8839K, paused 16ms+36ms, total 224ms
11-01 15:42:45.593: I/Choreographer(712): Skipped 66 frames!  The application may be doing too much work on its main thread.
11-01 15:42:48.913: I/Choreographer(712): Skipped 35 frames!  The application may be doing too much work on its main thread.
11-01 15:42:49.093: I/Choreographer(712): Skipped 42 frames!  The application may be doing too much work on its main thread.
11-01 15:42:55.083: I/Choreographer(712): Skipped 125 frames!  The application may be doing too much work on its main thread.
11-01 15:42:55.343: I/Choreographer(712): Skipped 68 frames!  The application may be doing too much work on its main thread.
11-01 15:42:55.653: I/Choreographer(712): Skipped 40 frames!  The application may be doing too much work on its main thread.
11-01 15:43:02.553: D/dalvikvm(712): GC_CONCURRENT freed 318K, 5% free 8821K/9223K, paused 16ms+68ms, total 231ms
11-01 15:43:02.863: D/dalvikvm(712): GC_FOR_ALLOC freed 418K, 7% free 8800K/9415K, paused 73ms, total 76ms
11-01 15:43:02.883: I/Choreographer(712): Skipped 224 frames!  The application may be doing too much work on its main thread.
11-01 15:43:03.013: D/dalvikvm(712): GC_CONCURRENT freed 397K, 7% free 8804K/9415K, paused 74ms+6ms, total 113ms
11-01 15:43:03.013: D/dalvikvm(712): WAIT_FOR_CONCURRENT_GC blocked 33ms
11-01 15:43:03.063: D/dalvikvm(712): GC_FOR_ALLOC freed 386K, 7% free 8802K/9415K, paused 41ms, total 41ms
11-01 15:43:03.183: D/dalvikvm(712): GC_CONCURRENT freed 388K, 7% free 8806K/9415K, paused 75ms+7ms, total 119ms
11-01 15:43:03.183: D/dalvikvm(712): WAIT_FOR_CONCURRENT_GC blocked 35ms
11-01 15:43:03.243: D/dalvikvm(712): GC_FOR_ALLOC freed 378K, 7% free 8803K/9415K, paused 51ms, total 51ms
11-01 15:43:03.433: I/Choreographer(712): Skipped 142 frames!  The application may be doing too much work on its main thread.
comment:..... adding the 4. row to custom adapter and listview ..... 
11-01 15:36:31.662: I/Choreographer(712): Skipped 36 frames!  The application may be doing too much work on its main thread.
11-01 15:36:32.542: D/dalvikvm(712): GC_CONCURRENT freed 415K, 23% free 9057K/11719K, paused 18ms+15ms, total 139ms
11-01 15:36:32.554: D/dalvikvm(712): WAIT_FOR_CONCURRENT_GC blocked 123ms
11-01 15:36:32.613: D/dalvikvm(712): GC_FOR_ALLOC freed 492K, 23% free 9046K/11719K, paused 56ms, total 56ms
11-01 15:36:32.753: D/dalvikvm(712): GC_CONCURRENT freed 449K, 23% free 9078K/11719K, paused 76ms+7ms, total 134ms
11-01 15:36:32.753: D/dalvikvm(712): WAIT_FOR_CONCURRENT_GC blocked 48ms
11-01 15:36:32.813: D/dalvikvm(712): GC_FOR_ALLOC freed 514K, 23% free 9046K/11719K, paused 54ms, total 54ms
11-01 15:36:32.943: D/dalvikvm(712): GC_CONCURRENT freed 451K, 23% free 9078K/11719K, paused 76ms+8ms, total 128ms
11-01 15:36:32.943: D/dalvikvm(712): WAIT_FOR_CONCURRENT_GC blocked 44ms
11-01 15:36:33.013: D/dalvikvm(712): GC_FOR_ALLOC freed 516K, 23% free 9046K/11719K, paused 53ms, total 53ms
11-01 15:36:33.143: D/dalvikvm(712): GC_CONCURRENT freed 453K, 23% free 9078K/11719K, paused 75ms+9ms, total 127ms
11-01 15:36:33.143: D/dalvikvm(712): WAIT_FOR_CONCURRENT_GC blocked 41ms
11-01 15:36:33.193: D/dalvikvm(712): GC_FOR_ALLOC freed 518K, 23% free 9046K/11719K, paused 50ms, total 50ms
11-01 15:36:33.333: D/dalvikvm(712): GC_CONCURRENT freed 454K, 23% free 9078K/11719K, paused 75ms+8ms, total 137ms
11-01 15:36:33.333: D/dalvikvm(712): WAIT_FOR_CONCURRENT_GC blocked 59ms
11-01 15:36:33.393: D/dalvikvm(712): GC_FOR_ALLOC freed 520K, 23% free 9046K/11719K, paused 56ms, total 56ms
11-01 15:36:33.533: D/dalvikvm(712): GC_CONCURRENT freed 456K, 23% free 9079K/11719K, paused 75ms+8ms, total 129ms
11-01 15:36:33.533: D/dalvikvm(712): WAIT_FOR_CONCURRENT_GC blocked 52ms
comment:..... many of this .....
11-01 15:40:05.064: D/dalvikvm(712): GC_FOR_ALLOC freed 451K, 23% free 9135K/11719K, paused 97ms, total 97ms
11-01 15:40:05.204: D/dalvikvm(712): GC_CONCURRENT freed 451K, 23% free 9135K/11719K, paused 76ms+6ms, total 136ms
11-01 15:40:05.204: D/dalvikvm(712): WAIT_FOR_CONCURRENT_GC blocked 47ms
11-01 15:40:05.293: D/dalvikvm(712): GC_FOR_ALLOC freed 451K, 23% free 9135K/11719K, paused 66ms, total 66ms
11-01 15:40:05.443: D/dalvikvm(712): GC_CONCURRENT freed 451K, 23% free 9135K/11719K, paused 76ms+6ms, total 148ms
11-01 15:40:05.443: D/dalvikvm(712): WAIT_FOR_CONCURRENT_GC blocked 67ms
11-01 15:40:05.513: D/dalvikvm(712): GC_FOR_ALLOC freed 451K, 23% free 9135K/11719K, paused 59ms, total 59ms
11-01 15:40:05.643: D/dalvikvm(712): GC_CONCURRENT freed 451K, 23% free 9135K/11719K, paused 76ms+7ms, total 127ms
11-01 15:40:05.643: D/dalvikvm(712): WAIT_FOR_CONCURRENT_GC blocked 41ms
11-01 15:40:05.703: D/dalvikvm(712): GC_FOR_ALLOC freed 451K, 23% free 9135K/11719K, paused 56ms, total 56ms
11-01 15:40:05.833: D/dalvikvm(712): GC_CONCURRENT freed 451K, 23% free 9135K/11719K, paused 75ms+7ms, total 127ms
11-01 15:40:05.833: D/dalvikvm(712): WAIT_FOR_CONCURRENT_GC blocked 42ms
11-01 15:40:05.913: D/dalvikvm(712): GC_FOR_ALLOC freed 451K, 23% free 9135K/11719K, paused 63ms, total 63ms
11-01 15:40:06.114: D/dalvikvm(712): GC_CONCURRENT freed 451K, 23% free 9135K/11719K, paused 76ms+39ms, total 196ms
11-01 15:40:06.114: D/dalvikvm(712): WAIT_FOR_CONCURRENT_GC blocked 118ms
11-01 15:40:06.963: E/Trace(734): error opening trace file: No such file or directory (2)
11-01 15:40:07.953: D/gralloc_goldfish(734): Emulator without GPU emulation detected.

here is my activity:

package com.float.rezepte;

import java.io.File;
import java.util.ArrayList;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RatingBar;
import android.widget.TextView;
import android.widget.Toast;

import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.float.utilities.ImageProcessing;
import com.float.utilities.Utilities;

public class AddRecipeActivity extends SherlockActivity {

private EditText editTextName;
private EditText editTextDescription;
private EditText editTextDuration;
private EditText editTextPortions;
private EditText editTextPortionsUnit;
private RatingBar ratingBarDifficutly;
private ImageView imageViewPicture;
private static final int SELECT_PICTURE = 1;
private static final int TAKE_PICTURE = 2;
public boolean deletePicture = false;
private String selectedImagePath;
private byte[] recipePicture = null;
private Recipe recipe;
private ProgressDialog dialog;
private IngredientAdapter ingredientAdapter;
private ImageButton imageButtonAddIngredient;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_add_recipe);
    ConnectView();
    ArrayList<Ingredient> values;

    if (savedInstanceState != null)
    {
        recipe = savedInstanceState.getParcelable("recipe");
        editTextName.setText(recipe.getName());
        editTextDescription.setText(recipe.getDescription());
        editTextDuration.setText(String.valueOf(recipe.getDuration()));
        editTextPortions.setText(String.valueOf(recipe.getPortions()));
        editTextPortionsUnit.setText(recipe.getPortionsUnit());
        ratingBarDifficutly.setRating(recipe.getDifficulty());
        values = (ArrayList<Ingredient>) recipe.getIngredientList();
    }else{
        recipe = new Recipe();
        values = new ArrayList<Ingredient>();
    }

    ingredientAdapter = new IngredientAdapter(this, values); 
    final ListView listViewIngredients = (ListView) findViewById(R.id.listViewIngredients);
    listViewIngredients.setAdapter(ingredientAdapter);

    imageButtonAddIngredient.setOnClickListener(new OnClickListener(){
        @Override
        public void onClick(View v) {
            ingredientAdapter.addItem(new Ingredient());
            ingredientAdapter.notifyDataSetChanged();
            Utilities.setListViewHeightBasedOnChildren(listViewIngredients);
        }
    });

    final ViewTreeObserver observer = imageViewPicture.getViewTreeObserver();
       observer.addOnGlobalLayoutListener (new OnGlobalLayoutListener () {
            @Override
            public void onGlobalLayout() {          
                imageViewPicture.getViewTreeObserver().addOnGlobalLayoutListener(this);
                if(recipe.getPicture() != null){
                    imageViewPicture.setImageBitmap(ImageProcessing.scaleImage(recipe.getPicture(), imageViewPicture.getWidth(), imageViewPicture.getHeight()));
                }
            }
        });
}

private void ConnectView(){
    editTextName = (EditText) findViewById(R.id.editTextName);
    editTextDescription = (EditText) findViewById(R.id.editTextDescription);
    editTextDuration = (EditText) findViewById(R.id.editTextDuration);
    editTextPortions = (EditText) findViewById(R.id.editTextPortions);
    editTextPortionsUnit = (EditText) findViewById(R.id.editTextPortionsUnit);
    ratingBarDifficutly = (RatingBar) findViewById(R.id.ratingBarDifficulty);
    imageViewPicture = (ImageView) findViewById(R.id.imageViewPicture);
    imageButtonAddIngredient = (ImageButton) findViewById(R.id.imageButtonAddIngredient);
}

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
  super.onSaveInstanceState(savedInstanceState);
  savedInstanceState.putParcelable("recipe", copyUserInputToRecipe());
}

private Recipe copyUserInputToRecipe(){
    recipe.setName(editTextName.getText().toString());
    recipe.setDescription(editTextDescription.getText().toString());
    recipe.setDifficulty(ratingBarDifficutly.getRating());
    if(!editTextDuration.getText().toString().equals("")){
        recipe.setDuration(Integer.parseInt(editTextDuration.getText().toString()));
    }
    if(!editTextPortions.getText().toString().equals("")){
        recipe.setPortions(Integer.parseInt(editTextPortions.getText().toString()));
    }
    recipe.setPortionsUnit(editTextPortionsUnit.getText().toString());
    if(recipePicture != null){
        recipe.setPicture(recipePicture);
    }
    return recipe;
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getSupportMenuInflater().inflate(R.menu.activity_add_recipe, menu);
    return true;
}

@Override
public void onBackPressed() {
    super.onBackPressed();
    overridePendingTransition(android.R.anim.fade_in,
            android.R.anim.fade_out);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.menu_cancel_recipe:
        finish();
        break;
    case R.id.menu_save_recipe:
            Intent returnIntent = new Intent();
            returnIntent.putExtra("recipe", recipe);
            setResult(RESULT_OK, returnIntent);
            finish();

        break;
    }
    return super.onOptionsItemSelected(item);
}
}

EDIT: The ViewTreeObserver is the problem. After removing it, no freezes came up.


Solution

  • So you store the image bytes to reuse when device orientation changes...

    You can detect device orientation changes by overriding

        onConfigurationChanged(Configuration newConfig) 
    

    method in your activity. Read on http://developer.android.com/reference/android/app/Activity.html#onConfigurationChanged(android.content.res.Configuration)

    and

    http://developer.android.com/reference/android/content/res/Configuration.html

    Make sure to specify

        android:configChanges="orientation" 
    

    in the manifest entry for that activity. With this you can detect if the device is in portrait or landscape orientation. Most importantly this will only be triggered when the device orientation is changed (unlike the global layout listener which fires up with every slight change on the screen).

    Hope this will help.