Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android app with database constantly "starting/waiting for a blocking gc alloc"

Tags:

android

sqlite

I've looked through specifically the addButtonClicked() method and the DBHandler itself. I can't figure out why the program basically gets stuck in an infinite loop when I try to add something to the database. Every time I run it and try to add something to the database it just freezes and gives this message over and over and over.

Error:

10-27 20:34:50.303 2849-2849/? I/art: Not late-enabling -Xcheck:jni (already on)
10-27 20:34:50.303 2849-2849/? I/art: Late-enabling JIT
10-27 20:34:50.312 2849-2849/? I/art: JIT created with code_cache_capacity=2MB compile_threshold=1000
10-27 20:34:50.408 2849-2849/com.example.test.assignment W/System: ClassLoader referenced unknown path: /data/app/com.example.test.assignment-2/lib/x86
10-27 20:34:50.966 2849-2860/com.example.test.assignment W/art: Suspending all threads took: 6.223ms
10-27 20:34:51.033 2849-2860/com.example.test.assignment I/art: Background partial concurrent mark sweep GC freed 423(15KB) AllocSpace objects, 418(7MB) LOS objects, 38% free, 6MB/10MB, paused 6.686ms total 54.772ms
10-27 20:34:51.577 2849-2860/com.example.test.assignment W/art: Suspending all threads took: 6.097ms
10-27 20:34:51.816 2849-2860/com.example.test.assignment I/art: WaitForGcToComplete blocked for 11.994ms for cause Background
10-27 20:34:52.017 2849-2860/com.example.test.assignment W/art: Suspending all threads took: 9.393ms
10-27 20:34:52.023 2849-2860/com.example.test.assignment I/art: Background sticky concurrent mark sweep GC freed 845(30KB) AllocSpace objects, 843(41MB) LOS objects, 76% free, 1233KB/5MB, paused 10.623ms total 31.789ms
10-27 20:34:52.132 2849-2860/com.example.test.assignment I/art: Background partial concurrent mark sweep GC freed 752(27KB) AllocSpace objects, 747(37MB) LOS objects, 15% free, 21MB/25MB, paused 20.980ms total 40.058ms
10-27 20:34:53.000 2849-2849/com.example.test.assignment I/art: Waiting for a blocking GC Alloc
10-27 20:34:53.001 2849-2849/com.example.test.assignment I/art: Starting a blocking GC Alloc
10-27 20:34:53.123 2849-2849/com.example.test.assignment I/art: Waiting for a blocking GC Alloc
10-27 20:34:53.126 2849-2849/com.example.test.assignment I/art: Starting a blocking GC Alloc
10-27 20:34:53.195 2849-2849/com.example.test.assignment I/art: Waiting for a blocking GC Alloc
10-27 20:34:53.205 2849-2849/com.example.test.assignment I/art: WaitForGcToComplete blocked for 10.178ms for cause Alloc

It just keeps running that over and over and the printSelectedDatabase() is never ran because it doesn't show in the text view.

Main Activity:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    EditText dataInput;
    TextView showText;
    DBHandler dbHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dataInput = (EditText) findViewById(R.id.dataInput);
        showText = (TextView) findViewById(R.id.showText);
        dbHandler = new DBHandler(this, null, null, 1);
        printSelectedDatabase();
    }

    public void addButtonClicked(View view){
        Animals animal = new Animals(dataInput.getText().toString());
        dbHandler.addAnimal(animal);
        printSelectedDatabase();
    }

    public void deleteButtonClicked(View view){
        String string = dataInput.getText().toString();
        dbHandler.deleteAnimal(string);
        printSelectedDatabase();
    }

    public void printSelectedDatabase(){
        String string = dbHandler.printDatabase();
        showText.setText(string);
        dataInput.setText("");
    }
}

Setter/Getters:

public class Animals {

    private int _id;
    private String _animalName;

    public Animals(){

    }

    public Animals(String animalName) {
        this._animalName = animalName;
    }

    public void set_id(int _id) {
        this._id = _id;
    }

    public void set_animalname(String _animalName) {
        this._animalName = _animalName;
    }

    public int get_id() {
        return _id;
    }

    public String get_animalName() {
        return _animalName;
    }
}

DBHandler:

import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.Cursor;
import android.content.Context;
import android.content.ContentValues;

public class DBHandler extends SQLiteOpenHelper {

    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "animals.db";
    public static final String TABLE_ANIMALS = "animals";
    public static final String COLUMN_ID = "_id";
    public static final String COLUMN_ANIMALS = "animalName";

    public DBHandler(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, DATABASE_NAME, factory, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String query = "CREATE TABLE " + TABLE_ANIMALS + "(" +
                COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                COLUMN_ANIMALS + " TEXT " +
                ");";
        db.execSQL(query);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_ANIMALS);
        onCreate(db);
    }

    //Add Animal
    public void addAnimal(Animals animal){
        ContentValues values = new ContentValues();
        values.put(COLUMN_ANIMALS, animal.get_animalName());
        SQLiteDatabase db = getWritableDatabase();
        db.insert(TABLE_ANIMALS, null, values);
        db.close();
    }
    //Delete Animal
    public  void deleteAnimal(String animalName){
        SQLiteDatabase db = getWritableDatabase();
        db.execSQL("DELETE FROM " + TABLE_ANIMALS + " WHERE " + COLUMN_ANIMALS + "=\"" + animalName + "\";");
    }

    //Print Animals
    public String printDatabase(){
        String string = "";
        SQLiteDatabase db = getWritableDatabase();
        String query = "SELECT * FROM " + TABLE_ANIMALS + " WHERE 1";
        Cursor cursor = db.rawQuery(query, null);
        cursor.moveToFirst();
        while(!cursor.isAfterLast()){
            if(cursor.getString(cursor.getColumnIndex("animalName"))!=null){
                string += cursor.getString(cursor.getColumnIndex("animalName"));
                string += "\n";
            }
        }
        db.close();
        return string;
    }


}
like image 366
Student Avatar asked Oct 28 '15 02:10

Student


2 Answers

Figured it out in case anyone happens to run into this particular error. In my DBHandler I was missing a go to next line within the while statement.

Original:

 while(!cursor.isAfterLast()){
                if(cursor.getString(cursor.getColumnIndex("animalName"))!=null){
                    string += cursor.getString(cursor.getColumnIndex("animalName"));
                    string += "\n";
                }
            }

Should be:

while(!cursor.isAfterLast()){
            if(cursor.getString(cursor.getColumnIndex("animalName"))!=null){
                string += cursor.getString(cursor.getColumnIndex("animalName"));
                string += "\n";
            }
            cursor.moveToNext();
        }
like image 87
Student Avatar answered Oct 02 '22 01:10

Student


Just to add on your answer. Instead of:

while(!cursor.isAfterLast()){
   // do stuff with cursor
    cursor.moveToNext();
}

your code would be more concise with:

while (cursor.moveToNext()) {
    // do stuff with cursor
}

When you do a query, the Cursor object is positioned BEFORE the first entry. The call to cursor.moveToNext() moves to the next position AND returns true if there is actually a record to move to and false otherwise.

Also, avoid calling cursor.getColumnIndex("columnName") from within a loop. You are better off caching the column index in an int variable and referring to that variable inside the loop.

int animalNameColumn = cursor.getColumnIndex("animalName");
while (cursor.moveToNext()) {
       if(cursor.getString(animalNameColumn)!=null){
            string += cursor.getString(animalNameColumn);
            string += "\n";
        }
}
like image 40
Gichamba Avatar answered Oct 02 '22 01:10

Gichamba