首页 > 系统 > Android > 正文

复习android四大组件(一)

2019-11-09 15:15:36
字体:
来源:转载
供稿:网友

activity:

1. 生命周期:    onCreate ---> onStart(可见) ---> onResume(获取焦点) ---> onWindowFocusChanged(焦点改变监听) ---> onPause(遮住) ---> onStop(当前activity进入后台) ---> onDestory(销毁)    onRestart(重新进入前台) ---> onStart() ---> onResume() ---> onWindowFocusChanged(焦点改变监听)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叠加。    singleTop:可以有多个实例,但是不允许多个相同Activity叠加。即,如果Activity在栈顶的时候,启动相同的Activity,不会创建新的实例,而会调用其onNewIntent方法。    singleTask:只有一个实例。在同一个应用程序中启动他的时候,若Activity不存在,则会在当前task创建一个新的实例,若存在,则会把task中在其之上的其它Activity destory掉并调用它的onNewIntent方法。    singleInstance:只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个实例,不允许有别的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都只会调用一次onCreate2. 前台服务需要调用 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"


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表