ContentProvider
ContentProvider表示“内容提供者”;
ContentProvider是一种数据共享机制,它将允许其它应用程序对自身应用程序中的数据
执行增删改查操作;
ContentProvider是Android核心组件之一,因此,开发人员在创建它时,需要自定义继承
ContentProvider,而且,它需要在项目清单文件中(AndroidMainfest.xml)中注册;
ContentProvider需要定义用于访问数据的URI,当其他应用程序知晓对应的URI时,即可
执行数据的相关操作。
ContentProvider无需被激活,当配置了ContentProvider的应用程序被安装到设备上,
同一台设备上的其它应用程序随时都可以访问它的数据。
ContentProvider的开发步骤:
自定义类继承android,content.ContentProvider类;
重写android.content.ContentProvider类中声明的抽象方法;
在AndroidMainfest.xml文件中配置ContentProvider:
创建<application>节点下添加<provider>子节点;
配置android.name属性,指定ContentProvider类;
配置android.authorities属性,指定用于访问数据的URI的host部分;
配置android:exported属性,指定值为true。
标准URI:scheme://host:port/path
例如:http://www.goole.com:80/android
注意:基于ContentProvider中数据增删改查的方法与使用SQLite数据库时使用的方法极为相似,因此,
大多数的ContentProvider共享的数据的方式都是通过操作SQLite数据库完成的,但是,ContentProvider
与SQLite数据库没有必然的关联。
DBOpenHelper:
MainActivity:
布局设置:
要在AndroidMainfest.xml中注册:
<provider android:name="com.example.lianxi.StudentProvider"
android:exported="true"
android:authorities="test"></provider>
访问ContentProvider共享的数据
ContentResolver:ContentResolver:用于访问其它应用程序通过ContentProvider共享的数据;
通过ContextWraper类定义的getContentResolver()方法即可获取ContentResolver的对象;
通过使用ContentResolver访问上一个应用程序内的数据,例子:
布局不需修改,MainActivity:
访问到的结果为:
SimpleCursorAdapter:
SimpleCursorAdapter是一种使用Cursor对象作为数据源的Adapter;
使用SimpleCursorAdapter时,要求Cursor对象中必须存在名为_id的列。
使用实例,同样访问的是上面应用的数据:
布局:
item_student:
ContentProvider中的URI,自定义ContentProvider,实例:
运行时需要先将上一个应用部署到虚拟机中,然后再将获取数据的应用运行,
通过一个应用获取另一个应用中的数据:
其他代码同上:核心代码:
Uri uri = Uri.parse("content://com.example.lianxi.providers/student/5");//获取一个数值
Uri uri = Uri.parse("content://com.example.lianxi.providers/student");//获取所有数值
ContentObserver监听数据的变化
使用ContentObserver可监听数据变化,当注册了ContentObserver的URI对应的数据发生变化时,该类中的onChange()
方法会被回调。
调用ContentResolver类定义的registerContentObserver()可以注册ContentObserver。
注意:ContentObserver的工作原理并不是每分每秒的监听对应的数据,只有ContentProvider的增删改查方法必须通知
了数据发生变化以后,ContentObserver才能知晓数据的变化。
MainActivity:
今天今天2015年最后一天。。。。
ContentProvider是一种数据共享机制,它将允许其它应用程序对自身应用程序中的数据
执行增删改查操作;
ContentProvider是Android核心组件之一,因此,开发人员在创建它时,需要自定义继承
ContentProvider,而且,它需要在项目清单文件中(AndroidMainfest.xml)中注册;
ContentProvider需要定义用于访问数据的URI,当其他应用程序知晓对应的URI时,即可
执行数据的相关操作。
ContentProvider无需被激活,当配置了ContentProvider的应用程序被安装到设备上,
同一台设备上的其它应用程序随时都可以访问它的数据。
ContentProvider的开发步骤:
自定义类继承android,content.ContentProvider类;
重写android.content.ContentProvider类中声明的抽象方法;
在AndroidMainfest.xml文件中配置ContentProvider:
创建<application>节点下添加<provider>子节点;
配置android.name属性,指定ContentProvider类;
配置android.authorities属性,指定用于访问数据的URI的host部分;
配置android:exported属性,指定值为true。
标准URI:scheme://host:port/path
例如:http://www.goole.com:80/android
注意:基于ContentProvider中数据增删改查的方法与使用SQLite数据库时使用的方法极为相似,因此,
大多数的ContentProvider共享的数据的方式都是通过操作SQLite数据库完成的,但是,ContentProvider
与SQLite数据库没有必然的关联。
ContentProvider例子:
package com.example.lianxi;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class StudentProvider extends ContentProvider{
private DBOpenHelper helper;
@Override
public int delete(Uri arg0, String selection, String[] selectionArgs) {
SQLiteDatabase db = helper.getReadableDatabase();
db.delete("students", selection, selectionArgs);
return 0;
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
//插入
SQLiteDatabase db = helper.getReadableDatabase();
db.insert("students", null, values);
return null;
}
@Override
public boolean onCreate() {
// 完成初始化的操作
helper = new DBOpenHelper(getContext());
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// 查询
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.query("students", projection, selection, selectionArgs, null, null, sortOrder);
return cursor;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = helper.getReadableDatabase();
db.update("students", values, selection, selectionArgs);
return 0;
}
}
DBOpenHelper:
package com.example.lianxi;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DBOpenHelper extends SQLiteOpenHelper{
public DBOpenHelper(Context context){
super(context,"number2.db",null,1);
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
String sql = "CREATE TABLE [students] ("
+"[_id] INTEGER PRIMARY KEY AUTOINCREMENT,"
+"[_name] VARCHAR(50) UNIQUE NOT NULL,"
+"[_age] INT NOT NULL DEFAULT 16"
+")";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
MainActivity:
package com.example.lianxi;
import android.app.Activity;
import android.content.ContentValues;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private DBOpenHelper helper;
private SQLiteDatabase db;
private EditText name;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
helper = new DBOpenHelper(this);
db = helper.getReadableDatabase();
name = (EditText) findViewById(R.id.name);
}
public void find_All(View view){
Cursor cursor = db.query("students", new String[]{"_id","_name","_age"}, null, null, null, null, "_id desc");
long id;
String name;
int age;
for(cursor.moveToFirst(); !cursor.isAfterLast();cursor.moveToNext()){
id = cursor.getLong(cursor.getColumnIndex("_id"));
name = cursor.getString(cursor.getColumnIndex("_name"));
age = cursor.getInt(cursor.getColumnIndex("_age"));
System.out.println("id = " + id + " ," + "name = " +name +" ," + "age = " + age);
}
cursor.close();
}
public void findName(View view){
String findName = name.getText().toString();
Cursor cursor = db.query("students", null, "_name=?", new String[]{findName}, null, null, null);
if(cursor.moveToFirst()){
long id1;
String name1;
int age1;
id1 = cursor.getLong(cursor.getColumnIndex("_id"));
name1 = cursor.getString(cursor.getColumnIndex("_name"));
age1 = cursor.getInt(cursor.getColumnIndex("_age"));
Toast.makeText(this, "学生记录为id = " + id1 + " ," + "name = " +name1 + " ," + "age = " + age1, Toast.LENGTH_LONG).show();
}else{
Toast.makeText(this, "没有匹配的记录!", Toast.LENGTH_LONG).show();
}
}
}
布局设置:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/find_all"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:onClick="find_All"
android:text="查询所有数据" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="30dp"
android:orientation="horizontal" >
<EditText
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10" >
</EditText>
<Button
android:id="@+id/find"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:onClick="findName"
android:text="查询" />
</LinearLayout>
</LinearLayout>
要在AndroidMainfest.xml中注册:
<provider android:name="com.example.lianxi.StudentProvider"
android:exported="true"
android:authorities="test"></provider>
访问ContentProvider共享的数据
ContentResolver:ContentResolver:用于访问其它应用程序通过ContentProvider共享的数据;
通过ContextWraper类定义的getContentResolver()方法即可获取ContentResolver的对象;
通过使用ContentResolver访问上一个应用程序内的数据,例子:
布局不需修改,MainActivity:
package com.example.lianxi;
import android.app.Activity;
import android.content.ContentValues;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private DBOpenHelper helper;
private SQLiteDatabase db;
private EditText name;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
helper = new DBOpenHelper(this);
db = helper.getReadableDatabase();
name = (EditText) findViewById(R.id.name);
}
public void find_All(View view){
Cursor cursor = db.query("students", new String[]{"_id","_name","_age"}, null, null, null, null, "_id desc");
long id;
String name;
int age;
for(cursor.moveToFirst(); !cursor.isAfterLast();cursor.moveToNext()){
id = cursor.getLong(cursor.getColumnIndex("_id"));
name = cursor.getString(cursor.getColumnIndex("_name"));
age = cursor.getInt(cursor.getColumnIndex("_age"));
System.out.println("id = " + id + " ," + "name = " +name +" ," + "age = " + age);
}
cursor.close();
}
public void findName(View view){
String findName = name.getText().toString();
Cursor cursor = db.query("students", null, "_name=?", new String[]{findName}, null, null, null);
if(cursor.moveToFirst()){
long id1;
String name1;
int age1;
id1 = cursor.getLong(cursor.getColumnIndex("_id"));
name1 = cursor.getString(cursor.getColumnIndex("_name"));
age1 = cursor.getInt(cursor.getColumnIndex("_age"));
Toast.makeText(this, "学生记录为id = " + id1 + " ," + "name = " +name1 + " ," + "age = " + age1, Toast.LENGTH_LONG).show();
}else{
Toast.makeText(this, "没有匹配的记录!", Toast.LENGTH_LONG).show();
}
}
}
访问到的结果为:
12-30 13:36:02.608: I/System.out(1305): id=1
12-30 13:36:02.616: I/System.out(1305): name=Mike
12-30 13:36:02.616: I/System.out(1305): age=28
12-30 13:36:02.616: I/System.out(1305): id=2
12-30 13:36:02.616: I/System.out(1305): name=fgusdfg
12-30 13:36:02.616: I/System.out(1305): age=21
12-30 13:36:02.616: I/System.out(1305): id=3
12-30 13:36:02.616: I/System.out(1305): name=huanghdf
12-30 13:36:02.616: I/System.out(1305): age=23
12-30 13:36:02.616: I/System.out(1305): id=4
12-30 13:36:02.616: I/System.out(1305): name=Macal
12-30 13:36:02.616: I/System.out(1305): age=45
12-30 13:36:02.616: I/System.out(1305): id=5
12-30 13:36:02.616: I/System.out(1305): name=jiaokong
12-30 13:36:02.616: I/System.out(1305): age=34
12-30 13:36:02.616: I/System.out(1305): id=6
12-30 13:36:02.620: I/System.out(1305): name=sdfff
12-30 13:36:02.620: I/System.out(1305): age=56
SimpleCursorAdapter:
SimpleCursorAdapter是一种使用Cursor对象作为数据源的Adapter;
使用SimpleCursorAdapter时,要求Cursor对象中必须存在名为_id的列。
使用实例,同样访问的是上面应用的数据:
MainActivity:
package com.example.contentresolver;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
public class MainActivity extends Activity {
private ListView listView;
private SimpleCursorAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ContentResolver cr = getContentResolver();
Uri uri = Uri.parse("content://test");
Cursor cursor = cr.query(uri, new String[] { "_id", "_name", "_age" },
null, null, null);
listView = (ListView) findViewById(R.id.lv_student);
String[] from = { "_id", "_name", "_age" };
int[] to = { R.id.item_id, R.id.item_name, R.id.item_age };
adapter = new SimpleCursorAdapter(this, R.layout.student_item, cursor,
from, to, 0);
listView.setAdapter(adapter);
}
}
布局:
<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:gravity="center_vertical"
>
<LinearLayout
android:id="@+id/ll_head"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:id="@+id/tv_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ID"
android:gravity="center"
android:layout_weight="1"
android:padding="3dp"
android:layout_margin="1dp"
android:background="#aaaaaa"
android:textColor="#ffffff"/>
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="NAME"
android:gravity="center"
android:layout_weight="1"
android:padding="3dp"
android:layout_margin="1dp"
android:background="#aaaaaa"
android:textColor="#ffffff"/>
<TextView
android:id="@+id/tv_age"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="AGE"
android:gravity="center"
android:layout_weight="1"
android:padding="3dp"
android:layout_margin="1dp"
android:background="#aaaaaa"
android:textColor="#ffffff"/>
</LinearLayout>
<ListView
android:id="@+id/lv_student"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="30dp"></ListView>
</RelativeLayout>
item_student:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="@+id/item_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ID"
android:gravity="center"
android:layout_weight="1"
android:padding="3dp"
android:layout_margin="1dp"
/>
<TextView
android:id="@+id/item_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="NAME"
android:gravity="center"
android:layout_weight="1"
android:padding="3dp"
android:layout_margin="1dp"
/>
<TextView
android:id="@+id/item_age"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="AGE"
android:gravity="center"
android:layout_weight="1"
android:padding="3dp"
android:layout_margin="1dp"
/>
</LinearLayout>
ContentProvider中的URI,自定义ContentProvider,实例:
核心代码:
StudentProvider:
package com.example.lianxi;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class StudentProvider extends ContentProvider {
/*
* 验证URI 1、是否合法 2、判断操作类型
*/
/*
* 合法的URI content://com.example.lianxi.providers/student 访问全部的数据
* content://com.example.lianxi.providers/student/5 访问ID为5的数据
*/
private DBOpenHelper helper;
private static UriMatcher MATCHER;// 用于验证URi的类
private static String AUTHORITY = "com.example.lianxi.providers";
private static String PATH = "student";
private static int MATCHER_ALL = 23;
private static int MATCHER_ID = 34;
static {
MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
MATCHER.addURI(AUTHORITY, PATH, MATCHER_ALL);
MATCHER.addURI(AUTHORITY, PATH + "/#", MATCHER_ID);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
if (MATCHER.match(uri) == MATCHER_ID) {
SQLiteDatabase db = helper.getReadableDatabase();
long id = ContentUris.parseId(uri);
String whereClause;
if (selection == null || "".equals(selection)) {
whereClause = "_id" + id;
} else {
whereClause = selection + " and _id=" + id;
}
int result = db.delete("students", whereClause, selectionArgs);
return result;
} else {
throw new IllegalArgumentException("非法的URI:" + uri.toString());
}
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// 插入
if (MATCHER.match(uri) == MATCHER_ALL) {
SQLiteDatabase db = helper.getReadableDatabase();
long id = db.insert("students", null, values);
return ContentUris.withAppendedId(uri, id);// 返回的为两者合成的
} else {
throw new IllegalArgumentException("非法的URI:" + uri.toString());
}
}
@Override
public boolean onCreate() {
// 完成初始化的操作
helper = new DBOpenHelper(getContext());
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// 查询
if (MATCHER.match(uri) == MATCHER_ALL) {
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.query("students", projection, selection,
selectionArgs, null, null, sortOrder);
return cursor;
} else if (MATCHER.match(uri) == MATCHER_ID) {
SQLiteDatabase db = helper.getReadableDatabase();
long id = ContentUris.parseId(uri);
String whereClause;
if (selection == null || "".equals(selection)) {
whereClause = "_id=" + id;
} else {
whereClause = selection + " and _id=" + id;
}
Cursor cursor = db.query("students", projection, whereClause,
selectionArgs, null, null, sortOrder);
return cursor;
} else {
throw new IllegalArgumentException("非法的URI:" + uri.toString());
}
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
if (MATCHER.match(uri) == MATCHER_ID) {
SQLiteDatabase db = helper.getReadableDatabase();
long id = ContentUris.parseId(uri);
String whereClause;
if (selection == null || "".equals(selection)) {
whereClause = "_id=" + id;
} else {
whereClause = selection + " and _id=" + id;
}
int result = db
.update("students", values, whereClause, selectionArgs);
return result;
} else {
throw new IllegalArgumentException("非法的URI:" + uri.toString());
}
}
}
运行时需要先将上一个应用部署到虚拟机中,然后再将获取数据的应用运行,
通过一个应用获取另一个应用中的数据:
其他代码同上:核心代码:
Uri uri = Uri.parse("content://com.example.lianxi.providers/student/5");//获取一个数值
Uri uri = Uri.parse("content://com.example.lianxi.providers/student");//获取所有数值
ContentObserver监听数据的变化
使用ContentObserver可监听数据变化,当注册了ContentObserver的URI对应的数据发生变化时,该类中的onChange()
方法会被回调。
调用ContentResolver类定义的registerContentObserver()可以注册ContentObserver。
注意:ContentObserver的工作原理并不是每分每秒的监听对应的数据,只有ContentProvider的增删改查方法必须通知
了数据发生变化以后,ContentObserver才能知晓数据的变化。
实例:
核心代码:
StudentProvider:
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
if (MATCHER.match(uri) == MATCHER_ID) {
SQLiteDatabase db = helper.getReadableDatabase();
long id = ContentUris.parseId(uri);
String whereClause;
if (selection == null || "".equals(selection)) {
whereClause = "_id=" + id;
} else {
whereClause = selection + " and _id=" + id;
}
int result = db.delete("students", whereClause, selectionArgs);
this.getContext().getContentResolver().notifyChange(uri, null);
return result;
} else {
throw new IllegalArgumentException("非法的URI:" + uri.toString());
}
}
MainActivity:
package com.example.contentresolver;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
public class MainActivity extends Activity {
private ListView listView;
private SimpleCursorAdapter adapter;
private Cursor cursor;
private Uri uri;
private ContentResolver cr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cr = getContentResolver();
uri = Uri.parse("content://com.example.lianxi.providers/student");//获取一个数值
// Uri uri = Uri.parse("content://com.example.lianxi.providers/student");//获取所有数值
cursor = cr.query(uri, new String[] { "_id", "_name", "_age" },
null, null, null);
ContentObserver observer = new ContentObserver(new Handler()){
@Override
public void onChange(boolean selfChange) {
// TODO Auto-generated method stub
cursor.requery();
adapter.notifyDataSetChanged();
super.onChange(selfChange);
}
};
cr.registerContentObserver(uri, true, observer);
listView = (ListView) findViewById(R.id.lv_student);
String[] from = { "_id", "_name", "_age" };
int[] to = { R.id.item_id, R.id.item_name, R.id.item_age };
adapter = new SimpleCursorAdapter(this, R.layout.student_item, cursor,
from, to, 0);
listView.setAdapter(adapter);
registerForContextMenu(listView);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// TODO Auto-generated method stub
AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;
int position = info.position;
cursor.moveToPosition(position);
String studentName = cursor.getString(cursor.getColumnIndex("_name"));
menu.add(Menu.NONE,1,1,"删除"+ studentName );
super.onCreateContextMenu(menu, v, menuInfo);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
// TODO Auto-generated method stub
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
int position = info.position;
cursor.moveToPosition(position);
long id = cursor.getLong(cursor.getColumnIndex("_id"));
Uri deleteUri = ContentUris.withAppendedId(uri, id);
cr.delete(deleteUri,null,null);
return super.onContextItemSelected(item);
}
}
今天今天2015年最后一天。。。。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理