1

Yesterday I made a nice listView to see my database, but today I tried to add on line to my database and I got an error message saying something like "Database leaked. blabla close your database". After that I could not add anymore line to my database.

But I restarted android studio and I could add new line (and no error anymore) ! BUT I can't see the news lines that I add. I only see my line that I added BEFORE my error (or maybe I can see the one I added that caused me the error). I checked my database with chrome and I see everything, so I really added news lines !

I don't know what is up, I checked my history for several class but I didn't make any bad change (I think). How can I see all my database again ? I also use a ContentProvider to access my database.

Here is my Fragment class with my list view (I use 2 button inside my elements from my list view and some TextView) :

public class ViewCardEditor extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
    public static final String authority = "com.example.jean.cartememoire.CardContentProvider";
    public String[] from;
    public final int[] to = {R.id.idList, R.id.themeList, R.id.questionList, R.id.reponseList, R.id.difficultList};
    StockCard stock;
    ViewGroup container;
    ListView listView;
    MySimpleCursorAdapter adapter;
    private ArrayList<String> data = new ArrayList<String>();



    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup c,
                             Bundle savedInstanceState) {
        container = c;
        View view = inflater.inflate(R.layout.fragment_view_card_editor, container, false);
        stock = StockCard.getInstance(container.getContext());
        from = new String[]{stock._ID,
                stock.THEME,
                stock.QUESTION,
                stock.REPONSE,
                stock.DIFFICULTE};

        // Inflate the layout for this fragment
        if (container != null) {
            container.removeAllViews();
        }
        databaseView(view);

        return view;
    }

    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        Uri.Builder builder = new Uri.Builder();
        Uri uri = builder.scheme("content").authority(authority)
                .appendPath(stock.STOCK_TABLE).build();
        return new CursorLoader(container.getContext(), uri, from,
                null, null, null);
    }
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        adapter.swapCursor(data);
    }
    public void onLoaderReset(Loader<Cursor> loader) {
        adapter.swapCursor(null);
    }



    public void databaseView(View view)
    {
        ArrayList<String> list;
        Cursor cursor = stock.getData();

        listView = (ListView) view.findViewById(R.id.listView);

        adapter = new MySimpleCursorAdapter(container.getContext(), R.layout.card_stock, null, from, to,0);
        listView.setAdapter(adapter);

        LoaderManager manager = getLoaderManager();
        manager.initLoader(0, null, this);

    }


    public void deleteOneCard(int id)
    {
        Uri.Builder builder = new Uri.Builder();
        builder.scheme("content").authority(authority).appendPath(stock.STOCK_TABLE);

        ContentUris.appendId(builder, id);
        Uri uri = builder.build();
        ContentResolver resolver = container.getContext().getContentResolver();
        resolver.delete(uri, null, null);

    }

    private class MySimpleCursorAdapter extends SimpleCursorAdapter
    {
        ViewHolder vh;
        public MySimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
            super(context, layout, c, from, to, flags);

        }

        public View newView(Context _context, Cursor _cursor, ViewGroup parent) {
            LayoutInflater inflater = (LayoutInflater) _context.getSystemService(_context.LAYOUT_INFLATER_SERVICE);
            View view = inflater.inflate(R.layout.card_stock, parent, false);
            vh = new ViewHolder();
            vh.idList = (TextView) view.findViewById(R.id.idList);
            vh.themeList = (TextView) view.findViewById(R.id.themeList);
            vh.questionList = (TextView) view.findViewById(R.id.questionList);
            vh.reponseList = (TextView) view.findViewById(R.id.reponseList);
            vh.difficulteList = (TextView) view.findViewById(R.id.difficultList);
            vh.Supprimer = (Button) view.findViewById(R.id.buttonDelete);
            vh.Modifier = (Button) view.findViewById(R.id.buttonModifier);


            view.setTag(vh);
            return view;
        }

        public void bindView(View view, Context Context, Cursor cursor) {
            vh.idList.setText(cursor.getString(cursor.getColumnIndex(stock._ID)));
            vh.themeList.setText(cursor.getString(cursor.getColumnIndex(stock.THEME)));
            vh.questionList.setText(cursor.getString(cursor.getColumnIndex(stock.QUESTION)));
            vh.reponseList.setText(cursor.getString(cursor.getColumnIndex(stock.REPONSE)));
            vh.difficulteList.setText(cursor.getString(cursor.getColumnIndex(stock.DIFFICULTE)));

            vh.Supprimer.setOnClickListener(new View.OnClickListener()
            {
                public void onClick(View v) {
                    View parentView = (View)v.getParent();
                    TextView idList = (TextView) parentView.findViewById(R.id.idList);
                    /*TextView themeList = (TextView) parentView.findViewById(R.id.themeList);
                    TextView questionList = (TextView) parentView.findViewById(R.id.questionList);
                    TextView reponseList = (TextView) parentView.findViewById(R.id.reponseList);
                    TextView difficulteList = (TextView) parentView.findViewById(R.id.difficultList);*/

                    int id = Integer.parseInt(idList.getText().toString());
                    deleteOneCard(id);
                    Toast.makeText(container.getContext(), "Suppression de "+id, Toast.LENGTH_SHORT).show();
                }
            });

            vh.Modifier.setOnClickListener(new View.OnClickListener()
            {
                public void onClick(View v) {
                    View parentView = (View)v.getParent();
                    TextView idList = (TextView) parentView.findViewById(R.id.idList);
                    TextView themeList = (TextView) parentView.findViewById(R.id.themeList);
                    themeList.setFocusable(true);
                    themeList.requestFocus();
                    /*TextView questionList = (TextView) parentView.findViewById(R.id.questionList);
                    TextView reponseList = (TextView) parentView.findViewById(R.id.reponseList);
                    TextView difficulteList = (TextView) parentView.findViewById(R.id.difficultList);*/

                    int id = Integer.parseInt(idList.getText().toString());
                    Toast.makeText(container.getContext(), "bouton Modifier pour "+id, Toast.LENGTH_SHORT).show();
                }
            });

        }
    }



    public class ViewHolder
    {
        Button Supprimer, Modifier;
        TextView idList, themeList, questionList, reponseList, difficulteList;

    }
}

Here my class for adding news lines :

public class AddCardEditor extends Fragment {
    EditText editTheme, editQuest, editRep;
    RatingBar ratingBar;
    Button buttonCreateCard;
    CardContentProvider stock;
    ViewGroup container;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup c,
                             Bundle savedInstanceState) {
        View view;
        view = inflater.inflate(R.layout.fragment_add_card_editor, container, false);
        // Inflate the layout for this fragment
        container = c;
        if (container != null) {
            container.removeAllViews();
        }
        editTheme =(EditText) view.findViewById(R.id.editTheme);
        editQuest =(EditText) view.findViewById(R.id.editQuest);
        editRep =(EditText) view.findViewById(R.id.editRep);
        ratingBar =(RatingBar) view.findViewById(R.id.ratingBar);
        buttonCreateCard =(Button) view.findViewById(R.id.buttonCreateCard);
        stock = new CardContentProvider();
        addData(container);
        return view;
    }

    public void addData(final ViewGroup container)
    {

            buttonCreateCard.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    try
                    {
                        ContentValues cv = new ContentValues();
                        CardContentProvider cp = new CardContentProvider();
                        cv.put(stock.THEME, editTheme.getText().toString());
                        cv.put(stock.QUESTION, editQuest.getText().toString());
                        cv.put(stock.REPONSE, editRep.getText().toString());
                        cv.put(stock.DIFFICULTE, ratingBar.getRating());

                        ContentResolver resolver = container.getContext().getContentResolver();
                        Uri.Builder builder = new Uri.Builder();
                        System.out.println("addDATA DEBUG");
                        builder.scheme("content").authority(stock.authority).appendPath(stock.STOCK_TABLE);
                        System.out.println("addDATA DEBUG2");
                        Uri uri = builder.build();
                        uri = resolver.insert(uri,cv);
                        long id = ContentUris.parseId(uri);
                        System.out.println("addDATA DEBUG3 : "+id);
                        Toast.makeText(container.getContext(), "Carte créé avec succès !", Toast.LENGTH_SHORT).show();
                    }
                    catch (Exception e)
                    {
                        Toast.makeText(container.getContext(), "Erreur, echec de création de la carte", Toast.LENGTH_SHORT).show();
                    }


                }
            });

    }


}

Then my layout for my listView :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/relativeList"
    android:descendantFocusability="blocksDescendants">

    <TextView
        android:text="@string/difficult"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView8"
        android:layout_below="@+id/textView7"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="29dp" />

    <TextView
        android:text="@string/r_ponse"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView7"
        android:layout_marginTop="20dp"
        android:layout_below="@+id/textView6"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/idList"
        android:layout_alignParentTop="true"
        android:layout_alignLeft="@+id/themeList"
        android:layout_alignStart="@+id/themeList"
        tools:ignore="HardcodedText" />

    <TextView
        android:text="Question :"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView6"
        android:layout_marginTop="14dp"
        android:layout_below="@+id/textView4"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        tools:ignore="HardcodedText" />

    <TextView
        android:text="@string/id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView3"
        android:layout_alignParentTop="true"
        android:layout_alignRight="@+id/textView4"
        android:layout_alignEnd="@+id/textView4" />

    <TextView
        android:text="Thème :"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView4"
        android:layout_below="@+id/textView3"
        android:layout_alignRight="@+id/textView6"
        android:layout_alignEnd="@+id/textView6"
        tools:ignore="HardcodedText" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/textView6"
        android:id="@+id/questionList"
        android:layout_toRightOf="@+id/themeList"
        android:layout_toEndOf="@+id/themeList" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/textView8"
        android:layout_alignLeft="@+id/questionList"
        android:layout_alignStart="@+id/questionList"
        android:id="@+id/reponseList" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/textView8"
        android:layout_alignRight="@+id/reponseList"
        android:layout_alignEnd="@+id/reponseList"
        android:id="@+id/difficultList"
        android:layout_toEndOf="@+id/reponseList"
        android:layout_toRightOf="@+id/reponseList" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/themeList"
        android:layout_marginLeft="33dp"
        android:layout_marginStart="33dp"
        tools:ignore="HardcodedText"
        android:layout_below="@+id/idList"
        android:layout_toRightOf="@+id/textView8"
        android:layout_toEndOf="@+id/textView8" />

    <Button
        android:text="@string/supprimerb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:id="@+id/buttonDelete"/>

    <Button
        android:text="@string/modifierB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/buttonModifier"
        android:layout_alignTop="@+id/questionList"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_alignLeft="@+id/buttonDelete"
        android:layout_alignStart="@+id/buttonDelete" />
</RelativeLayout>

And my ContentProvider class:

public class CardContentProvider extends ContentProvider {
    private StockCard stock;

    public static String authority = "com.example.jean.cartememoire.CardContentProvider";
    private static String path ="Cartes_table";

    public static final String _ID = "_id";
    public static final String THEME = "THEME";
    public static final String QUESTION = "QUESTION";
    public static final String REPONSE = "REPONSE";
    public static final String DIFFICULTE = "DIFFICULTE"; //# = un chiffre
    public static final String STOCK_TABLE = "Cartes_table";

    private static final int ID_STOCK_TABLE = 1;
    private static final int ID_THEME = 2;
    private static final int ID_QUESTION = 3;
    private static final int ID_REPONSE = 4;
    private static final int ID_DIFFICULTE = 5;
    private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);

    static {
        matcher.addURI(authority, STOCK_TABLE, ID_STOCK_TABLE);
        matcher.addURI(authority, STOCK_TABLE+"/*", ID_STOCK_TABLE);

    }


    @Override
    public boolean onCreate() {
        stock = StockCard.getInstance(getContext());
        return true;
    }

    @Nullable
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        SQLiteDatabase db = stock.getReadableDatabase();
        int code = matcher.match(uri);
        long id;
        Cursor cursor;

        switch (code)
        {
            case ID_STOCK_TABLE:
                cursor = db.query(STOCK_TABLE, projection, selection,
                        selectionArgs, null, null, sortOrder);
                break;
            default:
                Log.d("Uri provider =", uri.toString());
                throw new UnsupportedOperationException("Pas encore implémenté");
        }

        return cursor;
    }

    @Nullable
    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        SQLiteDatabase db = stock.getWritableDatabase();
        int code = matcher.match(uri);
        long id;
        Uri.Builder builder = new Uri.Builder();

        switch(code)
        {
            case ID_STOCK_TABLE:
                System.out.println(values.toString());
                id = db.insert(STOCK_TABLE, null, values);
                builder.appendPath(STOCK_TABLE);
                break;
            default:
                throw new UnsupportedOperationException("Pas encore implémenté");
        }

        builder.authority(authority);
        builder = ContentUris.appendId(builder, id);

        return builder.build();
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        SQLiteDatabase db = stock.getWritableDatabase();
        int code = matcher.match(uri);
        int i;

        switch(code)
        {
            case ID_STOCK_TABLE:
                long id = ContentUris.parseId(uri);
                i = db.delete(STOCK_TABLE, "_id=" + id, null);
                break;
            default:
                throw new UnsupportedOperationException("Pas encore implémenté");
        }

        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}

Thank you for help.

EDIT : I tried adding a cursor close but it didn't change anything... But I have a button to delete one line in my database and... If I delete one line, then I don't see the line anymore in my listView but I can see a line that I added and could not see before... I think I can only display 3 lines in my listView, so I feel like this is a problem in the listView itself. I'm checking the doc for listView too see what I miss...

EDIT 2 : This is definitely a design problem, I had only a few item show because I could not scroll through all my item. Here is my new fragment layout that contain my listView :

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="layout.ViewCardEditor"
android:background="@android:color/darker_gray">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/listView" />

</FrameLayout>

Before, layout_height was set to something like 500dp. But now my listView is little, I can scroll but all my Text View inside my listView are bugged, their content display content from other TextView and change again when I am scrolling. It is like the content from textView is scrolling with me in other TextView.

EDIT 3 : I vote to delete my question because I didn't had more error, but I have a new problem with my listView, it has a limited scroll :I can see 3 items and the top of a 4 item, I can scroll just a little bit...

Zul Huky
  • 331
  • 4
  • 24

1 Answers1

1

You'll need to notify Cursors that the content has changed using ContentResolvers.notifyChange(...) method. You'll want to do this in your custom ContentProvider when you update data. This call allows Cursors that register for change notifications to refresh their data.

Austin Hanson
  • 21,820
  • 6
  • 35
  • 41