Android(一)
四大组件
Activity
- 什么是Activity
四大组件之一,一个和用户交的互界面就是一个 activity,是所有 View 的容器
生命周期
生命周期描述的是一个类 从创建(new出来)到死亡(垃圾回收)的过程中会执行的方法,在这个过程中会针对不同的生命阶段会调用不同的方法。这些回调方法包括:
1 |
|
其实这些方法都是两两对应的:
1 |
|
还有一个 onRestart 方法了,在 Activity 被 onStop 后,但是没有被 onDestroy,在再次启动此 Activity 时就调用 onRestart(而不再调用 onCreate)方法;如果被 onDestroy 了,则是调用 onCreate 方法。
时机
当一个 Activity 启动另一个 Activity,然后按返回键返回到前一个 Activity 时。
当一个 Activity 启动另一个 Activity,然后当前 Activity 被系统销毁以释放资源,之后由于某种原因 (如用户点击了 Home 键),系统重新创建了该 Activity 时。
两个Activity之间跳转时必然会执行的是哪几个方法
一般情况比如说有两个activity,分别叫A,B ,当在A里面激活B组件的时候, A 会调用 onPause()方法,!
然后B 调用onCreate() ,onStart(), OnResume() ,这个时候B覆盖了窗体, A会调用onStop()方法. 如果B呢 是个透明的,或者是对话框的样式, 就不会调用onStop()方法。横竖屏切换时候Activity的生命周期
这个生命周期跟清单文件里的配置有关系
设置Activity的android:configChanges=”orientation|keyboardHidden|screenSize”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法,游戏开发中, 屏幕的朝向都是写死的如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?
除了在栈顶的activity,其他的activity都有可能在内存不足的时候被系统回收,一个activity越处于栈底,被回收的可能性越大.如果有多个后台进程,在选择杀死的目标时,采用最近最少使用算法(LRU)。
- Activity中提供了一个 onSaveInstanceState()回调方法,这个方法会保证一定在活动被回收之前调用, 可以通过这个方法来解决活动被回收时临时数据得不到保存的问题。
- 通过onRestoreInstanceState来存储和恢复数据,区别是不需要判断空了,onRestoreInstanceState调用一定是有值的
Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它们并不一定会被触发。
当应用遇到意外情况,由系统销毁一个Activity,onSaveInstanceState() 会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。
除非该activity是被用户主动销毁的,通常onSaveInstanceState()只适合用于保存一些临时性的状态
当用户按下 HOME 键时
长按 HOME 键,选择运行其他的程序时
锁屏时
从 activity A 中启动一个新的 activity 时
屏幕方向切换时
- 发送特定广播://在baseactivity里注册广播 registerReceiver(receiver, filter)//想退出的时候就在onRecriver方法里finish()。
- 可以通过 intent的flag 来实现, intent.setFlag(FLAG_ACTIVITY_CLEAR_TOP)激活一个新的activity,然后在新的activity的oncreate方法里面就可以finish掉.
- 如何返回数据基本流程
使用 startActivityForResult(Intent intent, int requestCode) 方法打开 Activity;
新 Activity 中调用 setResult(int resultCode, Intent data) 设置返回数据之后,关闭 Activity 就会调用onActivityResult 方法;在原来的activity里重写 onActivityResult(int requestCode, int resultCode, Intent data) 方法;
注意:新的 Activity 的启动模式不能设置成 singleTask(如果已创建,会使用以前创建的)与 singleInstance(单独的任务栈),不能被摧毁(执行不到 finish 方法) ,父 Activity 中的 onActivityResult 方法将不会执行;
PendingIntent简单地理解为延迟执行的 Intent。
Android中Task任务栈的分配。
- 任务栈的概念问:一个手机里面有多少个任务栈?
答:一般情况下,有多少个应用正在运行,就对应开启多少个任务栈;每开启一个应用程序就会创建一个与之对应的任务栈;栈:后进先出,最先进栈,就会最后出栈。Activity的启动模式就是修改任务栈的排列情况 - 任务栈的作用:它是存放 Activity 的引用的,Activity不同的启动模式,对应不同的任务栈的存放;可通过 getTaskId()来获取任务栈的 ID,如果前面的任务栈已经清空,新开的任务栈 ID+1,是自动增长的;
启动模式
- standard 标准启动模式
- singleTop 单一顶部模式如果任务栈的栈顶存在这个要开启的activity,不会重新的创建activity,而是复用已经存在的activity,会调用 onNewInstance(),复用已经存在的实例。如果栈顶没有或者不在栈顶,会重新创建。应用场景:singleTop适合接收通知启动的内容显示页面。例如,某个新闻客户端的新闻内容页面,如果收到10个新闻推送,每次都打开一个新闻内容页面是很耗内存的。
- singeTask 单一任务栈,在当前任务栈里面只能有一个实例存在当开启activity的时候,就去检查在任务栈里面是否有实例已经存在,如果有实例存在就复用这个已经存在的activity,并且把这个activity上面的所有的别的activity都清空,复用这个已经存在的activity。保证整个任务栈里面只有自己的一个实例存在。会调用 onNewInstance(),复用已经存在的实例。应用场景:singleTask适合作为程序入口点,例如应用中的主页(Home页)。假设用户在主页跳转到其他页面,运行多次操作后想返回到主页,假设不使用SingleTask模式,在点击返回的过程中会多次看到主页,这明显就是设计不合理了。
- singleInstance:activity会运行在自己的任务栈里面,并且这个任务栈里面只有一个实例存在如果你要保证一个activity在整个手机操作系统里面只有一个实例存在,使用singleInstance应用场景: 电话拨打界面。singleInstance适合需要与程序分离开的页面。例如我们有个需求,需要打开别的应用,这个时候如果不设置singleInstance的话,这个新打开的应用在我们程序的任务栈里,用户想要按任务键切换的话没法切换。
https://rengwuxian.com/dang-wo-an-xia-home-jian-zai-qie-hui-lai-hui-fa-sheng-shen-me/
singleInstance 和 singleTask 的区别:singleTask 强调的只是唯一性:我只会在一个 Task 里出现;而且这个 Task 里也只会有一个我的实例。而 singleInstance 除了唯一性,还要求独占性:我要独自霸占一个完整的 Task。
使用 singleTask 模式的场景主要包括:
- 任务的入口点:适用于任务的入口点,例如应用的主界面,确保整个应用只有一个实例。
- 处理特定动作的Activity:比如一个音乐播放器的播放界面,通过设置为singleTask,可以确保只有一个播放界面存在。
值得注意的是,使用 singleTask 要小心处理 Activity 的生命周期,尤其是在 onNewIntent 方法中接收新的 Intent,并进行相应的处理。
问题:如何使用 LaunchMode 来实现单实例 Activity?
可以使用 singleTask 或 singleInstance 模式来实现单实例 Activity。
问题:如何在不同的任务栈中启动 Activity?
要在不同的任务栈中启动 Activity,可以通过设置 Intent 的 FLAG_ACTIVITY_NEW_TASK 标志位,然后调用 startActivity()方法。例如:
1 |
|
这样,TargetActivity 就会在一个新的任务栈中启动。需要注意的是,如果目标 Activity 已经存在于其他任务栈中,系统会将其移动到新的任
Affinity
在 Android 里,一个 App 默认只能有一个 Task 显示在最近任务列表里。但其实用来甄别这份唯一性的并不是 App,而是一个叫做 taskAffinity 的东西。Affinity 就是相似、有关联的的意思,在 Android 里,每个 Activity 都有一个 taskAffinity,它就相当于是对每个 Activity 预先进行的分组。它的值默认取自它所在的 Application 的 taskAffinity,而 Application 的 taskAffinity 默认是 App 的包名。
onNewIntent
简单理解: onResume 前面多了 onNewIntent()方法
第一种情况:activity launchMode为singleTask或者singleInstance
1、activitya start activityb
2、activityb start activitya
在第二步被执行后,activitya就会顺序执行 onNewIntent onRestart onStart onResume
第二种情况:(一般情况)
大概意思是当Activity被设以singleTop模式启动,当需要再次响应此Activity启动需求时,会复用栈顶的已有Activity,还会调用onNewIntent方法。并且,再接受新发送来的intent(onNewIntent方法)之前,一定会先执行onPause方法
onPause onNewIntent onResume
第二种情况:如果ActivityA在栈顶,且现在要再启动ActivityA,这时会调用onNewIntent()方法 ,生命周期顺序为:onCreate—>onStart—>onResume—onPause>onNewIntent—>onResume
在内存吃紧的情况下,系统可能会 kill 掉后台运行的 Activity ,如果不巧要启动的那个 activity 实例被系统 kill 了,那么系统就会调用 onCreate 方法,而不调用 onNewIntent 方法。这里有个解决方法就是在 onCreate 和 onNewIntent 方法中调用同一个处理数据的方法
问题
一个应用有 4 个 Activity, ABCD, 他们的启动模式分别为 standard, singleTop,singleTask, singlelnstance, 现在 A>B>C>D>A>B>C>D
A 启动 B,B 启动 C, C 启动 D, D 启动 A, A 启动 B,B 启动 C, C 启动 D。现在这个应用 ABCDAcvity 实例各几个????有几个 Acvity 栈?? ?
1)当 CActivity 的 taskAfFinity 和大家一样时启动流程是这样的:
A 启动 B 没有任何波澜,他们都是在一个堆栈,取名栈 1,启动 C,c 寻找 taskAffnity 一样的栈,发现栈 1,而栈 1 中没有 C 实例,所有创建 C 实例。启动 D 时
D 为 singlelnstance,所有会另开一个栈,存放 D。一轮启动过后! 目前栈为2个
栈 1 里面的实例是 ABC
栈 2 里面的实例是 D
D 启动 A=》A 会在栈 1中创建
栈 1 里面的实例是 ABCA 栈 2 里面的实例是 D
A 启动 b=》B 会在栈 1中创建
栈 1 里面的实例是 ABCAB
栈 2 里面的实例是 D
B 启动 C=》由于但是由于栈 1 有 c,所有 singleTask 的特性会将 c 上的实例通通清除
栈 1 里面的实例是 ABC
栈 2 里面的实例是 D
C 启动 D=》D 为 singleInstance, 而现在 D 又有实例,所有不会创建新的,复用原本的 D 实例栈 1 里面的实例是 ABC
栈 2 里面的实例是 D
最终结果是: ABCD 实例各一个,栈 2 个
2)当 CActivity 的 taskAffinity 和大家不一样时启动流程是这样的:
A 启动 B 没有任何波澜,他们都是在一个栈取名栈 1,启动 c 时。由于 C 的 taskAffinity 和 A 不一样,也就是栈 1 不一样,所有会单独创建个栈 2,存放 C。
C 启动 D,D 为 singleInstance 所有会另开一个栈 3,存放 d。一轮启动过后目前栈为3个
栈 1 里面的实例是 AB
栈 2 里面的实例是 C
栈 3 里面的实例是 D
D 启动 A=》A 会在栈 1 中创建栈 1 里面的实例是 ABA 栈 2 里面的实例是 C 栈 3 里面的实例是 D
A 启动 b=》B 会在栈 1 中创建栈 1 里面的实例是 ABAB 栈 2 里面的实例是 C 栈 3 里面的实例是 D
B 启动 C=》C 会去找 taskAffinity 相同的栈,也就是栈 2,栈 2 的 c 在最上面所有复用 C 实例
栈 1 里面的实例是 ABAB
栈2里面的实例是 C
栈 3 里面的实例是 D
C 启动 D=》D 为 singleInstance, 而现在 D 又有实例,所有不会创建新的,复用原本的 D 实例
栈 1 里面的实例是 ABAB
栈 2 里面的实例是 C
栈 3 里面的实例是 D
最终结果是: AB 实例各 2 个,CD 实例各 1 个 栈3个
- Android下的进程进程是被系统创建的,当内存不足的时候,又会被系统回收内存管理
Android 系统在运行多个进程时,如果系统资源不足,会强制结束一些进程,优先选择哪个进程来结束是有优先级的。会按照以下顺序杀死(进程级别):
①、空: 进程中没有任何组件(无组件启动,做进程缓存使用,恢复速度快),任务栈清空,意味着程序退出了,但进程留着,这个就是空进程,容易被系统回收;
②、后台:进程中只有停止状态(onStop)的 Activity;
③、服务:进程中有正在运行的服务;
④、可见:进程中有一个暂停状态(onPause)的 Activity;
⑤、前台:进程中正在运行一个 Activity;Activity 在退出的时候进程不会销毁, 会保留一个空进程方便以后启动. 但在内存不足时进程会被销毁;
不要在 Activity 做耗时的操作, 因为 Activity 切换到后台之后(Activity 停止了), 内存不足时, 也容易被销毁;热启动:退出后在进入应用不会执行application里的代码了。
横竖屏切换生命周期
- 、不设置 Activity 的 Android: configChanges 时,切屏会重新调用生命周期,切横屏会调用一次,切竖屏会调用两次。
2)、设置 Activity 的 Android:configChanges=”orientation”时,切开还是会重新调用生命周期,切横竖屏都只调用次生命周期。
3)、设置 Activity 的 Android: configChanges “orientation keyboardHidden: 切屏不会重新调用冬个生命周期,只会调用 onConfigurationChanged 方法
Service
什么时候使用 Service?
1、Service 的特点可以让他在后台一直运行, 可以在 service 里面创建线程去完成耗时的操作.
2、Broadcast receiver 捕获到一个事件之后, 可以起一个 service 来完成一个耗时的操作.
Service的生命周期。Service有哪些启动方法,有什么区别,怎样停用Service?
在Service的生命周期有onCreate, onStartCommand, onDestroy,onBind和onUnbind。
一旦在项目的任何位置调用了Context的startService()方法,相应的服务就会启动起来,并回调onStartCommand()方法。如果这个服务之前还没有创建过,onCreate()方法会先于onStartCommand()方法执行。
通常有两种方式启动一个Service,他们对Service生命周期的影响是不一样的。
- 通过startService
Service会经历 onCreate 到onStartCommand,然后处于运行状态,stopService的时候调用onDestroy方法。 如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。 - 通过bindService
Service会运行onCreate,然后是调用onBind, 这个时候调用者和Service绑定在一起。调用者退出了,Srevice就会调用onUnbind->onDestroyed方法。所谓绑定在一起就共存亡了。调用者也可以通过调用unbindService方法来停止服务,这时候Srevice就会调用onUnbind->onDestroyed方法。
音乐播放:
增加StartService,来增加后台播放功能 startService(intent);
StartService后,onUnbind不会停服务,会解除绑定
- service如何杀不死
- onStartCommand方法,返回START_STICKY(粘性)当service因内存不足被kill,当内存又有的时候,service又被重新创建
- 设置优先级
- 在服务里的ondestory里发送广播,在广播里再次开启这个服务,双进程守护
service是否在main thread中执行, service里面是否能执行耗时的操作?
Service和Activity是运行在当前app所在进程的main thread(UI主线程)里面service里面不能执行耗时的操作(网络请求,拷贝数据库,大文件 ),需要在子线程中执行 new Thread(){}.start()
service里面可以弹土司吗
由于没有关联的界面,土司会无法显示出来,创建一个Handler,并将其与主线程的Looper关联起来。然后,在需要弹出土司的地方,通过Handler来发送弹出土司的消息
1 |
|
- 什么是IntentService?有何优点?
普通的service ,默认运行在ui main 主线程,Sdk给我们提供的方便的,带有异步处理的service类OnHandleIntent() 处理耗时的操作,不需要开启子线程,这个方法已经在子线程中运行了Intentservice,若未执行完成上一次的任务,将不会新开一个线程,是等待之前的任务完成后,再执行新的任务,等任务完成后再次调用stopService()
startForeground(id, notification)
拥有service的进程具有较高的优先级。当内存不足时,拥有service的进程具有较高的优先级。将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed
广播
请描述一下 Broadcast Receiver。
Android 中:系统在运行过程中,会产生会多事件,那么某些事件产生时,比如:电量改变、收发短信、拨打电话、屏幕解锁、开机,系统会发送广播,只要应用程序接收到这条广播,就知道系统发生了相应的事件,从而执行相应的代码。使用广播接收者,就可以收听广播广播分三种:有序广播、无序广播、本地广播
- 无序广播(标准广播):无序广播不可中断,不能互相传递数据;所有与广播中的 action 匹配的广播接收者都可以收到这条广播,并且是没有先后顺序,视为同时收到
- 有序广播:一个接一个的传递,广播可中断,通过调用 abortBroadcast()方法;接收者之间可以传递数据(intent)所有与广播中的action匹配的广播接收者都可以收到这条广播,但是是有先后顺序的,按照广播接收者的优先级排序优先级的定义
1 |
|
最终接收者:所有广播接收者都接收到广播之后,它才接收,并且一定会接收abortBroadCast:阻止其他接收者接收这条广播,类似拦截,只有有序广播可以被拦截发送有序广播:sendOrderedBroadcast(intent)
本地广播
- 与全局广播相比,LocalBroadcast 更加高效和安全,因为它只在应用内部传递消息,不会被其他应用接收到,也不需要进行权限检查。
- 需要注意的是,在 Android 10 及以上版本中,LocalBroadcast 机制已经被废弃,建议使用其他方式进行应用内部通信,如使用 ViewModel 或 LiveData。
如何注册广播
广播的方式一般有两种,在代码中注册和在 AndroidManifest.xml中注册,其中前者也被称为动态注册,后者也被称为静态注册
动态注册:安卓中有一些广播接收者,必须使用代码注册,清单文件注册是无效的,屏幕锁屏和解锁电量改变
静态注册:可以使用清单文件注册,广播一旦发出,系统就会去所有清单文件中寻找,哪个广播接收者的 action 和广播的 action 是匹配的,如果找到了,就把该广播接收者的进程启动起来
【强制】 避免使用隐式 Intent 广播(静态、动态注册)敏感信息,信息可能被其他注册了对应 BroadcastReceiver 的 App 接收如果广播仅限于应用内,则可以使用 LocalBroadcastManager 的 sendBroadcast ()实现,避免敏感信息外泄和 Intent 拦截的风险。 (效率更高,使用的 handler,静态是 pms)
正例:
1 |
|
LocalBroadcastReceiver 是应用内广播,利用 Handler 实现,利用了 IntentFilter 的 match 功能提供消息的发布与接收功能,实现应用内通信,效率和安全性比较高,仅支持动态注册
4大组件其中比较特殊的是广播接收者,可以不在清单文件中配置,可以通过代码进行注册。其他组件全部在清单文件中注册
广播的生命周期
- 广播接收者的生命周期非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁;
- 广播接收者中不要做一些耗时的工作,否则会弹出 Application No Response错误对话框;
- 最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉;
- 耗时的较长的工作最好放在服务中完成;
广播产生的问题
广播的最大问题就是被滥用,各种全家桶app的相互唤醒,以及保活措施导致设备占用内存增多,性能下降。
google 是如何处理这些问题的
在新版本api中去除了影响较大的全局跨进程广播,比如网络状态变化,新图片或新视频的添加等 。
即使你在app中对这些广播进行了静态注册,依然不会被唤醒 ;如果需要监听网络环境改变,谷歌建议使用JobScheduler(系统服务)来监听;而图片和视频的广播在api24中被完全禁用了。
内容提供者
Android 设计 ContentProvider 主要是为了实现跨进程通信。
调用系统功能,拍照、裁剪、查联系人、短信、系统文件、音乐的时候用到
1 |
|
- 提供一种统一的数据访问格式。调用者无需关心数据源于何处(如DB、XML文件和网络等),只需获取到对应的ContentResolver来进行增删查改即可。
- 四大组件之一,主要用于在不同的应用程序之间实现数据共享的功能,不同于sharepreference和文件存储中的两种全局可读写操作模式,内容提供其可以选择只对哪一部分数据进行共享,从而保证我们程序中的隐私数据不会有泄漏的风险通常,是把私有数据库的数据暴露给其他应用在清单文件中定义内容提供者的标签。
- 注意必须要有authorities属性,这是内容提供者的主机名,功能类似地址 ,可以自己定义。若需提供数据给其他应用,则 exported 要设为true
scheme前缀是固定的: content://
授权host:此例中为 com.xxx.yyy.provide
r路径与参数:此例中为 test_path/1
原理:packmanagerservice里注册,在使用ContentResolver来进行查询操作时,query 方法层层调用到 ActivityThread 的 acquireExistingProvider 方法,根据URI字符串当中的授权host(即 authority )和当前所在用户的 userId 来获取对应的Provider实例。
1 |
|
把自己的数据通过uri的形式共享出去,android 系统下不同程序,数据默认是不能共享访问 需要去实现一个类去继承ContentProvider。
1 |
|
为什么要用ContentProvider?它和sql的实现上有什么差别?
屏蔽数据存储的细节,对用户透明,用户只需要关心操作数据的uri就可以了不同app之间共享,操作数据Sql也有增删改查的方法,但是contentprovider 还可以去增删改查本地文件. xml文件的读取,更改,网络数据读取更改
请介绍下Android的数据存储方式
- 文件储存,在内部文件和SD卡getCacheDir(),在data/data/包名/cachegetFilesDir(),在data/data/包名/filesSD卡:首先通过File file = new File(Environment.getExternalStorageDirectory(), “info.txt”),然后通过io存储
- SharedPreference
- SQLite数据库:当应用程序需要处理的数据量比较大时,为了更加合理地存储、管理、查询数据,往往使用关系数据库来存储数据。
- ContentProvider
通知图库更新
1 |
|
Fragment
- 简单说说Fragment?
用途:在一个Activity里切换界面,切换界面时只切换Fragment里面的内容生命周期方法跟Activity一致,可以理解把其为就是一个Activity,与Activity同存亡,Activity的XX方法调用,Fragment的XX方法就调用
fragment懒加载
懒加载就是页面对用户可见时再去加载数据使用add hide() show()方法切换fragment ,不会走任何的生命周期,无法通过生命周期进行刷新,而是使用onHiddenChanged()
当fragment结合viewpager使用的时候,显示隐藏调用的是setUserVisibleHint()所以需要在这两个方法都判断下,让fragment显示再去加载数据(loadData),当然要先判断是否初始化完成
- 他们是怎么进行传递数据的?
- 活动传递给Fragment:为了方便碎片和活动之间进行通信, FragmentManager提供了一个findFragmentById的方法,专门用于从布局文件中获取碎片的实例,前提是自己在布局文件中定义fragment这个标签,还有findViewByTag,在replace 的时候设置tag或者在fragment里声明接口,然后activity获得fragment对象调用接口里的方法
- fragment数据传递给活动,直接getActivity就可以调用活动里的方法了
- activity给fragment传递数据一般不通过fragment的构造方法来传递,会通过setArguments来传递,因为当横竖屏会调用fragment的空参构造函数,数据丢失。
- fragment和fragment数据传递首先在一个fragment可以得到与它相关联的活动,然后再通过这个活动去获取另外一个fragment的实例,这样也就实现了不同fragment之间的通信功能FragmentManager
- add 和 replace 有什么区别?
用add方式实现fragment的效果就是:切换fragment时不会重新创建,是什么样子切换回来还是什么样子;
用replace的效果就是:切换fragment时每次都会重新创建初始化
- 使用add的情况下,这个FrameLayout其实有2层,多层肯定要比一层的来得浪费,所以还是推荐使用replace。
- 当然有时候还是需要使用add的。比如要实现轮播图的效果,每个轮播图都是一个独立的Fragment,而他的容器FrameLayout需要add多个Fragment,这样他就可以根据提供的逻辑进行轮播了。
- 而至于返回键的时候,这个跟事务有关,跟使用add还是replace没有任何关系。replace()方法会将被替换掉的那个Fragment彻底地移除掉,因此最好的解决方案就是使用hide()和show()方法来隐藏和显示Fragment,这就不会让Fragment的生命周期重走一遍了。
- Fragment和view的区别
- Fragment可以有效的对 view进行管理(增删和替换)而且结构更加清晰,有模块化的实现思想。用view 很多逻辑代码可能都需要写在Activity里,如果view很多, 耦合度会很高。用Fragment则可以各自管理,起了解耦的作用。一般软件简单的话直接view,复杂的用Fragment。
- viewpager是一个滑动切换的控件,Fragment是一个轻量级的Activity,这个Fragment可以放到这个Viewpager里面去运行。例如QQ或微信那样,可以来回切换不同的选项卡,即切换了不同的Fragment。
- 通常Viewpager 会放 fargment或者view。
- 在一个Activity里切换界面,切换界面时只切换Fragment里面的内容。Fragment通常用来作为一个activity界面的一部分。
- fragment有生命周期
- 回退栈
Activity切换是通过栈的形式,不断压栈出栈,在Fragment的时候,如果不是手动开启回退栈,它是直接销毁再重建,但如果将Fragment任务添加到回退栈,情况就会不一样了,它就有了类似Activity的栈管理方式。
popBackStack() 弹出堆栈中的一个并且显示,类似按下返回键的操作;
popBackStack(String tag,int flags)
tag可以为null或者相对应的tag,flags只有0和1(POP_BACK_STACK_INCLUSIVE)两种情况
如果tag为null,flags为0时,弹出回退栈中最上层的那个fragment。
如果tag为null ,flags为1时,弹出回退栈中所有fragment。
如果tag不为null,那就会找到这个tag所对应的fragment,flags为0时,弹出该
fragment以上的Fragment,如果是1,弹出该fragment(包括该fragment)以上的fragment。
1 |
|