content provider 深入解析

本文详细介绍了Android中的ContentProvider组件,包括其作用、实现方式及应用场景。通过一个具体的例子展示了如何创建和使用ContentProvider来管理和共享应用间的数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       Content providers are one of the primary building blocks of Android applications, providing content to applications. They encapsulate data and provide it to applications through the single ContentResolver interface. A content provider is only required if you need to share data between multiple applications.  If you don't need to share data amongst multiple applications you can use a database directly via SQLiteDatabase.

 

      照我的理解的话,你可以把ContentProvider 当成是一个适配器。 也就是让应用程序能够通过Content provider提供的接口,调用database 提供的接口来访问database中的数据。也就是说用户可以直接使用ContentResolver操作ContentProvider  来间接访问其它应用程序存在database 中的数据。

    下面的例子是实现了这个过程。

一 实现custom content provider  

 

public class ReadingProvider extends ContentProvider {

    public static final String AUTHORITY = ReadingProvider.class.getName().toLowerCase();

 //下面是定义了两个访问类型的常量。
 //访问整张数据表
    private static final int TYPE_ALL_ITEMS           = 1;
    //访问该张表中特定的row的数据
    private static final int TYPE_SINGLE_ITEM         = 2;
   
    //这个contentprovider对应的数据库
    private ReadingOpenHelper dbhelper = null;

 //用来匹配content provider的 Uri
    private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);

    static {
        matcher.addURI(AUTHORITY, "items", TYPE_ALL_ITEMS);
  //注意这个# 的意思是占位符,对应的uri可以是这样的形式
  //static final Uri URI = Uri.parse("content://" + ReadingProvider.AUTHORITY + "/items");
  //itemUri = Uri.withAppendedPath(URI, "" + item_id);
        matcher.addURI(AUTHORITY, "items/#", TYPE_SINGLE_ITEM);
    }

 //在这个content provider创建的时候打开数据库
    @Override
    public boolean onCreate() {
     log.debug("readingprovider oncreate");
        dbhelper = new ReadingOpenHelper(getContext());
        return true;
    }
   
    @Override
    public int delete(Uri uri, String where, String[] whereArgs) {
        switch (matcher.match(uri)) {
        case TYPE_ALL_ITEMS:

        //当匹配TYPE_ALL_ITEMS 这个Uri的时候就删掉ItemColumns.TABLE_NAME 这个table中相应的数据
            return dbhelper.getWritableDatabase().delete(ItemColumns.TABLE_NAME, where, whereArgs);
        case TYPE_SINGLE_ITEM:

        //当匹配TYPE_SINGLE_ITEM 这个Uri的时候就删掉ItemColumns.TABLE_NAME 这个table中用id指定的row的数据
            String i_id = uri.getPathSegments().get(1);
            return dbhelper.getWritableDatabase().delete(ItemColumns.TABLE_NAME, ItemColumns._ID + "=" + i_id, null);
        }
        throw new IllegalArgumentException("Unsupported URI: " + uri);
    }

 

    @Override
    public String getType(Uri uri) {
        switch (matcher.match(uri)) {
        case TYPE_ALL_ITEMS:
            return null;//there is no type so return null
        case TYPE_SINGLE_ITEM:
            return null;
        }
        throw new IllegalArgumentException("Unsupported URI: " + uri);
    }
   
    @Override
    public Uri insert(Uri uri, ContentValues initialValues) {
        long id = 0L;
        switch (matcher.match(uri)) {
        case TYPE_ALL_ITEMS:

       //当匹配这个Uri的时候就在(ItemColumns.TABLE_NAME这个table中插入initialValues
            id = dbhelper.getWritableDatabase().insertOrThrow(ItemColumns.TABLE_NAME, null, initialValues);
            return ContentUris.withAppendedId(ItemColumns.URI, id);
        }
        throw new IllegalArgumentException("Illegal Uri: " + uri.toString());
    }

 

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sort) {
     //log.debug("reading provider query" + uri.toString());
     Cursor cursor = null;
        switch (matcher.match(uri)) {
        case TYPE_ALL_ITEMS:
         cursor = dbhelper.getReadableDatabase().query(ItemColumns.TABLE_NAME, projection, selection, selectionArgs, null, null, sort);
         break;
        case TYPE_SINGLE_ITEM:
            String i_id = uri.getPathSegments().get(1);
            cursor = dbhelper.getReadableDatabase().query(ItemColumns.TABLE_NAME, projection, ItemColumns._ID + "=" + i_id, null, null, null, null);
            break;
        default:
            throw new IllegalArgumentException("Illegal Uri: " + uri.toString());
        }
       
        if (cursor != null) {
         cursor.setNotificationUri(getContext().getContentResolver(), uri);
        } else {
            log.warn("query failed in reading provider");
        }
        return cursor;
    }

    @Override
    public int update(Uri uri, ContentValues initialValues, String where, String[] whereArgs) {
        switch (matcher.match(uri)) {
        case TYPE_ALL_ITEMS:
            return dbhelper.getWritableDatabase().update(ItemColumns.TABLE_NAME, initialValues, where, whereArgs);
        }
        throw new IllegalArgumentException("Illegal Uri: " + uri.toString());
    }
}

 

note: 由上面的content provider的实现我们可以看到,content provider的内部都是在对其相关联的那个数据库进行操作。

 

二 下面实现这个数据库。 ReadingOpenHelper  继承 SQLiteOpenHelper,使用父类提供的接口来对自己定义的数据库进行相关的操作

1.

public class ReadingOpenHelper extends SQLiteOpenHelper {
 
 private final Log log = Utils.getLog(getClass());

    public ReadingOpenHelper(Context context) {
        super(context, "bereader.db", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {    

        //下面是创建一个数据库的sql语句
        String sql_create_item = cat(
                "CREATE TABLE IF NOT EXISTS ", ItemColumns.TABLE_NAME, " (",
                ItemColumns._ID, " INTEGER PRIMARY KEY AUTOINCREMENT, ",
                ItemColumns.TITLE, " VARCHAR(256)"
                ");"
        );
        String sql_index_item_title = cat(
                "CREATE UNIQUE INDEX IDX_",
                ItemColumns.TABLE_NAME,
                "_",
                ItemColumns.TITLE,
                " ON ",
                ItemColumns.TABLE_NAME,
                " (",
                ItemColumns.TITLE,
                ");"
        );

        //执行这个sql语句

        db.execSQL(sql_create_item);
        db.execSQL(sql_index_item_title);
    }
   
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
     log.debug("onUpdate, from: " + oldVersion + " to " + newVersion);
        if (oldVersion!=newVersion) {
            // drop db 更新数据库的时候要先删掉以前的数据库,这里我们调用onCreate(db);
           //来重新生成一个数据库
            db.execSQL(cat("DROP TABLE ", ItemColumns.TABLE_NAME));
            onCreate(db);
        }
    }

 

    String cat(String... ss) {
        StringBuilder sb = new StringBuilder(ss.length << 3);
        for (String s : ss)
            sb.append(s);
        return sb.toString();
    }
}

 

2.下面这个类就是表示数据库中的一个一个item实体,定义了这个item所在的数据表的名字,用来访问这个数据表的Uri,和这个item的field 这里只有一个TITLE

public interface ItemColumns extends BaseColumns {

    //用这个Uri就能够从provider中访问数据库中存储的ItemColumns 的内容

    static final Uri URI = Uri.parse("content://" + ReadingProvider.AUTHORITY + "/items");

    static final String TABLE_NAME = "beReaderItems";
    static final String TITLE = "title";
}

 

三: 下面我们来使用content provider来访问数据库中的数据。

void testProvider(){

 

      ContentValues cv = new ContentValues();
    ContentResolver cr = getContentResolver();
    
     cv.put(ItemColumns.TABLE_NAME, "title_name1");
     //插入一条item

     cr.insert(ItemColumns.URI,cv);
     //查询指定的item

     String itemUri = Uri.withAppendedPath(ItemColumns.URI, "" + item_id);
    Cursor cursor = cr.query(itemUri,
      new String [] {ItemColumns._ID,ItemColumns.TITLE,},
      null, null, null);

    

//更新一条记录

      cv.put(ItemColumns.TABLE_NAME, "title_name1");
        int n = cr.update(
                ItemColumns.URI,
                cv,
                ItemColumns.URI._ID + "=" + itemId,
                null
        );     
 }

内容概要:本文针对国内加密货币市场预测研究较少的现状,采用BP神经网络构建了CCi30指数预测模型。研究选取2018年3月1日至2019年3月26日共391天的数据作为样本,通过“试凑法”确定最优隐结点数目,建立三层BP神经网络模型对CCi30指数收盘价进行预测。论文详细介绍了数据预处理、模型构建、训练及评估过程,包括数据归一化、特征工程、模型架构设计(如输入层、隐藏层、输出层)、模型编译与训练、模型评估(如RMSE、MAE计算)以及结果可视化。研究表明,该模型在短期内能较准确地预测指数变化趋势。此外,文章还讨论了隐层节点数的优化方法及其对预测性能的影响,并提出了若干改进建议,如引入更多技术指标、优化模型架构、尝试其他时序模型等。 适合人群:对加密货币市场预测感兴趣的研究人员、投资者及具备一定编程基础的数据分析师。 使用场景及目标:①为加密货币市场投资者提供一种新的预测工具和方法;②帮助研究人员理解BP神经网络在时间序列预测中的应用;③为后续研究提供改进方向,如数据增强、模型优化、特征工程等。 其他说明:尽管该模型在短期内表现出良好的预测性能,但仍存在一定局限性,如样本量较小、未考虑外部因素影响等。因此,在实际应用中需谨慎对待模型预测结果,并结合其他分析工具共同决策。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值