1.Android生命周期:
1)启动流程:
onCreate->onStart->onResume
2)被覆盖状态或锁屏:
调用onPause;若再次回到主页,依次调用onRestart->onStart->onResume
D/com.marcy.androidintroduction.MainActivity: -->onPause:
D/com.marcy.androidintroduction.MainActivity: -->onStop:
D/com.marcy.androidintroduction.MainActivity: -->onRestart:
D/com.marcy.androidintroduction.MainActivity: -->onStart:
D/com.marcy.androidintroduction.MainActivity: -->onResume:
3)转到其他activity或按home键回主页:
onPause->onStop
D/com.marcy.androidintroduction.MainActivity: -->onPause:
D/com.marcy.androidintroduction.MainActivity: -->onStop:
4)再次回退到该activity:
onRestart->onStart->onResume
D/com.marcy.androidintroduction.MainActivity: -->onRestart:
D/com.marcy.androidintroduction.MainActivity: -->onStart:
D/com.marcy.androidintroduction.MainActivity: -->onResume:
5)用户退出该activity:
onPause->onStop->onDestroy
D/com.marcy.androidintroduction.SecondActivity: -->onPause:
D/com.marcy.androidintroduction.SecondActivity: -->onStop:
D/com.marcy.androidintroduction.SecondActivity: -->onDestroy:
- onRestart代表activity正重新启动,每当activity处于不可见状态再转为可见时便会调用。可理解成当activity的生命周期未走到 onDestroy,再次启动时便会调用onRestart。
- onStart代表Activity可见,但未出现在前台,还无法和用户交互
- onPause代表Activity正在停止,可做一些存储工作。此方法必须执行完,onResume才会开始
D/com.marcy.androidintroduction.activitylifecycle.MainActivity: -->onPause:
D/com.marcy.androidintroduction.activitylifecycle.SecondActivity: -->onCreate:
D/com.marcy.androidintroduction.activitylifecycle.SecondActivity: -->onStart:
D/com.marcy.androidintroduction.activitylifecycle.SecondActivity: -->onResume:
源码查看:可见逻辑,当pause,并且ResumeWhilePausing为false的时候,向下执行。
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
pausing |= startPausingLocked(userLeaving, false, next, false);
}
if (pausing && !resumeWhilePausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
"resumeTopActivityLocked: Skip resume: need to start pausing");
// At this point we want to put the upcoming activity's process
// at the top of the LRU list, since we know we will be needing it
// very soon and it would be a waste to let it get killed if it
// happens to be sitting towards the end.
if (next.app != null && next.app.thread != null) {
mService.updateLruProcessLocked(next.app, true, null);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
if (lastResumed != null) {
lastResumed.setWillCloseOrEnterPip(true);
}
return true;
}
6)activity横竖屏切换时,会先保存,销毁,再重新生成,加载保存数据。
也即是onPause->onSaveInstanceState->onStop->onDestroy
再重新生成onCreate->onStart->onRestoreInstanceState->onResume
D/com.marcy.androidintroduction.activitylifecycle.MainActivity: -->onPause:
D/com.marcy.androidintroduction.activitylifecycle.MainActivity: -->onSaveInstanceState:
D/com.marcy.androidintroduction.activitylifecycle.MainActivity: -->onStop:
D/com.marcy.androidintroduction.activitylifecycle.MainActivity: -->onDestroy:
D/com.marcy.androidintroduction.activitylifecycle.MainActivity: -->onCreate:
D/com.marcy.androidintroduction.activitylifecycle.MainActivity: -->onStart:
D/com.marcy.androidintroduction.activitylifecycle.MainActivity: -->onRestoreInstanceState:
D/com.marcy.androidintroduction.activitylifecycle.MainActivity: -->onResume:
此处采用android9时,onSaveInstanceState和onStop执行顺序会发生互换
onSaveInstanceState只会在程序异常结束的情况下执行
案例:新建一个edittext,输入数据,接着界面旋转,让程序执行onSaveInstanceState,查看保存的数据:
@Override
protected void onSaveInstanceState(Bundle outState) {
Log.d(TAG, TAG + "-->onSaveInstanceState: ");
super.onSaveInstanceState(outState);
outState.putString("extra_test","测试数据");
Parcelable test = mEt.onSaveInstanceState();
}
可以在debug中查看到存储的数据:
editorState = {ParcelableParcel@4719}
error = null
frozenWithFocus = true
selEnd = 3
selStart = 3
text = {SpannableStringBuilder@4720} "得得得得得"
mStartActivityRequestWhoSaved = null
mSuperState = null
此处并非全部数据。但可以看出,主要的定位与值已被保存。
2.Activity与Fragment生命周期关系
1)启动时,fragment在activity执行到onStart时,先onAttach,再执行正常的启动流程:
24396-24396 D: MainActivity-->onCreate:
24396-24396 D: MainActivity-->onStart:
24396-24396 D: MainFragment-->onAttach:
24396-24396 D: MainFragment-->onCreate:
24396-24396 D: MainFragment-->onCreateView:
24396-24396 D: MainFragment-->onViewCreated:
24396-24396 D: MainFragment-->onStart:
24396-24396 D: MainActivity-->onResume:
24396-24396 D: MainFragment-->onResume:
2) activity退出前台时,fragment的生命周期与activity前后执行
22730-22730 D: MainActivity-->onPause:
22730-22730 D: MainFragment-->onPause:
22730-22730 D: SecondActivity-->onCreate:
22730-22730 D: SecondActivity-->onStart:
22730-22730 D: SecondActivity-->onResume:
22730-22730 D: MainActivity-->onSaveInstanceState:
22730-22730 D: MainActivity-->onStop:
22730-22730 D: MainFragment-->onStop:
3)activity结束时,依附在activity上的fragment与加载时一样,最后一步调用Detach:
24396-24396 D: MainActivity-->onPause:
24396-24396 D: MainFragment-->onPause:
24396-24396 D: MainActivity-->onStop:
24396-24396 D: MainFragment-->onStop:
24396-24396 D: MainActivity-->onDestroy:
24396-24396 D: MainFragment-->onDestroyView:
24396-24396 D: MainFragment-->onDestroy:
24396-24396 D: MainFragment-->onDetach:
3.activity与menu创建顺序:
1)创建顺序:最后执行
25697-25697 D: MainActivity-->onCreate:
25697-25697 D: MainActivity-->onStart:
25697-25697 D: MainActivity-->onResume:
25697-25697 D: MainActivity-->onCreateOptionsMenu:
4.Activity的启动模式
采用adb shell dumpsys activity activities查看任务栈
1)standard
最常见模式,标准模式,每次跳转创建一个实例,跳转后的activity加入到跳转时的那个activity的栈中。点击四次跳转MainActivity,再点击一次跳转SecondActivity的栈如图所示:
Running activities (most recent first):
TaskRecord{fe26711 #3066 A=com.marcy.androidintroduction U=0 StackId=1 sz=6}
Run #6: ActivityRecord{efa4ff5 u0 com.marcy.androidintroduction/.activitylifecycle.SecondActivity t3066}
Run #5: ActivityRecord{35428e8 u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3066}
Run #4: ActivityRecord{cb7ebc9 u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3066}
Run #3: ActivityRecord{6de5b91 u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3066}
Run #2: ActivityRecord{33e6607 u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3066}
Run #1: ActivityRecord{1728969 u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3066}
TaskRecord{553692d #2352 A=com.transsion.phonemaster U=0 StackId=1 sz=1}
Run #0: ActivityRecord{800bb52 u0 com.transsion.phonemaster/com.cyin.himgr.widget.activity.MainActivity t2352}
此后再跳转一次MainActivity:
Run #7: ActivityRecord{46ca5c0 u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3067}
Run #6: ActivityRecord{f960dbc u0 com.marcy.androidintroduction/.activitylifecycle.SecondActivity t3067}
Run #5: ActivityRecord{c628ebf u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3067}
Run #4: ActivityRecord{b76131d u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3067}
Run #3: ActivityRecord{96c2d3a u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3067}
Run #2: ActivityRecord{f916dc4 u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3067}
Run #1: ActivityRecord{bea8590 u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3067}
TaskRecord{553692d #2352 A=com.transsion.phonemaster U=0 StackId=1 sz=1}
Run #0: ActivityRecord{800bb52 u0 com.transsion.phonemaster/com.cyin.himgr.widget.activity.MainActivity t2352}
2)singleTop
栈顶复用模式。若当前新activity已处于栈顶,则activity不会被重复创建,每次跳转时onStart不会被重复调用。但当activity不处于栈顶,则仍会重复创建
示例:点击若干次跳转MainActivity,再点击跳转SecondeActivity,在SecondActivity中再跳转回MainActivity
log:
19640-19640 D: MainActivity-->onPause:
19640-19640 D: MainActivity-->onResume:
19640-19640 D: MainActivity-->onPause:
19640-19640 D: SecondActivity-->onCreate:
19640-19640 D: SecondActivity-->onStart:
19640-19640 D: SecondActivity-->onResume:
19640-19640 D: MainActivity-->onSaveInstanceState:
19640-19640 D: MainActivity-->onStop:
19640-19640 D: SecondActivity-->onPause:
19640-19640 D: MainActivity-->onCreate:
19640-19640 D: MainActivity-->onStart:
19640-19640 D: MainActivity-->onResume:
19640-19640 D: MainActivity-->onCreateOptionsMenu:
19640-19640 D: SecondActivity-->onStop:
任务栈:
Running activities (most recent first):
TaskRecord{19389bd #3068 A=com.marcy.androidintroduction U=0 StackId=1 sz=3}
Run #3: ActivityRecord{8d6b607 u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3068}
Run #2: ActivityRecord{570e996 u0 com.marcy.androidintroduction/.activitylifecycle.SecondActivity t3068}
Run #1: ActivityRecord{baa02cb u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3068}
TaskRecord{553692d #2352 A=com.transsion.phonemaster U=0 StackId=1 sz=1}
Run #0: ActivityRecord{800bb52 u0 com.transsion.phonemaster/com.cyin.himgr.widget.activity.MainActivity t2352}
3)SingleTask
栈内复用模式,只要Activity在该栈中存在,那么多次启动该Activity都不会重新创建实例。若不存在,则系统会先创建一个新的任务栈,再将实例入栈该栈。
当以ApplicationContext启动Activity时,在清单配置栈名或指定SINGLE_TASK标签时都能让Activity达成SingleTask效果。
示例1:
SecondActivity设置跳转模式singleTask,不指定任务栈,ThirdActivity不设置跳转模式,先让SecondActivity跳转去ThirdActivity,再从ThirdActivity跳转回来,再跳转回ThirdActivity
log:
26379-26379 D: SecondActivity-->onPause:
26379-26379 D: ThirdActivity-->onCreate:
26379-26379 D: ThirdActivity-->onStart:
26379-26379 D: ThirdActivity-->onResume:
26379-26379 D: SecondActivity-->onStop:
26379-26379 D: ThirdActivity-->onPause:
26379-26379 D: SecondActivity-->onRestart:
26379-26379 D: SecondActivity-->onStart:
26379-26379 D: SecondActivity-->onResume:
26379-26379 D: ThirdActivity-->onStop:
26379-26379 D: ThirdActivity-->onDestroy:
26379-26379 D: SecondActivity-->onPause:
26379-26379 D: ThirdActivity-->onCreate:
26379-26379 D: ThirdActivity-->onStart:
26379-26379 D: ThirdActivity-->onResume:
26379-26379 D: SecondActivity-->onStop:
任务栈:
Running activities (most recent first):
TaskRecord{a7163bc #3069 A=com.marcy.androidintroduction U=0 StackId=1 sz=3}
Run #3: ActivityRecord{899a474 u0 com.marcy.androidintroduction/.activitylifecycle.ThirdActivity t3069}
Run #2: ActivityRecord{6a40352 u0 com.marcy.androidintroduction/.activitylifecycle.SecondActivity t3069}
Run #1: ActivityRecord{d329d59 u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3069}
TaskRecord{553692d #2352 A=com.transsion.phonemaster U=0 StackId=1 sz=1}
Run #0: ActivityRecord{800bb52 u0 com.transsion.phonemaster/com.cyin.himgr.widget.activity.MainActivity t2352}
从log可见,当第二次回到SecondActivity时,ThirdActivity调用了onDestory,也即是当在同一栈中,再次调用启动方式为SingleTask的Activity时,栈顶的Activity被移除。
示例2:
指定SecondActivity启动模式SingleTask,指定ThirdActivity启动栈为com.testsingletask.stack,并使用Application启动,再次执行SecondActivity跳转ThirdActivity,再从ThirdActivity跳转去SecondActivity
29602-29602 D: SecondActivity-->onPause:
29602-29602 D: ThirdActivity-->onCreate:
29602-29602 D: ThirdActivity-->onStart:
29602-29602 D: ThirdActivity-->onResume:
29602-29602 D: SecondActivity-->onStop:
29602-29602 D: ThirdActivity-->onPause:
29602-29602 D: SecondActivity-->onRestart:
29602-29602 D: SecondActivity-->onStart:
29602-29602 D: SecondActivity-->onResume:
29602-29602 D: ThirdActivity-->onStop:
29602-29602 D: SecondActivity-->onPause:
29602-29602 D: ThirdActivity-->onRestart:
29602-29602 D: ThirdActivity-->onStart:
29602-29602 D: ThirdActivity-->onResume:
29602-29602 D: SecondActivity-->onStop:
可见此时ThirdActivity没有被onDestory
任务栈:
TaskRecord{8cef55f #3073 A=com.testsingletask.stack U=0 StackId=1 sz=1}
Run #3: ActivityRecord{1f9dc48 u0 com.marcy.androidintroduction/.activitylifecycle.ThirdActivity t3073}
TaskRecord{cec680a #3072 A=com.marcy.androidintroduction U=0 StackId=1 sz=2}
Run #2: ActivityRecord{cf45556 u0 com.marcy.androidintroduction/.activitylifecycle.SecondActivity t3072}
Run #1: ActivityRecord{cd8615b u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3072}
TaskRecord{da92abb #3070 A=com.edog.car.oushangsdk U=0 StackId=1 sz=1}
Run #0: ActivityRecord{800bb52 u0 com.transsion.phonemaster/com.cyin.himgr.widget.activity.MainActivity t2352}
4)SingleInstance
按照SingleInstance模式启动的Activity具备全局唯一性。每次启动均会开启一个新的线程
案例:
将SecondActivity设为singleInstance,启动Main,跳转Second,再跳转Third,再跳转Second,再跳转Third……多次交换
28118-28118 D: MainActivity-->onStop:
28118-28118 D: SecondActivity-->onPause:
28118-28118 D: ThirdActivity-->onCreate:
28118-28118 D: ThirdActivity-->onStart:
28118-28118 D: ThirdActivity-->onResume:
28118-28118 D: SecondActivity-->onStop:
28118-28118 D: ThirdActivity-->onPause:
28118-28118 D: SecondActivity-->onRestart:
28118-28118 D: SecondActivity-->onStart:
28118-28118 D: SecondActivity-->onResume:
28118-28118 D: ThirdActivity-->onStop:
28118-28118 D: SecondActivity-->onPause:
28118-28118 D: ThirdActivity-->onCreate:
28118-28118 D: ThirdActivity-->onStart:
28118-28118 D: ThirdActivity-->onResume:
28118-28118 D: SecondActivity-->onStop:
28118-28118 D: ThirdActivity-->onPause:
28118-28118 D: SecondActivity-->onRestart:
28118-28118 D: SecondActivity-->onStart:
28118-28118 D: SecondActivity-->onResume:
28118-28118 D: ThirdActivity-->onStop:
查看thead:
TaskRecord{1da85d9 #3355 A=com.marcy.androidintroduction U=0 StackId=1 sz=1}
Run #3: ActivityRecord{2e299af u0 com.marcy.androidintroduction/.activitylifecycle.SecondActivity t3355}
TaskRecord{53867f #3354 A=com.marcy.androidintroduction U=0 StackId=1 sz=3}
Run #2: ActivityRecord{ab46d87 u0 com.marcy.androidintroduction/.activitylifecycle.ThirdActivity t3354}
Run #1: ActivityRecord{91e4aee u0 com.marcy.androidintroduction/.activitylifecycle.ThirdActivity t3354}
Run #0: ActivityRecord{981be6f u0 com.marcy.androidintroduction/.activitylifecycle.MainActivity t3354}
可见目前SecondActivity独立存在在一个线程之中,而ThirdActivity正常创建了多个。
3.Service
三种启动方式:
1)startService
startService(new Intent(this , FirstService.class));
启动流程:
32115-32115 D: FirstService-->onCreate:
32115-32115 D: FirstService-->onStartCommand:
采用直接启动方法,在启动之后service的生命周期就和activity无关了。即使该acitiviy结束,service依旧存在。可以通过调用stopService来进行指定Service关闭
2)bindService(Intent)
采用bindservice启动:
mServiceConnection = new TestServiceConnection();
bindService(new Intent(this , FirstService.class) , mServiceConnection , Context.BIND_AUTO_CREATE);
启动流程
4802-4802 D: MainActivity-->onCreate:
4802-4802 D: MainActivity-->onStart:
4802-4802 D: MainActivity-->onResume:
4802-4802 D: FirstService-->onCreate:
4802-4802 D: FirstService-->onBind:
4802-4802 D: MainActivity-->onCreateOptionsMenu:
该生命周期与activity绑定。
强制关闭时:
4802-4802 D: FirstService-->onUnbind:
4802-4802 D: FirstService-->onDestroy:
当activity销毁时:
5953-5953 D: MainActivity-->onPause:
5953-5953 D: MainActivity-->onStop:
5953-5953 D: MainActivity-->onDestroy:
5953-5953 D: FirstService-->onUnbind:
5953-5953 D: FirstService-->onDestroy:
3)隐式启动
直接上代码
清单定制:
<service android:name=".activitylifecycle.FirstService">
<intent-filter>
<action android:name="com.example.firstservice"/>
</intent-filter>
</service>
//若不采用该方式隐式启动service,则会报Service Intent must be explicit异常。 这是Android 5.0 (Lollipop) 之后的规定
Intent intent = new Intent();
intent.setAction("com.example.firstservice");
intent.setPackage(getPackageName()); //兼容Android 5.0
startService(intent);
4.Broadcast
1.broadcast receiver两种注册方式:
注册方式决定了广播接收器的生命周期。静态接收器为常驻型,即使应用程序关闭后也会接收广播并调用。动态注册的广播注册器生命周期与activity一致。demo中采用静态接收。
1)清单静态注册
<receiver android:name=".activitylifecycle.broadcast.NormalBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"></action>
<action android:name="Haurchefant"/>
</intent-filter>
</receiver>
2)代码动态注册
registerReceiver(new NormalBroadcastReceiver() , new IntentFilter("Haurchefant"));
2.发送广播:
1)普通广播
动态接收器优先级>静态接收器优先级
Intent intent = new Intent("Haurchefant");
intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
sendBroadcast(intent);
接收器:
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, TAG + "-->onReceive: " + intent.getAction());
if(intent.getAction().equals("Haurchefant")){
Toast.makeText(context, "Haurchefant", Toast.LENGTH_SHORT).show();
}
}
运行后结果:
18642-18642 D: NormalBroadcastReceiver-->onReceive: Haurchefant
2)有序广播
发送有序广播牵扯到了广播定义中优先级这个值,也即是
android:priority=""
取值范围:-1000----1000
同优先级的情况下,动态接收器优先级>静态接收器优先级
<receiver android:name=".activitylifecycle.broadcast.OrderedFirstBroadcastReceiver">
<intent-filter
android:priority="2">
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"></action>
<action android:name="Ordered"/>
</intent-filter>
</receiver>
<receiver android:name=".activitylifecycle.broadcast.OrderedSecondBroadcastReceiver">
<intent-filter
android:priority="1">
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"></action>
<action android:name="Ordered"/>
</intent-filter>
</receiver>
如上,注册两个广播。并在activity中发射
Intent intent = new Intent("Ordered");
intent.putExtra("Key" , 123);
intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
sendOrderedBroadcast(intent , null);
结果如下:
19332-19332 D: OrderedFirstBroadcastReceiver-->onReceive: Ordered
19332-19332 D: OrderedFirstBroadcastReceiver-->onReceive: result=123
19332-19332 D: OrderedSecondBroadcastReceiver-->onReceive: result=123
3.其他问题:
android8.0之后,google对隐式Intent发送广播,也即是不指定广播组件名称做了限制,直接发送会导致Background execution not allowed: receiving Intent的bug。
突破不可发送隐式可采用addFlags来解决。
在intent.send前添加
intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);”
原理可见:
在Android8.0上突破隐式广播的限制
感谢作者的分享。
*Broadcast生命周期很短,不应在广播中开一个新线程。
在 Android 中,程序的响应( Responsive )被活动管理器( Activity Manager )和窗口管理器( Window Manager )这两个系统服务所监视。当 BroadcastReceiver 在 10 秒内没有执行完毕,Android 会认为该程序无响应。所以在 BroadcastReceiver 里不能做一些比较耗时的操作,否侧会弹出ANR ( Application No Response )的对话框。如果需要完成一项比较耗时的工作,应该通过发送Intent 给 Service ,由 Service 来完成。而不是使用子线程的方法来解决,因为 BroadcastReceiver 的生命周期很短(在 onReceive() 执行后 BroadcastReceiver 的实例就会被销毁),子线程可能还没有结束BroadcastReceiver 就先结束了。如果 BroadcastReceiver 结束了,它的宿主进程还在运行,那么子线程还会继续执行。但宿主进程此时很容易在系统需要内存时被优先杀死,因为它属于空进程(没有任何活动组件的进程)。
5.ContentProvider
ContentProvider即四大组件中内容提供者,本质是一个数据的中转站。它的原理采用了Binder机制的映射相关。
多数使用ContentProvider的场合是控制本地数据库。
//唯一标识符
public static final String AUTOHORITY = "com.marcy.sampleprovider";
//注册uri
private static final UriMatcher mMatcher;
static {
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//若资源路径="content://com.marcy.sampleprovider/user,返回注册码User_Code"
mMatcher.addURI(AUTOHORITY , "user" , User_Code);
mMatcher.addURI(AUTOHORITY , "job" , Job_Code);
}
关键方法:
@Nullable
@Override
public Uri insert( @NonNull Uri uri, @Nullable ContentValues values) {
String table = getTableName(uri);
mDB.insert(table , null , values);
mContext.getContentResolver().notifyChange(uri , null);
return uri;
}
@Nullable
@Override
public Cursor query( @NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
String table = getTableName(uri);
return mDB.query(table , projection , selection , selectionArgs , null , null , sortOrder , null);
}
代码中执行:
private Uri setUri(){
Uri uri_user = Uri.parse("content://com.marcy.sampleprovider/user");
return uri_user;
}
private ContentValues insertData(){
ContentValues values = new ContentValues();
values.put("_id" , 3);
values.put("name" , "haurchefant");
return values;
}
private void getContentResolverAndInsertDataAndQueryData(){
ContentResolver resolver = getContentResolver();
resolver.insert(setUri() , insertData());
Cursor cursor = resolver.query(setUri() , new String[]{"_id" , "name"} , null , null , null);
while (cursor.moveToNext()){
Log.d(TAG, TAG + "-->getContentResolverAndInsertDataAndQueryData: " + "query book:" + cursor.getInt(0) +" "+ cursor.getString(1));
}
cursor.close();
}
具体调用:
private void operateUser(){
setUri();
insertData();
getContentResolverAndInsertDataAndQueryData();
}
最终结果:
20992-20992 D: ContentProviderActivity-->getContentResolverAndInsertDataAndQueryData: query book:1 Carson
20992-20992 D: ContentProviderActivity-->getContentResolverAndInsertDataAndQueryData: query book:2 Kobe
20992-20992 D: ContentProviderActivity-->getContentResolverAndInsertDataAndQueryData: query book:3 haurchefant
这里讲的非常详细,感谢作者分享。
Android:关于ContentProvider的知识都在这里了!
以上所有代码:
添加链接描述