简体   繁体   中英

Android - Content Provider query cursor

I cannot seem to grasp the concept of Content provider. I personally think that it bloats the code, it over-complicates it, and is plainly awful.

BTW this will be the first example code of a multi-table ContentProvider that you will find on the web. There is absolutelly NONE other, except for maybe the ContactsProvider ("veeeerrrrry usefull" - by being super-stuffed and indescifrable). I am sure many noobs like me will appreciate this.

Please help me make a simple cursor from a content provider. I have the NORMAL code bellow (using a simple SQLiteOpenHelper), and I need to translate it into content-provider code:

    Button btnp = (Button) findViewById(R.id.btnproc);
    btnp.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
        Context mycontext = getApplicationContext();
        SQLiteDatabase db = new myDbHelper(mycontext).getWritableDatabase();
        String sql = "select _id,data,titlu,cont from notificari where date(data)<=date(datetime())";
        Cursor cursor = db.rawQuery(sql, null);
        Log.w("...MainActivity...", "Record count:"+Integer.toString(curu.getCount()));
            while(curu.moveToNext()){
                String lista = curu.getString(0)+",'"+curu.getString(1)+"',"+curu.getString(2)+",'"+
                        curu.getString(3)+"'";
                Log.e("...MainActivity...", lista);
            }

        }
    });

So I need the cursor to be obtained from content-provider. I have already started developing this "mind-blowing" content-provider, but I have no idea if what I am doing is ok, since it is so overcomplicated. Here it goes (my content-provider needs to refference more than one table):

public class MyFirstProvider extends ContentProvider {
static final String PROVIDER_NAME = "com.mystuff.myapp.MyFirstProvider";
    static final String URL = "content://" + PROVIDER_NAME + "/cte";
    static final String URL2 = "content://" + PROVIDER_NAME + "/clienti";
    static final String URL3 = "content://" + PROVIDER_NAME + "/uzeri";
    static final String URL4 = "content://" + PROVIDER_NAME + "/notificari";
    static final Uri CONTENT_URI = Uri.parse(URL);
    static final Uri CONTENT_URI2 = Uri.parse(URL2);
    static final Uri CONTENT_URI3 = Uri.parse(URL3);
    static final Uri CONTENT_URI4 = Uri.parse(URL4);


    static final int uriCode = 1;
    static final int uriCode1 = 2;
    static final int uriCode2 = 3;
    static final int uriCode3 = 4;
    static final int uriCode4 = 5;
    static final int uriCode5 = 6;
    static final int uriCode6 = 7;
    static final int uriCode7 = 8;


    static final UriMatcher uriMatcher;
    private static HashMap<String, String> values;
    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(PROVIDER_NAME, "cte", uriCode);
        uriMatcher.addURI(PROVIDER_NAME, "cte/*", uriCode1);
        uriMatcher.addURI(PROVIDER_NAME, "clienti", uriCode2);
        uriMatcher.addURI(PROVIDER_NAME, "clienti/*", uriCode3);
        uriMatcher.addURI(PROVIDER_NAME, "uzeri", uriCode4);
        uriMatcher.addURI(PROVIDER_NAME, "uzeri/*", uriCode5);
        uriMatcher.addURI(PROVIDER_NAME, "notificari", uriCode6);
        uriMatcher.addURI(PROVIDER_NAME, "notificari/*", uriCode7);
    }

    @Override
    public boolean onCreate() {
        Context context = getContext();
        DatabaseHelper dbHelper = new DatabaseHelper(context);
        db = dbHelper.getWritableDatabase();
        if (db != null) {
            return true;
        }
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        switch (uriMatcher.match(uri)) {
            case uriCode:
                qb.setTables(TABLE_NAME);
                qb.setProjectionMap(values);
                break;
            case uriCode2:
                qb.setTables(TABLE_CLIENTI);
                qb.setProjectionMap(values);
                if (sortOrder == null || sortOrder == "") {
                    sortOrder = TCL_NUME_CLIENT;
                }
                break;
            case uriCode6:
                qb.setTables(TABLE_NOTIF);
                qb.setProjectionMap(values);
                break;

            default:
                throw new IllegalArgumentException("Unsupported URI: " + uri);
        }
        Cursor c = qb.query(db, projection, selection, selectionArgs, null,null, sortOrder);
        c.setNotificationUri(getContext().getContentResolver(), uri);
        return c;
    }


    // ... there is other code here regarding the insert,update and delete (not relevant now)

    private SQLiteDatabase db;
    static final String DATABASE_NAME = "mydb";
    static final String TABLE_NAME = "names";
    public static final String TABLE_UZERI = "uzeri";
    public static final String TABLE_NOTIF = "notificari";


    static final int DATABASE_VERSION = 3;
    static final String CREATE_DB_TABLE = " CREATE TABLE " + TABLE_NAME
            + " (_id INTEGER PRIMARY KEY AUTOINCREMENT, "
            + " name TEXT NOT NULL);";

    static final String CREATE_DB_TABLE_NOTIFICARI = "CREATE TABLE IF NOT EXISTS " + TABLE_NOTIF + " (_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
            TNOT_ID_NOT + " INTEGER NOT NULL DEFAULT 0, " +
            TNOT_DATA + " DATE NOT NULL, " +
            TNOT_SURSA + " INTEGER NOT NULL DEFAULT 0, "+
            TNOT_DEST + " INTEGER NOT NULL DEFAULT 0, "+
            TNOT_TIP + " TEXT, "+
            TNOT_TITLU + " TEXT, "+
            TNOT_TITLUCONT + " TEXT, "+
            TNOT_CONT + " TEXT, "+
            TNOT_STERS + " INTEGER DEFAULT 0, "+
            TNOT_NOU + " INTEGER NOT NULL DEFAULT 0)";

   private static class DatabaseHelper extends SQLiteOpenHelper {
        DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(CREATE_DB_TABLE);
            db.execSQL(CREATE_DB_TABLE_UZERI);
            db.execSQL(CREATE_DB_TABLE_NOTIFICARI);
        }

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

I tried to "translate" the Activity code that logs the content of the cursor but it just does NOTHING. It's VERY frustrating. Here is my "translation":

Button btnp = (Button) findViewById(R.id.btnproc);
btnp.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        String[] coloane = {MyFirstProvider.TNOT_ID_ID, MyFirstProvider.TNOT_DATA,MyFirstProvider.TNOT_TITLU, MyFirstProvider.TNOT_CONT};
        Cursor curu = MainActivity.this.getContentResolver().query(MyFirstProvider.CONTENT_URI_NOTIF,coloane,null,null,MyFirstProvider.TNOT_DATA);

        Log.w("...MainActivity...", "Recorduri:"+Integer.toString(curu.getCount()));
        while(curu.moveToNext()){
            String lista = curu.getString(0)+",'"+curu.getString(1)+"',"+curu.getString(2)+",'"+
                    curu.getString(3)+"'";
            Log.e("...MainActivity...", lista);
        }

    }
});

I must assure you that the table has 4 records inside (I insert them manually after table creation) Also if I put this code inside the ContentProvider, then the Log displays the content of the table as desired:

Cursor c = qb.query(db, projection, selection, selectionArgs, null,null, sortOrder);
        while(c.moveToNext()){
            Log.w("...Provider...",c.getString(0)+"-"+c.getString(1)+"-"+c.getString(2));
        }

But I do not want to do this in the content provider, I want to do it in the Activity code. What am I doing wrong?

Please help.

Thank you

You don't have to use ContentProvider if you don't have to. Identify your requirements. If the data is private to your application AND if it has to be stored in a table format, then you can access SQLite engine directly in Android without having to go via ContentProvider . But if you want other apps or system to access your app's data, then yes - that's a legitimate use case for ContentProvider .

Nonetheless, i would suggest you read this article - that tells you how to access SQLite engine with and without ContentProvider .

Hope this helps.

Anyways, for your problem at hand, try this -

Cursor c = qb.query(db, projection, selection, selectionArgs, null,null, sortOrder);
if (c == null) {
  // error - log some message
}
else if (c.getCount() < 1) {
  // nothing to show  - log some message
}
else {
  while(c.moveToNext()){
    Log.w("...Provider...",c.getString(0)+"-"+c.getString(1)+"-"+c.getString(2));
  } 
}

Instead of this

btnp.setOnClickListener(new View.OnClickListener

try

btnp.setOnClickListener(this)

and implement onClickListner to the Activity.

In short, instead of casting onClickListener to button, implement it to the whole activity and try.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM