2

I have an android application using SQLite database. I have a CardView and has data like name, cost and description. My CardView has an option menu to input data and update it. When the option menu clicked it will go to another activity. In that activity, it has a TextView that will be showing a same name in CardView.

This my code of my DB

 public ModelPemesanan getnamap(int selectionn){
    SQLiteDatabase db = this.getReadableDatabase();
    String cb = "SELECT * FROM " + TABLE_PEMESANAN + " WHERE " + KEY_ID_PEMESANAN + "= '" + selectionn + "'";
    Cursor cursor = db.rawQuery(cb, null);
    if (cursor != null)
        cursor.moveToFirst();

    ModelPemesanan modelPemesanan = new ModelPemesanan();
    modelPemesanan.set_namap(cursor.getString(1));
    modelPemesanan.set_lapak(cursor.getString(2));
    modelPemesanan.set_desk(cursor.getString(3));
    modelPemesanan.set_lapak(cursor.getString(4));
    modelPemesanan.set_total(Integer.parseInt(cursor.getString(6)));
    modelPemesanan.set_resi(cursor.getString(7));

    db.close();
    return modelPemesanan;
}

In my class that I use to input data

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_resi);

    init();

    simpan.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            modelPemesanan.set_namap(nama.getText().toString());
            modelPemesanan.set_resi(nores.getText().toString());
            db.updateresi(modelPemesanan);
        }
    });

}

private void init() {
    pilih = getIntent().getIntExtra("id_pemesanan", 0);
    db = new Database(this);
    modelPemesanan = db.getnamap(pilih);

    judul = (TextView) findViewById(R.id.tvmasukkan);
    nama = (TextView) findViewById(R.id.tvnamapembeli);
    nores = (EditText) findViewById(R.id.etnoresi);
    simpan = (Button) findViewById(R.id.btsimpannoresi);
    lapak = (TextView) findViewById(R.id.tvnamalapak);


    nama.setText(modelPemesanan.get_namap());
}

In my adapter class, I am using an intent to pass the value of the index.

 holder.pop.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(final View v) {
            PopupMenu popup = new PopupMenu(context, holder.pop);
            popup.inflate(R.menu.menu_list);
            popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    db = new Database(context);
                    final int selectionn = listpemesanan.get(position).get_idp();
                    switch (item.getItemId()){
                        case R.id.input:
                            Intent i = new Intent(v.getContext(), ResiAct.class);
                            i.putExtra("id_pemesanan", selectionn);
                            context.startActivity(i);
                            break;

I used a select query in my database. Here's my logcat

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.asus.daringku/com.example.asus.daringku.ResiAct}: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2345)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2405)
    at android.app.ActivityThread.access$800(ActivityThread.java:155)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1323)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5376)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
    Caused by: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
    at android.database.AbstractCursor.checkPosition(AbstractCursor.java:426)
    at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
    at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
    at com.example.asus.daringku.Database.Database.getnamap(Database.java:279)
    at com.example.asus.daringku.ResiAct.init(ResiAct.java:44)
    at com.example.asus.daringku.ResiAct.onCreate(ResiAct.java:28)
    at android.app.Activity.performCreate(Activity.java:6021)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2405) 
    at android.app.ActivityThread.access$800(ActivityThread.java:155) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1323) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:135) 
    at android.app.ActivityThread.main(ActivityThread.java:5376) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)

 

And this my XML

 <TextView
    android:id="@+id/tvmasukkan"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Masukkan Nomor Resi untuk : "
    android:textSize="20sp"
    android:padding="10dp"/>
<TextView
    android:id="@+id/tvnamapembeli"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="17sp"
    android:padding="10dp"
    android:text="NAMA"
    android:layout_below="@id/tvmasukkan"
    />
<TextView
    android:id="@+id/tvnamalapak"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/tvnamapembeli"
    android:padding="10dp"
    android:textSize="17sp"
    android:text="NAMA LAPAK"
    />
<EditText
    android:id="@+id/etnoresi"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ems="10"
    android:hint="Masukkan Nomor Resi"
    android:padding="10dp"
    android:layout_below="@id/tvnamalapak"/>
<Button
    android:id="@+id/btsimpannoresi"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/etnoresi"
    android:layout_centerHorizontal="true"
    android:padding="10dp"
    android:text="simpan"/>

Please help! Thank you.

MikeT
  • 51,415
  • 16
  • 49
  • 68
Anita Tata
  • 53
  • 5
  • Your query simply did not return any data. Also, don't assemble SQL statements like this (danger of SQL injection). – Henry Aug 05 '18 at 03:56
  • @Henry what will someone accomplish doing a SQL injection with Androids SQLite? The database is local and the user can anyway just get the database and modify it as he/she wants. – HB. Aug 05 '18 at 04:12
  • @HB even if there is not much damage done in this case it is bad habit to fall into. Imagine similar code used in other circumstances. – Henry Aug 05 '18 at 04:18
  • @Henry I can't think of any circumstance (with SQLite) that can cause any damage. I mean, if you use SQLite for what it was meant for (storing user data), SQL injection wouldn't bother me at all. – HB. Aug 05 '18 at 04:25

1 Answers1

3

A size of 0 indicates that there are no extracted rows from which data can be extracted.

You should not attempt to extract data from a Cursor when there are no rows (you will get such an exception), as such you should check if there are any rows from which data can be extracted before trying to extract data from the Cursor.

Your code is checking a Cursor, returned from the rawQuery method, to see if it is null, probably in an attempt to avoid checking an empty Cursor. Checking for null is useless as a Cursor returned from the rawQuery method, even if it is empty, will not be null (it's count will be 0, if there are no rows).

You can check the number of rows using the Cursor getCount() method to see if there are 0 rows. However, the Cursor moveTo???? methods, such as the moveToFirst method, return true if the move could be made otherwise false. As you are using the moveToFirst method you simply need to check the result to see if the move was made, rather than check the number of rows.

As such you could use :-

public ModelPemesanan getnamap(int selectionn){
    SQLiteDatabase db = this.getReadableDatabase();
    String cb = "SELECT * FROM " + TABLE_PEMESANAN + " WHERE " + KEY_ID_PEMESANAN + "= '" + selectionn + "'";
    Cursor cursor = db.rawQuery(cb, null);
    ModelPemesanan modelPemesanan = new ModelPemesanan(); //<<<<<<<< MOVED HERE
    if (cursor.moveToFirst() {

        modelPemesanan.set_namap(cursor.getString(1));
        modelPemesanan.set_lapak(cursor.getString(2));
        modelPemesanan.set_desk(cursor.getString(3));
        modelPemesanan.set_lapak(cursor.getString(4));
        modelPemesanan.set_total(Integer.parseInt(cursor.getString(6)));
        modelPemesanan.set_resi(cursor.getString(7));
    }
    cursor.close() //<<<<<<<< YOU SHOULD ALWAYS CLOSE CURSORS WHEN DONE WITH THEM
    db.close();
    return modelPemesanan;
}
  • Note if there are no rows returned then the returned ModelPemesanan will will as it was constructed. So you should probably check it to determine if any data has been set.

However, the better/recommended approach, with android is use arguments to pass parameters (protects against SQL injection) and also the SQLiteDatabase convenience methods (builds the appropriate underlying SQL) when they can be used.

So the following would be recommended :-

public ModelPemesanan getnamap(int selectionn){
    SQLiteDatabase db = this.getReadableDatabase();
    String whereclause = KEY_ID_PEMESANAN + "=?";
    String[] whereargs = new String[]{String.valueOf(selectionn)};
    Cursor cursor = db.query(
        TABLE_PEMESANAN,
        null, //<<<< null = all columns, else String[] of columns to extract
        whereclause, //<<<< WHERE clause less WHERE keyword with ? for arguments (as per whereargs 1 for 1)
        whereargs, // <<<< arguments to replace ? placeholder on 1 for 1 basis
        null, // <<<< GROUP BY clause less GROUP BY keywords (null for no clause)
        null, // <<<< HAVING clause less HAVING keyword (null for no clause)
        null // <<<< ORDER BY clause less ORDER BY keywords (null for no clause)
    );
    ModelPemesanan modelPemesanan = new ModelPemesanan(); //<<<<<<<< MOVED HERE
    if (cursor.moveToFirst() {

        modelPemesanan.set_namap(cursor.getString(1));
        modelPemesanan.set_lapak(cursor.getString(2));
        modelPemesanan.set_desk(cursor.getString(3));
        modelPemesanan.set_lapak(cursor.getString(4));
        modelPemesanan.set_total(Integer.parseInt(cursor.getString(6)));
        modelPemesanan.set_resi(cursor.getString(7));
    }
    cursor.close() //<<<<<<<< YOU SHOULD ALWAYS CLOSE CURSORS WHEN DONE WITH THEM
    db.close();
    return modelPemesanan;
}

Your root issue is likely that the value being passed to the method, i.e. selectionn is not an existing id and thus you are extracting no rows. So you probably need to determine why this value is not matching any rows.

MikeT
  • 51,415
  • 16
  • 49
  • 68
  • Thank you for you're answer. There is no error when I clicked the option menu. But in my textview that store a value it's don't show the value. What I must to do now? – Anita Tata Aug 05 '18 at 08:49
  • @AnitaTata As per the last paragraph. You are likely not passing a value that matches an id in the table. You should tick this question as answered as it answers this question and then ask another question if you cannot ascertain why the value doesn't match a row. *Hint put a breakpoint at this line `db = new Database(this);` run in debug mode and check the value of **pillih**. If that's not as expected then perhaps a breakpoint immediately after `final int selectionn = listpemesanan.get(position).get_idp();` along with checking the value of **selectionn** may show where the problem lies.* – MikeT Aug 05 '18 at 09:06
  • In my post before, I try to passing a value that is a position of the cardview. Then i put in the variable 'pilih'. Am I wrong writing the code to using the intent? – Anita Tata Aug 05 '18 at 09:06
  • @AnitaTata My guess is that you are not getting the correct value from the menu onClick (see 2nd part of hint in my previous comment). – MikeT Aug 05 '18 at 09:08
  • @AnitaTata nothing wrong with using intent extras to pass data such as id's between activities. Does the item at that position have the correct id? – MikeT Aug 05 '18 at 09:14
  • I know whats the problem. It's so embarrassing, I forgot to select the id of the value in my database. So it's passing a null value. Thank you so much for your help. – Anita Tata Aug 05 '18 at 10:01