Android ContentProvider介绍

WSL2 Ubuntu 22.04安装NVIDIA驱动避坑指南:从驱动版本选择到CUDA环境验证 本文详细介绍了在WSL2 Ubuntu 22.04中安装NVIDIA驱动和配置CUDA环境的完整流程,包括驱动版本选择、环境变量设置以及常见问题解决方案。通过本指南,用户可以避免常见的安装陷阱,确保GPU加速环境正确配置,适用于深度学习开发和CUDA编程。 阅读详情

在Android中数据的存储一共有五种形式,分别是:Shared Preferences、网络存储、文件存储,外储存储、SQLite。但是我们知道一般这些存储都只是在单独的一个应用程序之中达到一个数据的共享。而使用ContentProvider共享数据的好处是统一了数据访问方式。ContentProvide对数据进行封装,不用关心数据存储的细节。下面我们通过代码来介绍这个ContentProvider的使用过程。

复制代码
public class ItemContentProvier {

    /*Authority*/ 
    public static final String  AUTHORITY="com.itchq.contentprovider";

    /*Match Code*/
    public static final int ITEM=1;
    public static final int ITEM_POS=2;
    
    /*Default sort order*/
    public static final String DEFAULT_SORT_ORDER = "_id asc";
    
       /*MIME*/  
    public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.itchq.contentprovider";  
    public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.itchq.contentprovider";
    
    
    public static final String ARTICE_ITEM="articeitem";
    
    /*Content URI*/
    public static final Uri CONTENT_ARTICE=Uri.parse("content://"+AUTHORITY+"/"+ARTICE_ITEM);
    
    public interface Artice{
        
        public static final String ID="_id";
        
        public static final String TITLE="title";
        
        public static final String CONTENT_ID="contentid";
    }
    
}
复制代码

上面这个类都是定义数据库一些常量,我们往往把它单独的提前出来使代码结构更清晰一点。

URI 通用资源标志符,这个Uri代表了要操作的数据,后面要访问这个数据库就可以通过这个URI来指定,用于唯一标识某个具体的ContentProvider

URI格式如下:
[content://][com.itchq.contentprovider][/artice][/1]

 |------A------|-----------------B-------------------|---C---|---D--|

A:前缀表明数据受控于一个内容提供者。它从不修改,也就是schema,ContentProvider(内容提供者)的scheme已经由Android所规定, scheme为:content://

B:称为Authority,它唯一地标识了一个特定的Content Provider,因此,这部分内容一般使用Content Provider所在的package来命名,使得它是唯一的,在上面的代码中使用    public static final String  AUTHORITY="com.itchq.contentprovider";定义这个变量,这个还有一个地方使用到,就是在AndroidMainfest.xml中要声明这个数据库的时候需要使用,如下代码:

         <provider
            android:name="com.itchq.contentprovider.itContentProvider"
            android:authorities="com.itchq.contentprovider"/>

 

上面这个android:authorities这个就是和我们的AUTHORITY里面定义的字符串是一样的,这个地方要注意点,如果不一样外部就不可以访问这个数据库了,我们所说的URI唯一性也是在这个地方来体现出来的,

C:称为资源路径,它表示所请求的资源的类型,这部分内容是可选的

D:资源ID,它表示所请求的是一个特定的资源,它通常是一个数字,对应前面我们所介绍的数据库表中的_id字段的内容,它唯一地标志了某一种资源下的一个特定的实例

我们在定义URI的时候一般情况行都是需要定义这个C,但是D就没有定义,简单点说C就是代表了数据库中某一个表(这个名字是随意定义不一定就是和我们的数据库表名字相同,这里只是一个比喻),而D则是表示操作这个表的哪一个字段,相当于我们的SQL语句中 where id=1这个条件

继续往下看:

       /*MIME*/  
    public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.itchq.contentprovider";  
    public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.itchq.contentprovider";

这个是MIME类型,每一个ContenProvider中都必须定义这个MIME,其实这个MIME类型一般来说就估计上面两种,被分为两部分前面是数据的大类别,后面定义具体的种类,比如上面的vnd.android.cursor.dir和vnd.android.cursor.item都是固定不会变的,后面的字段都是相同的而且随便定义,一般的数据库中都vnd.+包名。对于vnd.android.cursor.dir这个类型表示的访问多个资源的URI,就是你操作的是一整张表,比如添加新数据了,删除某一个表后者是查询表的全部记录等等,而vnd.android.cursor.item是表示访问单个资源的URI,比如更新表中某一个自定的记录,查询某一条指定的信息,就是相当SQL中的where条件语句。

 

Artice这个接口是我们这个数据库的表的字段,这里看出这个表有三个字段,分别是:_id,title,contentid。ITEM和ITEM_POS这两个变量分别定义URI匹配规则的匹配码。

比如如果我们访问的URI是content://com.itchq.contentprovider/articeitem,则匹配规则返回的匹配码为ITEM。如果访问的是content://com.itchq.contentprovider/articeitem/# # 是一个通配符表示如何数据,则匹配规则返回的匹配码为ITEM_POS,这两个常量我们后面还会有用到的

下面就是ContentProvider的定义了

 

复制代码
package com.itchq.contentprovider;

import java.util.HashMap;

import com.itchq.contentprovider.ItemContentProvier.Artice;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;

public class itContentProvider extends ContentProvider{


    private static final String DB_NAME="itchq.db";
    
    private static final String DB_TABLE_ARTICE="artice";
    
    private static final int DB_VERSION=1;
    
    private DBHelper dbHelper = null;  
    
    private static final String DB_CREATE_ARTICE = "create table " + DB_TABLE_ARTICE +  
            " (" + Artice.ID + " integer primary key autoincrement, " +  
            Artice.TITLE + " text not null, " +  
            Artice.CONTENT_ID + " integer not null);";
    
    private static final UriMatcher uriMatcher;
    private static final HashMap<String, String> articleProjectionMap;
    static{
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(ItemContentProvier.AUTHORITY, ItemContentProvier.ARTICE_ITEM, ItemContentProvier.ITEM);
        uriMatcher.addURI(ItemContentProvier.AUTHORITY, ItemContentProvier.ARTICE_ITEM+"/#", ItemContentProvier.ITEM_POS);
        
        articleProjectionMap = new HashMap<String, String>();  
        articleProjectionMap.put(Artice.ID, Artice.ID);  
        articleProjectionMap.put(Artice.TITLE, Artice.TITLE);  
        articleProjectionMap.put(Artice.CONTENT_ID,Artice.CONTENT_ID); 
    }
    @Override
    public boolean onCreate() {
        // TODO Auto-generated method stub
        dbHelper = new DBHelper(getContext(), DB_NAME, null, DB_VERSION);  
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        // TODO Auto-generated method stub
         SQLiteDatabase db = dbHelper.getReadableDatabase();  
          
         SQLiteQueryBuilder sqlBuilder = new SQLiteQueryBuilder();  
         switch(uriMatcher.match(uri)){
         case ItemContentProvier.ITEM:{
             sqlBuilder.setTables(DB_TABLE_ARTICE);
             sqlBuilder.setProjectionMap(articleProjectionMap); 
             break;
         }
         case ItemContentProvier.ITEM_POS:{
             String id = uri.getPathSegments().get(1);  
             sqlBuilder.setTables(DB_TABLE_ARTICE);  
             sqlBuilder.setProjectionMap(articleProjectionMap);  
             sqlBuilder.appendWhere(Artice.ID + "=" + id);  
             break;
         }
         default:  
             throw new IllegalArgumentException("Error Uri: " + uri);  
         }
        Cursor cursor = sqlBuilder.query(db, projection, selection, selectionArgs, null, null, TextUtils.isEmpty(sortOrder) ? ItemContentProvier.DEFAULT_SORT_ORDER : sortOrder);
        cursor.setNotificationUri(getContext().getContentResolver(), uri);  
        return cursor;
    }

    @Override
    public String getType(Uri uri) {
        // TODO Auto-generated method stub
        switch (uriMatcher.match(uri)) { 
        case ItemContentProvier.ITEM:{
            return ItemContentProvier.CONTENT_TYPE;
        }
        case ItemContentProvier.ITEM_POS:{
            return ItemContentProvier.CONTENT_ITEM_TYPE;
        }
        default:
            throw new IllegalArgumentException("Error Uri: " + uri); 
        }
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO Auto-generated method stub
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        long id = db.insert(DB_TABLE_ARTICE, Artice.ID, values); 
        if (id < 0) {
            throw new SQLiteException("Unable to insert " + values + " for "
                    + uri);
        }
        Uri newUri = ContentUris.withAppendedId(uri, id);
        getContext().getContentResolver().notifyChange(newUri,null);
        return newUri;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // TODO Auto-generated method stub
        SQLiteDatabase db = dbHelper.getWritableDatabase();  
        int count = 0;
        switch(uriMatcher.match(uri)){
        case ItemContentProvier.ITEM:{
             count = db.delete(DB_TABLE_ARTICE, selection, selectionArgs);
             break;
        }
        case ItemContentProvier.ITEM_POS:{
            String id = uri.getPathSegments().get(1);
            count = db.delete(DB_TABLE_ARTICE,Artice.ID + "=" + id  
                     + (!TextUtils.isEmpty(selection) ? " and (" + selection + ')' : ""), selectionArgs);
             break;
        }
        default:
            throw new IllegalArgumentException("Error Uri: " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return count;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        // TODO Auto-generated method stub
        SQLiteDatabase db = dbHelper.getWritableDatabase();  
        int count = 0;
        switch(uriMatcher.match(uri)){
        case ItemContentProvier.ITEM:{
             count = db.update(DB_TABLE_ARTICE, values, selection, selectionArgs);
             break;
        }
        case ItemContentProvier.ITEM_POS:{
            String id = uri.getPathSegments().get(1);
            count = db.update(DB_TABLE_ARTICE, values, Artice.ID + "=" + id  
                     + (!TextUtils.isEmpty(selection) ? " and (" + selection + ')' : ""), selectionArgs);
             break;
        }
        default:
            throw new IllegalArgumentException("Error Uri: " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return count;
    }
    
    private static class DBHelper extends SQLiteOpenHelper{

        public DBHelper(Context context, String name, CursorFactory factory,
                int version) {
            super(context, name, factory, version);
            // TODO Auto-generated constructor stub
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            // TODO Auto-generated method stub
            db.execSQL(DB_CREATE_ARTICE);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            // TODO Auto-generated method stub
            
        }
        
    }

}
复制代码

 

继承ContentProvider类需要实现默认下面这些方法

public boolean onCreate() 在创建ContentProvider时调用

 

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 用于查询指定Uri的ContentProvider,返回一个Cursor

 

public int delete(Uri uri, String selection, String[] selectionArgs) 用于从指定Uri的ContentProvider中删除数据

 

public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) 用于更新指定Uri的ContentProvider中的数据

 

public Uri insert(Uri uri, ContentValues values) 用于添加新数据到指定Uri的ContentProvider中

 

public String getType(Uri uri) 用于返回指定的Uri中的数据的MIME类型

这个就是前面说的,如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头。即

public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.itchq.contentprovider"; 

如果要操作的数据属于非集合类型数据(简单点说就是指定where条件的),那么MIME类型字符串应该以vnd.android.cursor.item/开头。即

public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.itchq.contentprovider";

 

UriMatcher类用于匹配Uri 这个就是要设置Uri的匹配规则,我们可以根据不同的Uri来操作不同的数据,比如前面我们定义的那个URI

 

 /*Content URI*/
    public static final Uri CONTENT_ARTICE=Uri.parse("content://"+AUTHORITY+"/"+ARTICE_ITEM);

 

分解这个URI字符串是”content://com.itchq.contentprovider/articeitem“,那么我们操作可以是content://com.itchq.contentprovider/articeitem这个字符串也也可能是content://com.itchq.contentprovider/articeitem/#这个字符串,前面表示操作整个数据库表,后面指定是操作数据库某一个字段,那我们是如何知道这个匹配码呢?这个就需要UriMatcher类来设定

public void addURI (String authority, String path, int code) ;

authority就是上面定义的public static final String  AUTHORITY="com.itchq.contentprovider";这个变量,path就是就是指具体那个路径,一般就是URI规则中表示C的部分,比如上面URI规则中 public static final Uri CONTENT_ARTICE=Uri.parse("content://"+AUTHORITY+"/"+ARTICE_ITEM);那么这个path指的就是ARTICE_ITEM这个字符串变量,即public static final String ARTICE_ITEM="articeitem"; code就是后面那个匹配码,比如我们可以看一下update更新语句里面有这么一个switch函数:

 

复制代码
       switch(uriMatcher.match(uri)){
        case ItemContentProvier.ITEM:{

        }
        case ItemContentProvier.ITEM_POS:{

        }
        default:
            throw new IllegalArgumentException("Error Uri: " + uri);
        }
复制代码

 

上面的ItemContentProvier.ITEM 和 ItemContentProvier.ITEM_POS 就是已经定义好的匹配码,即code参数,我们通过这个ItemContentProvier.ITEM可以知道操作整个数据库表,ItemContentProvier.ITEM_POS操作的是数据库表中某一列,这个匹配一般都是一开始初始化的时候就需要全部给注册上的,

    static{
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(ItemContentProvier.AUTHORITY, ItemContentProvier.ARTICE_ITEM, ItemContentProvier.ITEM);
        uriMatcher.addURI(ItemContentProvier.AUTHORITY, ItemContentProvier.ARTICE_ITEM+"/#", ItemContentProvier.ITEM_POS);

这个就是注册上的,我们先看这个path参数有ItemContentProvier.ARTICE_ITEM和ItemContentProvier.ARTICE_ITEM/#,这两个就是分别表示操作的数据库表和数据库对应某一列,最后一个参数就是我们上面也说到的匹配码,构造函数的参数为UriMatcher.NO_MATCH,它表示当uriMatcher不能匹配指定的URI时,就返回代码UriMatcher.NO_MATCH常量值为-1

public int match (Uri uri)

与传入的Uri匹配,它会首先与找我们之前通过addURI方法添加进来的Uri匹配,这个URI匹配是这样的,前面部分固定是A部分:content://, B部分是authority,也就是我们addURI里面添加的第一个参数,C部分表示是路径,也就是我们在addRUI添加的第二个参数path,就是说最后匹配的URI就是这样的 content://authority/path。

authority和path都是我们在addURI参数就第一个和第二个的参数。如果匹配成功就返回之前我们设置的code值,否则返回一个UriMatcher.NO_MATCH常量值为-1

        articleProjectionMap = new HashMap<String, String>();  
        articleProjectionMap.put(Artice.ID, Artice.ID);  
        articleProjectionMap.put(Artice.TITLE, Artice.TITLE);  
        articleProjectionMap.put(Artice.CONTENT_ID,Artice.CONTENT_ID); 

在上面的put函数中,第一个参数表示列的别名,第二个参数表示列的真实名称。在这个例子中,我们把列的别名和和真实名称都设置成一样的。

在query函数中,我们使用SQLiteQueryBuilder来辅助数据库查询操作,使用这 个类的好处是我们可以不把数据库表的字段暴露出来,而是提供别名给第三方应用程序使用,这样就可以把数据库表内部设计隐藏起来,方便后续扩展和维护。列别 名到真实列名的映射是由上面这个HashMap成员变量来实现的,当然这里没有修改,也可以不用定义。

复制代码
    @Override
    public String getType(Uri uri) {
        // TODO Auto-generated method stub
        switch (uriMatcher.match(uri)) { 
        case ItemContentProvier.ITEM:{
            return ItemContentProvier.CONTENT_TYPE;
        }
        case ItemContentProvier.ITEM_POS:{
            return ItemContentProvier.CONTENT_ITEM_TYPE;
        }
        default:
            throw new IllegalArgumentException("Error Uri: " + uri); 
        }
    }
复制代码

这个是返回当前Uri所数据的MIME类型,如果该Uri对应的数据可能包括多条记录,那么MIME类型字符串就是以 vnd.android.cursor.dir/开头,我们通过前面的addURI指定 ItemContentProvier.ITEM是返回全面的类型,如果Uri对应的数据只包含一条记录,那么MIME类型字符串就是以 vnd.android.cursor.item/开头,前面的addURI得知ItemContentProvier.ITEM_POS这个返回的是某一列信息。

还有一点是我们在itContentProvider类的内部中定义了一个DBHelper类,它继承于SQLiteOpenHelper类,它用是用辅助我 们操作数据库的。使用这个DBHelper类来辅助操作数据库的好处是只有当我们第一次对数据库时行操作时,系统才会执行打开数据库文件的操作,

剩下的更新查询删除等操作就不多说了,最后不要忘记在AndroidManifest.xml中进行定义

         <provider
            android:name="com.itchq.contentprovider.itContentProvider"
            android:authorities="com.itchq.contentprovider"
            android:multiprocess="false"
            />

在配置Content Provider的时候,最重要的就是要指定它的authorities属性了,只有配置了这个属性,第三方应用程序才能通过它来找到这个Content Provider。这要需要注意的,这里配置的authorities属性的值是和我们前面在ItemContentProvier.java文件中定义的AUTHORITY 常量的值是一致的。另外一个属性multiprocess是一个布尔值,它表示这个Content Provider是否可以在每个客户进程中创建一个实例,这样做的目的是为了减少进程间通信的开销。这里我们为了减少不必要的内存开销,把属性 multiprocess的值设置为false,使得系统只能有一个Content Provider实例存在,它运行在自己的进程中。下面看看在Activity中投入和操作这些数据库的

复制代码
    private void add(){
        ContentValues values = new ContentValues();
        values.put(Artice.TITLE, "test");
        values.put(Artice.CONTENT_ID, 1);
        Uri uri = getContentResolver().insert(ItemContentProvier.CONTENT_ARTICE, values);
    }
    
    private void query(){
        String[] projection = new String[] {  
                Artice.ID,  
                Artice.TITLE,  
                Artice.CONTENT_ID
        };
        Cursor cursor = getContentResolver().query(ItemContentProvier.CONTENT_ARTICE, projection, null, null, ItemContentProvier.DEFAULT_SORT_ORDER);
        if (cursor.moveToFirst()) {
            do{
                int id=cursor.getInt(cursor.getColumnIndex(Artice.ID));
                String title=cursor.getString(cursor.getColumnIndex(Artice.TITLE));
                int content_id=cursor.getInt(cursor.getColumnIndex(Artice.CONTENT_ID));

            }while(cursor.moveToNext());
        }
    }
复制代码
ItemContentProvier.CONTENT_ARTICE就是我们前面定义的那个URI
这个介绍一个ContentUris类,这个类是它用于在Uri后面追加一个ID或者解析出传入的Uri所带上的ID值,就是我们说的URI规则中最后D部分
|------A------|-----------------B-------------------|---C---|---D--|
常用的两个方法如下:
public static Uri withAppendedId (Uri contentUri, long id)  用于为路径加上ID部分
Uri resultUri = ContentUris.withAppendedId(ItemContentProvier.CONTENT_ARTICE, 10);
那么这个Uri就是content://com.itchq.contentprovider/articeitem/10,那么我们在前面使用UriMatch.addURI匹配码就是
uriMatcher.addURI(ItemContentProvier.AUTHORITY, ItemContentProvier.ARTICE_ITEM+"/#", ItemContentProvier.ITEM_POS);
这个,那么这个时候返回的匹配码就是 ItemContentProvier.ITEM_POS。

public static long parseId (Uri contentUri)从路径中获取ID部分
Uri uri = Uri.parse("content://com.itchq.contentprovider/articeitem/10"
long personid = ContentUris.parseId(uri);//获取的结果为:10,前面的操作中有用到这个
itchq
TMS_WebGMaps_1.9.8.0_Full_Source TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder 立即下载

相关推荐

《数学建模与数学实验》第5版 线性规划 习题3.4

1. 某鸡场有1000只鸡,用动物饲料和谷物混合喂养. 2. 某工厂用A1,A2两台机床加工B1,B2,B3三种不同零件. 3. 某工厂利用两种原料甲、乙生产$A_1、A_2、A_3$三种产品. 4. 每班的护士在值班开始时向病房报到,连续工作8个小时. 5. 某工厂生产 A1 、A2 两种型号的产品 6. 有两个煤厂A,B 7. 某工厂制造三种产品,生产这三种产品需要三种资源 8. 已知某工厂计划生产1,2,3三种产品,各产品需要在ABC设备加工。...

hexiaosi_的博客 2万+

Android ContentProvider的介绍

一、ContentProvider的概念  ContentProvider:为存储和获取数据提供统一的接口。可以在不同的应用程序之间共享数据。Android已经为常见的一些数据提供了默认的ContentProvider  1、ContentProvider使用表的形式来组织数据   无论数据的来源是什么,ContentProvider都会认为是一种表,然后把数据组织成表格  2、Cont...

FLY_THINK2012的博客 90

UE5音效系统全解析:从Sound Cue到MetaSounds的实战指南

在游戏开发中,音频系统是构建沉浸式体验的关键技术之一。其核心原理在于通过数字信号处理(DSP)和空间音频渲染,模拟真实世界的听觉感知。传统音频管线通常基于静态资源播放与混合,而现代引擎则引入了程序化音频生成与动态调制技术,这极大地提升了音频的互动性与表现力,使其能够实时响应游戏状态变化。这一技术革新对于开发开放世界、VR及3A级游戏尤为重要,它能实现风吹草动皆有不同声响、音效随环境动态变化的细腻效果。本文聚焦虚幻引擎5(UE5)的音效系统,深入剖析其新旧两套核心架构:稳定高效的Sound Cue、Sound

weixin_31179927的博客 334

android ContentProvider简单介绍及使用

从ContentProvider与ContentResolver和Uri的关系,无论是ContentResolver还是ContentProvider,它们所提供的CRUD方法的第一个参数都是uri,也就是说Uri是ContentProvider 与ContentResolver数据交换的标识符,ContentResolver对指定的Uri执行CRUD操作,但uri并不是真正的数据中心,因此CRU

WannerWang的博客 500

ENSP Pro VXLAN EVPN分布式网关部署配置

在BGP EVPN方式部署分布式网关的场景中,控制平面的流程包括VXLAN隧道建立、MAC地址动态学习;转发平面的流程包括同子网已知单播报文转发、同子网BUM报文转发、跨子网报文转发。该方式实现的功能全面,支持主机IP路由通告、主机MAC地址通告、主机ARP通告,可以直接使能ARP广播抑制功能。如果在VXLAN网络中采用分布式网关,推荐使用此方式。对比集中式网关,分布式网关的arp条目比集中式网关的arp条目少,分布式网关只学习租户侧的arp条目,不学习网络侧的arp条目。

qq2353177176的博客 4564

3DMax高效建模与人工智能:一场颠覆传统创作的效率革命

AI与3DMax的结合,不仅是工具效率的升级,更是一场创作范式的革命。从“手动雕刻”到“智能共生”,设计师的角色正从执行者转向决策者。正如网友所言:“AI不是替代人类,而是赋予凡人以神笔。”在这场变革中,唯有拥抱技术、深耕创意,方能在数字艺术的浪潮中立于潮头。参考文献与工具推荐技术原理:火星时代资讯《人工智能和三维建模》工具实测:哔哩哔哩《tyDiffusion 3dsMax应用》9、Tripo AI官网教育案例:原创论文《人工智能技术介入三维动画课程建设》

m0_46478534的博客 3019

Android之---ContentProvider介绍

ContentProvider—Android四大组件之一

AM小可乐的博客 449

CloudCompare

分割点云:选中要分割的点云文件–>Segment–>左键框出要分割的点或者区域–>Segment Out–>Comfirm Segmentation,原点云文件被分割成两个结构,选中分割出来的remaining,右键delete即可。qSRA (Surface of Revolution Analysis):计算一个点云和一个假定旋转平面之间的距离(旋转平面用2D轮廓定义),距离计算好后,用户可以创建一个偏差的2D图或者圆柱或圆锥的投影。②表现为同样的对象或者至少有同样的形状。

xiaoyaolangwj的博客 4709

安卓中的数据存储方式以及ContentProvider的简单介绍

1.介绍android的数据存储方式 File存储 sharedPrefrence存储方式 conmtentprovider sqlitedatabase 网络存储   2.请介绍下ContentProvider是如何实现数据共享的 安卓中如果想将自己应用程序的数据暴露给其他的应用程序的时候就需要创建内容提供者.第三方可以通过contentResolver来访问该provider   3.为什么要

geeksi的博客 371

Balser相机的硬件触发实战:从连线到信号处理

本文详细介绍了Balser相机硬件触发的实战应用,从硬件接线、信号定义到软件配置(Pylon Viewer及API)提供了完整指南。重点阐述了如何利用外部物理电信号实现微秒级精准触发,解决工业场景下的同步与延迟问题,并分享了信号调理、抗干扰等高级实战经验。

y9z0a1b的博客 339

基于simulink的能量管理策略的场景实例:混合动力电动汽车(HEV)的能量回收与分配策略

本文以混合动力电动汽车(HEV)为研究对象,通过Simulink建模详细演示了能量管理策略的设计与实现。内容涵盖HEV系统架构、核心组件工作原理,并分步骤指导搭建车辆动力学模型、动力系统组件模型和基于规则的能量管理策略。重点分析了制动能量回收与功率分配机制,通过仿真验证了逻辑门限策略在提升燃油经济性和维持电池SOC平衡方面的有效性。文章最后展望了更高级控制策略的应用前景,为HEV能量优化提供了完整的仿真研究框架。

xiaoheshang_123的博客 213

安卓开发四大组件——contentProvider基本使用介绍(1)

问题背景 我们在安卓日常开发和学习过程中,contentProvider是个很常见的概念,毕竟是四大组件之一。不过可能工作和学习过程中涉及到contentProvider的场景有时候不是很多。本文先初步介绍下contentProvider的基本使用。 问题分析 话不多说,直接上代码,代码主要可以分为两大部分,一个是内容提供...

baorant24的博客 872

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Android四大组件之ContentProvider介绍和简单实例

Content Providers Content provider管理android以结构化方式存放的数据。他以相对安全的方式封装数据并且提供简易的处理机制。Content provider提供不同进程间数据交互的标准化接口。当你准备取出content provider中的数据时,你需要获得一个和当前上下文相关的ContentResolver对象作为客户端。这个...

xkfer 2453

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Android ContentProvider的介绍(很详细)

博客分类: android进阶 一、ContentProvider的概念  ContentProvider:为存储和获取数据提供统一的接口。可以在不同的应用程序之间共享数据。Android已经为常见的一些数据提供了默认的ContentProvider  1、ContentProvider使用表的形式来组织数据   无论数据的来源是什么,ContentProvider都会认为是...

weixin_30547797的博客 61

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

【Android数据存储】ContentProvider详细介绍(附实例源码)

1.ContentProvider是什么?     ContentProvider——内容提供者。它是一个类,这个类主要是对Android系统中进行共享的数据进行包装,并提供了一组统一的访问接口供其他程序调用。这些被共享的数据,可以使系统自己的也可以使我们个人应用程序中的数据,ContentProvider使用表的形式来组织数据. 2.为什么要有ContentPro

毕小烦的学习笔记 6707

Android中使用ContentProvider读取数据的介绍

1.添加布局,相信大家已经习以为常 主界面添加一个ListView控件,在创建一个xml文件添加相应的布局即可. 注意:LIstView控件中的android:layout_height最好指定为match_parent,不要指定为wrap_content 因为:前者它可以根据屏幕的高和LIstView的高算出一个屏幕可以展示出多少的条目,后者算不出来了,是对ListView的优化 ...

weixin_30701521的博客 312
上一篇: PYTHON框架之DJANGO学习笔记(十四)
lin91o7c
博客等级 码龄12年 1粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值