Android 四大组件基础知识(一)

1 Android 组件

       2018年,已经开始1/4,感觉自己不能在放纵自己了,要想提高就要先迈步,写博客就是我的第一步,它是我这一年是否成长的见证。各位同仁,如有写的不好的地方,请多多指点,你的指点会让我更加认清我自己,在此先表达我的谢意!

1、Activity

1、功能:是android 四大组件之一,可以用于显示view,app与用户交互的媒介。

2、 生命周期 onCreate onStart onResume onPause onStop onDestroy onRestart 七大生命周期。
知识点:
①Activity可见的生命周期 onStart~onPause。
②在onPause生命周期中可以做一些数据的保存操作,不能太耗时,因为在界面跳转时,只有onPause方法执行完毕,下一个Activity才能走onResume方法。
③onStop可以做一些重量级的回收操作,也不要太耗时。
④onDestroy 是最后的一个生命周期,在这里我们可以一些回收操作和资源的释放。

一些操作:Activity的生命周期情况:
①一个Activity第一次启动的时候,会走onCreate onStart onResume
②当A跳到B各自的生命周期:如果是透明主题,A会走onPause,B会走onCreate onStart onResume ,A是不会走onStop,如果是不透明的主题,A会走onStop。其它的生命周期一样。
③当在回到A的时候,A会走 onRestart onStart onResume
④当按back键 onPause onStop onDestroy (会出栈)
⑤如果在activity的onCreate方法中直接调用finish方法Activity会走onCreate onDestroy。开发文档中,onResume  onPause onStop 这三种状态存在的时间比较长,如果我们直接调用finish方法,不存在交互,也就不会调用这写方法了。
⑤如果一个activity设置的启动模式为:singleTask,在此页面在启动此页面会都会走那些生命周期:onPause,onNewIntent,onResume 。

Activity静态加载fragment:
(1)所谓静态加载就是定义一个fragment,在依赖的Activity布局文件中通过name属性直接引用的方式,代码如下:
<fragment    
    android:id="@+id/myFragment"    
    android:name="com.ugdao.activityandfragment.MyFragment"    
    android:layout_width="match_parent"    
    android:layout_height="wrap_content"></fragment>   
(2)所走的生命周期如下:AAA标签代表:Fragment,aaa标签代表:Activity(启动走的生命周期)  
04-16 17:03:59.557 27124-27124/? E/AAA: onAttach:     
04-16 17:03:59.557 27124-27124/? E/AAA: onCreate:     
04-16 17:03:59.557 27124-27124/? E/AAA: onCreateView:     
04-16 17:03:59.567 27124-27124/? E/aaa: onCreate:
04-16 17:03:59.557 27124-27124/? E/AAA: onActivityCreated:      
04-16 17:03:59.567 27124-27124/? E/AAA: onStart:     
04-16 17:03:59.567 27124-27124/? E/aaa: onStart:     
04-16 17:03:59.567 27124-27124/? E/aaa: onResume:     
04-16 17:03:59.567 27124-27124/? E/AAA: onResume: 
(3)按back键,销毁activity,activity所走的生命周期如下:(Fragment引领着Activity)  
04-16 17:17:05.297 28898-28898/com.ugdao.activityandfragment E/AAA: onPause:     
04-16 17:17:05.297 28898-28898/com.ugdao.activityandfragment E/aaa: onPause:    
04-16 17:17:05.687 28898-28898/com.ugdao.activityandfragment E/AAA: onStop:     
04-16 17:17:05.687 28898-28898/com.ugdao.activityandfragment E/aaa: onStop:    
04-16 17:17:05.687 28898-28898/com.ugdao.activityandfragment E/AAA: onDestroy:    
04-16 17:17:05.687 28898-28898/com.ugdao.activityandfragment E/AAA: onDetach:    
04-16 17:17:05.687 28898-28898/com.ugdao.activityandfragment E/aaa: onDestroy:  
Activity动态加载fragment生命周期如下:(加载)(自定义一个fragment在代码中动态替换相应的布局)  
04-16 17:31:49.177 30550-30550/? E/aaa: onCreate:     
04-16 17:31:49.177 30550-30550/? E/aaa: onStart:     
04-16 17:31:49.177 30550-30550/? E/aaa: onResume    
04-16 17:31:57.857 30550-30550/com.ugdao.activityandfragment E/AAA: onAttach:     
04-16 17:31:57.857 30550-30550/com.ugdao.activityandfragment E/AAA: onCreate:     
04-16 17:31:57.867 30550-30550/com.ugdao.activityandfragment E/AAA: onCreateView:
04-16 17:31:57.867 30550-30550/com.ugdao.activityandfragment E/AAA: onActivityCreated:     
04-16 17:31:57.867 30550-30550/com.ugdao.activityandfragment E/AAA: onStart:     
04-16 17:31:57.867 30550-30550/com.ugdao.activityandfragment E/AAA: onResume  
按back键退出走的生命周期是:
04-16 18:07:13.837 884-884/com.ugdao.activityandfragment E/AAA: onPause:   
04-16 18:07:13.837 884-884/com.ugdao.activityandfragment E/aaa: onPause:   
04-16 18:07:14.217 884-884/com.ugdao.activityandfragment E/AAA: onStop:   
04-16 18:07:14.217 884-884/com.ugdao.activityandfragment E/aaa: onStop:   
04-16 18:07:14.217 884-884/com.ugdao.activityandfragment E/AAA: onDestroy:   
04-16 18:07:14.217 884-884/com.ugdao.activityandfragment E/AAA: onDetach:   
04-16 18:07:14.217 884-884/com.ugdao.activityandfragment E/aaa: onDestroy:  

Activity异常时候的生命周期(minSdkVersion 15)

(1)当我们正常启动activity时候,会走 onCreate onStart onResume三个生命周期方法

(2)当我们从竖屏切换到横屏的时候,生命周期如下:

04-17 02:38:31.374 20350-20350/com.ugdao.activityandfragment E/aaa: onPause:   
04-17 02:38:31.386 20350-20350/com.ugdao.activityandfragment E/aaa: onStop:   
04-17 02:38:31.386 20350-20350/com.ugdao.activityandfragment E/aaa: onDestroy:   
04-17 02:38:31.532 20350-20350/com.ugdao.activityandfragment E/aaa: onCreate:   
04-17 02:38:31.534 20350-20350/com.ugdao.activityandfragment E/aaa: onStart:   
04-17 02:38:31.534 20350-20350/com.ugdao.activityandfragment E/aaa: onRestoreInstanceState:   
04-17 02:38:31.536 20350-20350/com.ugdao.activityandfragment E/aaa: onResume: 

(3)再在这个基础上切换到竖屏,生命周期如下:

04-17 02:56:19.770 21306-21306/com.ugdao.activityandfragment E/aaa: onPause:   
04-17 02:56:19.779 21306-21306/com.ugdao.activityandfragment E/aaa: onStop:   
04-17 02:56:19.779 21306-21306/com.ugdao.activityandfragment E/aaa: onDestroy:   
04-17 02:56:19.845 21306-21306/com.ugdao.activityandfragment E/aaa: onCreate:   
04-17 02:56:19.846 21306-21306/com.ugdao.activityandfragment E/aaa: onStart:   
04-17 02:56:19.847 21306-21306/com.ugdao.activityandfragment E/aaa: onRestoreInstanceState:   
04-17 02:56:19.850 21306-21306/com.ugdao.activityandfragment E/aaa: onResume:  

(4)在清单文件中,给activity配置configChanges属性,属性设置为orientation|screenSize,代码如下:

<activity android:name=".MainActivity"<span style="background-color:rgb(255,0,0);"> android:configChanges="orientation|screenSize"</span>>  
     <intent-filter>  
       <action android:name="android.intent.action.MAIN" />  
  
       <category android:name="android.intent.category.LAUNCHER" />  
     </intent-filter>  
</activity>  

切换横竖屏后,就不会在走生命周期:只会走onConfigurationChanged方法,并且横竖都只走一次。

04-17 03:02:53.806 21684-21684/com.ugdao.activityandfragment E/aaa: onConfigurationChanged: 

(5)在清单文件中,给activity配置configChanges属性,属性设置为orientation|keyboardHidden,代码如下:

结果:和4一样。

注意点:

当minSdkVersion >=13时

orientation 或者orientation|keyboardHidden|screenSize,都不会重新调用各自的生命周期。

当minSdkVersion<13时

(1)不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次

(2)设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次

(3)设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

禁止横竖屏的切换方法:

一、在AndroidManifest.xml中设置activity中的android:screenOrientation属性值来实现。

(1)竖屏:android:screenOrientation="portrait"

(2)横屏:android:screenOrientation="landscape"

二、在Java代码中通过类似如下代码来设置 (不推荐这种方法,在大的app不同方向启动时会慢)

(1)竖屏: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)

(2)横屏:setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)

三、如果要彻底禁止翻转,忽略重力感应带来的切换,(模拟器上不管用,在真机上是正确的)

(1)忽略重力:android:screenOrientation="nosensor"

Activity四种启动模式:

(1)standard:默认模式,无论我们将要启动的activity在栈中的位置是否是在栈顶或栈的其它位置,都会重新创建一个实例。

(2)singleTop:栈顶模式:如果我们要启动的activity是在栈顶,在栈中就不会创建新的实例,会直接复用,如果不在栈顶,就会重新创建一个实例。

(3)singleTask:栈中单实例模式,我们将要启动的activity,如果其在栈中有实例就会直接复用这个实例,如果不是在栈顶,其上面的实例会出栈,其回到栈顶。

(4)singleInstance:特点是:启动界面的时候,它会创建一个新栈,栈中只有这一个实例,多用于跨进程通讯时候用。如:来电话显示界面。

Activity 之间传递数据

bundle理解:可以理解为是intent中的数据。

数据保存方式:

①可以把数据保存到intent对象中

②也可以把数据保存到bundle对象中,在把bundle对象封装到intent中。代码如下:

//把数据封装至intent对象中
intent.putExtra("malename", "张三");
intent.putExtra("femalename", "李四");
     
    //把数据封装至bundle对象中
    Bundle bundle = new Bundle();
    bundle.putString("malename", "张三" );
    bundle.putString("femalename", "李四" );
     
    //把bundle对象封装至intent对象中
    intent.putExtras(bundle);
    startActivity(intent);

它们俩谁更好呢,线面来分析一下:

场景一:如果是我们只启动一个界面,并且传递的值只在这个启动界面里用到,这样我们直接通过intent直接传值比较好,因为如果需要bundle保存数据的话,我们需要创建对象,我们知道创建对象是会消耗内存的,所以建议使用intent直接传值。

场景二:如果我们通过A界面可以跳转到B和C界面

直接用Intent我们就会写两遍,并且写两遍传值的方法,如果Bundle我们只需用一个Bundle对象即可,最为公用。这样就减少了代码量。所以这种情况推荐使用bundle。

如何返回数据:

基本流程:

①使用startActivityForResult(Intent intent, int requestCode)方法打开Activity;

②在新Activity中调用setResult(int requestCode,int resultCode,Intent data)方法;

③在原来的activity中重写onActivityResult(int requestCode, int resultCode,Intent data)方法;

④注意新的activitity的启动模式不能是SingleTask模式,因为如果新Activity在栈中已经创建,启动它时候是不会重新走onCreate生命周期方法的,而是会走onNewIntent方法和onResume()方法。在这个方法里我们将接收到一个新的intent,用这个intent覆盖我们之前启动此activity的intent,这样我们getIntent()方法的时候,就是最新的intent。代码如下:

@Override  
protected void onNewIntent(Intent intent) {  
    super.onNewIntent(intent);  
    setIntent(intent);  
}  

service

1、简介:

service是Android四大组件之一,其可以在后台长时间的执行工作,它不和用户产生Ui交互。如果没有显示指定service的进程,那么service和activity是运行在当前app中的Ui Thread中,其不能做耗时操作,如果想做耗时操作,需要开启子线程进行。

2、service的启动方式及生命周期

(1)start方式启动:生命周期:

   onCreate onStartCommand onDestroy

  一般使用以下两种方法创建一个startService

  ①继承Service类

 ②继承IntentService类,intentService类父类是Service,若不同时处理多个请求,优先选择IntentService,重写onHandleIntent()方法,此方法已经默认帮我们开启了一个子线程,操作完成后不需要我们手动调用stopService,onHandleIntent()方法会主动调用此方法。当我们调用startService(intent),会立即回调startCommand方法。onHandleIntent方法是在onStartCommand方法之后执行。

注意:

①在项目中有可能多次启动了此service,但是当我们调用stopService()方法或者是stopSelf方法此服务就会停止。

②若系统正在调用多个onStartCommand请求,如果其中一个请求启动时,需要停止此请求,为了避免把整个服务停掉,需要选择stopSelf(int)方法,此方法的参数就是启动请求的id,当我们调用stopSelf(int)方法时候,此id会和startCommand方法中的启动id进行比较,如果相等,就停止,如果在调用stopSelf(int)之前,service又接受了一个新的start请求,那么这个启动请求的id与stopSelf(int)传递的id不一样,就不能提停止此服务,这样就解决了这个问题。

(2)service绑定方式:生命周期

  onCreate onBind onUnbind onDestroy

 注意:创建bound service 必须重写onBind回调方法,因为此方法返回一个IBind接口,此接口是组件和service的通讯的桥梁。

组件绑定此服务的时候,会获取IBind接口,通过类型转换,可以获取此service的实例,通过实例可以调用service的方法。代码如下:

}  
       ...  
     
       bindService(new Intent(MainActivity.this, MyService.class), serviceConnection, Context.BIND_AUTO_CREATE);  
         
       ...  
  
   }  
  
   ServiceConnection serviceConnection = new ServiceConnection() {  
       @Override  
       public void onServiceConnected(ComponentName componentName, <span style="background-color:rgb(255,0,0);">IBinder iBinder</span>) {  
  
           MyService myservice = (MyService) iBinder;  
           myservice.stopSelf(1);  
       }  
  
       @Override  
       public void onServiceDisconnected(ComponentName componentName) {  
  
       }  
   };  

注意点: 我们创建service时候一定要在清单文件中进行配置,如果是通过Android studio自动生成的不用配置。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值