【Android入门学习】关卡1:四大组件

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的知识都在这里了!

以上所有代码:
添加链接描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值