复习android四大组件(一)

activity:

1. 生命周期:
    onCreate ---> onStart(可见) ---> onResume(获取焦点) ---> onWindowFocusChanged(焦点改变监听) ---> onPause(遮住) ---> onStop(当前activity进入后台) ---> onDestory(销毁)

    onRestart(重新进入前台) ---> onStart() ---> onResume() ---> onWindowFocusChanged(焦点改变监听)

    判断当前的activity进入后台的方法是 onStop()

    判断当前的app进入后台的方法是:

@Override
public void onTrimMemory(int level) {
    super.onTrimMemory(level);
    switch (level){
        case TRIM_MEMORY_UI_HIDDEN:
            LogUtils.e("当前应用程序进入了后台");
            break;
    }
}


2. activity的权限问题:
    code检测activity的时候,如果android:exported="true"就会存在漏洞问题(只要添加了inter-filter、action之后exported会默认是true),我们可以通过给activity添加自定义的权限来解决
        ① 首先添加自定义的权限:<permission android:name="com.test.demo.per"/>
        ② 给activity添加自定义权限:android:permission="com.test.demo.per" , 并设置<category android:name="android.intent.category.DEFAULT" />
        ③ 在另外一个应用中添加访问权限:<uses-permission android:name="com.test.demo.per"/>
        ④ 通过指定的action获取类名类访问:
            Intent intent = new Intent();
            intent.setAction("android.intent.action.media.test");
            startActivity(intent);

3. 启动模式:
    standard:默认模式,可以不用写配置。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。
            重新startActivity(),就会重新创建一个activity; 按home键,再进去,就不会创建,走onreStart()
    singleTop:可以有多个实例,但是不允许多个相同Activity叠加。即,如果Activity在栈顶的时候,启动相同的Activity,不会创建新的实例,而会调用其onNewIntent方法。
            重新startActivity() 不在栈顶,就会重新创建一个activity; 按home键,再进去,就不会创建,走onreStart()
    singleTask:只有一个实例。在同一个应用程序中启动他的时候,若Activity不存在,则会在当前task创建一个新的实例,若存在,则会把task中在其之上的其它Activity destory掉并调用它的onNewIntent方法。
    singleInstance:只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个实例,不允许有别的Activity存在。
            会 新建一个栈 来存放这个activity的实例,下次重新激活 onNewIntent() -> onreStart() -> onResume() -> onWindowFocusChanged();
            按home键,再进去,就不会创建,走onreStart(),不会显示该activity,进入的是主任务栈

4. 保存数据状态onSaveInstanceState(Bundle outState):
    ① 当系统内存不足时, 调用onPause()和onStop()方法后的activity可能会被系统摧毁, 此时内存中就不会存有该activity的实例对象了. 如果之后这个activity重新回到前台, 之前所作的改变就会消失.
    为了避免此种情况的发生, 开发者可以覆写onSaveInstanceState()方法。
    ② 该方法的默认实现可以自动的保存UI控件的状态数据, android应用框架中定义的几乎所有UI控件都恰当的实现了onSaveInstanceState()方法
    ③ 如果需要保存额外的数据时, 就需要覆写onSaveInstanceState()方法. 如需要保存类中成员变量的值
    ④ 保存持久化数据的操作应该放在onPause()中. onSaveInstanceState()方法只适合保存瞬态数据, 比如UI控件的状态, 成员变量的值等.
    ⑤ 除了系统处于内存不足的原因会摧毁activity之外, 某些系统设置的改变也会导致activity的摧毁和重建. 例如改变屏幕方向
        if (savedInstanceState != null) {  
            temp = savedInstanceState.getString("temp");  
        }  

5. 启动activity:
    ① 启动LAUNCHER的activity:
    ② 启动DEFAULT的activity:
            startACtivity(Intent)
    ③ startactivityforresult()

6. 横竖屏切换生命周期:
    ① 默认情况下都会重新创建一次(网上有说竖屏-->横屏是一次,横屏-->竖屏是两次,但是测试都是一次)
    ② 在配置文件中给activity配置 android:configChanges="orientation|screenSize|keyboardHidden",其中"orientation|screenSize"是必须的,之后再切换屏幕,不再重新创建activity,而是走onConfigurationChanged(Configuration newConfig)方法。



Service:


1. 启动方式:
        startService(intent): onCreate() ---> onstart() ---> onStartCommand()
        stopService(intent): onDestory()
        
        bindService(intent, new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                LogUtils.e("连接成功");
                LifeService.MyBinder binder = (LifeService.MyBinder) service;
                LifeService lifeService = (LifeService) binder.getService1(); //getService1()是在MyBinder里面自定义的一个方法
                lifeService.testService();
            }
            @Override
            public void onServiceDisconnected(ComponentName name) {
                LogUtils.e("断开连接");
            }
        } , Service.BIND_AUTO_CREATE);
        : onCreate() ---> onBind() ---> onServiceConnected(ComponentName name, IBinder service)
        不管是startService还是bindStartService都只会调用一次onCreate

2. 前台服务需要调用 startForeground ( android 2.0 及其以后版本 )或 setForeground (android 2.0 以前的版本)使服务成为 前台服务。
    使用前台服务可以避免服务在后台运行的时候被系统KILL。        
    例如手机中的音乐播放器,不管手机是否是在休眠状态,只要开始播放了,系统就不会去KILL这个服务,只有当停止播放音乐时,服务才可能会回收清除。


   

BroadcastReceiver:


1. 动态注册广播:
        DynicBroadcast dynicBroadcast = new DynicBroadcast();
        IntentFilter filter = new IntentFilter();
        filter.addAction("com.fanghan.broadcase.test");
        registerReceiver(dynicBroadcast , filter);
        
        在onDestory()里面再进行注销:unregisterReceiver(dynicBroadcast);

2. 静态注册广播:
        <receiver
            android:name=".broadcasts.StaticBroadcast"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.fanghan.broadcase.test2"/>
            </intent-filter>
        </receiver>
        
        Intent intent5 = new Intent();
        intent5.setAction("com.fanghan.broadcase.test2");
        intent5.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        sendBroadcast(intent5);
        
        注意:安卓3.1之后添加了flag,两个:intent5.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)唤醒所有广播,FLAG_EXCLUDE_STOPPED_PACKAGES不唤醒未启动的应用广播(网上是这么说的,实际代码测试还是没有启动,不知道是哪里出错了)。
        

3. APP应用内部广播:
     //registerReceiver(mBroadcastReceiver, intentFilter);
     //注册应用内广播接收器
     localBroadcastManager = LocalBroadcastManager.getInstance(this);
     localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);
            
     //unregisterReceiver(mBroadcastReceiver);
     //取消注册应用内广播接收器
     localBroadcastManager.unregisterReceiver(mBroadcastReceiver);
    
     Intent intent = new Intent();
     intent.setAction(BROADCAST_ACTION);
     intent.putExtra("name", "qqyumidi");
     //sendBroadcast(intent);
     //发送应用内广播
     localBroadcastManager.sendBroadcast(intent);
    


contentprovider:


1. 使用ContentProvider共享数据的好处是统一了数据访问方式。打开api系统会默认走: 空参构造--->onCreate() ,所以初始化操作最好自己创建一个有参构造函数。

2. Uri简介:这种URI由3个部分组成, “content://”, 代表数据的路径(配置文件里面的authorities属性),table的名字。示例:
        content://media/internal/images  这个URI将返回设备上存储的所有图片
        content://contacts/people/  这个URI将返回设备上的所有联系人信息
        content://contacts/people/45 这个URI返回单个结果(联系人信息中ID为45的联系人记录)
        
        private static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        static {
            uriMatcher.addURI("com.fanghan.contentprovider.test","contact",CONTACT);
            LogUtils.e("初始化了:" + uriMatcher.match(Uri.parse("content://com.fanghan.contentprovider.test/contact")));
        }
        
        创建数据库表:
        create table contact(_id integer primary key autoincrement,name text not null,number text not null);
        

3. 获取联系人信息为例:
        ContentResolver cr = context.getContentResolver();
        Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
        if(cursor != null){
            if(cursor.moveToFirst()){
                while (cursor.moveToNext()){}
                
4. 关于Cursor的用法:
        getColumnCount():返回所有列的总数
        getColumnIndex(String columnName):返回指定列的名称,如果不存在返回-1
        getColumnName(int columnIndex):从给定的索引返回列名
        getColumnIndexOrThrow(String columnName):从零开始返回指定列名称,如果不存在将抛出IllegalArgumentException 异常
        getColumnNames():返回一个字符串数组的列名
        getCount():返回Cursor 中的行数
        moveToFirst():移动光标到第一行
        moveToLast():移动光标到最后一行
        moveToNext():移动光标到下一行
        moveToPosition(int position):移动光标到一个绝对的位置
        moveToPrevious():移动光标到上一行
        
5. 关于SQLiteDatabase的用法:
        SQLiteDatabase database = dbHelp.getWritableDatabase(); //可读可写
        SQLiteDatabase database = dbHelp.getReadableDatabase();//仅可读
        
        insert(String table, String nullColumnHack, ContentValues values):
                table名字;当values为空时插入的字段,用null;插入的数据
        query(String table, String[] columns, String selection,String[] selectionArgs, String groupBy, String having,String orderBy):
                table:表名。相当于select语句from关键字后面的部分。如果是多表联合查询,可以用逗号将两个表名分开。
                columns:要查询出来的列名。相当于select语句select关键字后面的部分。
                selection:查询条件子句,相当于select语句where关键字后面的部分,在条件子句允许使用占位符“?”
                selectionArgs:对应于selection语句中占位符的值,值在数组中的位置与占位符在语句中的位置必须一致,否则就会有异常。
                groupBy:相当于select语句group by关键字后面的部分
                having:相当于select语句having关键字后面的部分
                orderBy:相当于select语句order by关键字后面的部分,如:personid desc, age asc;
                limit:指定偏移量和获取的记录数,相当于select语句limit关键字后面的部分。
        delete(String table, String whereClause, String[] whereArgs):
        update(String table, ContentValues values, String whereClause, String[] whereArgs):
                
        
        
6. SQLite3支持 NULL、INTEGER、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)数据类型,虽然它支持的类型虽然只有五种,
    但实际上sqlite3也接受varchar(n)、char(n)、decimal(p,s) 等数据类型,只不过在运算或保存时会转成对应的五种数据类型
        
                

7. 4.2之后Contentprovider默认不再有导出属性。也就是说,android:exported属性的默认值为"false"



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值