Android——Fragment

Android——Fragment,第1张

Fragment必须总是被嵌入到一个activity之中,并且fragment的生命周期直接接受其宿主activity的生命周期的影响。你可以认为fragment是activity的一个模块零件,它有自己的生命周期,接收它自己的输入的事件,并且可以在activity运行时添加或者删除。

应该将每一个fragment设计为模块化和可复用化的activity组件。也就是说,你可以在多个activity中引用同一个fragment,因为fragment定义了它自己的布局,并且使用它本身生命周期回调的行为。

Fragment比Activity多了几个额外的生命周期回调方法:

管理fragment生命周期与管理activity生命周期很相像,像activity一样,fragment也有三种状态:

1、Resumed:

fragment在运行中的activity中可见。

2、Paused:

另一个activity处于前台且得到焦点,但是这个fragment所在的activtiy仍然可见(前台activity部分透明,或者没有覆盖全屏)。

3、Stopped:

fragment不可见。要么宿主activity已经停止,要么fragment已经从activity上移除,但已被添加到后台栈中。一个停止的fragment仍然活着(所有的状态和成员信息仍然由系统保留着)。但是,它对于用户来讲已经不再可见,并且如果activity被杀掉,它也将被杀掉。

如果activity的进程被杀掉了,在activity被重新创建时,你恢复fragment状态。可以执行fragment的onSaveIntanceState()来保存状态(注意:fragment是在onCreate(),onCreateView()或者onActivityCreate()中进行恢复)。

在生命周期方面,activity和fragment之间一个很重要的不同就是在各自的后台栈中是如何存储的。当activity停止时,默认情况下activity被安置在由系统管理的activity后台栈中;fragment仅当在一个事务被移除时,通过显式调用addToBackStack()请求保存的实例,该fragment才被置于由宿主activity管理的后台栈。

类似与Android系统为Activity维护一个任务栈,我们也可以通过Activity维护一个回退栈来保存每次Fragment事务发生的变化。

如果你将Fragment任务添加到回退栈,当用户点击后退按钮时,将看到上一次的保存的Fragment。一旦Fragment完全从后退栈中d出,用户再次点击后退键,则退出当前Activity。

通过Arguments创建Fragment,不建议通过为Fragment添加带参数的构造函数

1、FragmentPagerAdapter:对于不再需要的fragment,选择调用detach方法,仅销毁视图,并不会销毁fragment实例。

2、FragmentStatePagerAdapter:会销毁不再需要的fragment,当当前事务提交以后,会彻底的将fragment从当前Activity的FragmentManager中移除。

3、懒加载,核心方法是 setUserVisibleHint()

原因1:横竖屏切换,造成Fragment重新实例化。

原因2:按下Home键,Activity处于后台,由于内存不足被销毁,重新唤醒时Fragment重新实例化。

注:出现的原因是在 API24 之前的 v4包 的源码问题,

解决方案:通过检查onCreate的参数Bundle savedInstanceState就可以判断,当前是否发生Activity的重新创建:

默认的savedInstanceState会存储一些数据,只有在savedInstanceState==null时,才进行创建Fragment实例:

android 怎么获取一个activity启动模式

在Android中每个界面都是一个Activity,切换界面 *** 作其实是多个不同Activity之间的实例化 *** 作。在Android中Activity的启动模式决定了Activity的启动运行方式。

Android总Activity的启动模式分为四种:

Activity启动模式设置:

<activity android:name="MainActivity" android:launchMode="standard" />

Activity的四种启动模式:

1 standard

模式启动模式,每次激活Activity时都会创建Activity,并放入任务栈中。

2 singleTop

如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。

3 singleTask

如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈中。

4 singleInstance

在一个新栈中创建该Activity实例,并让多个应用共享改栈中的该Activity实例。一旦改模式的Activity的实例存在于某个栈中,任何应用再激活改Activity时都会重用该栈中的实例,其效果相当于多个应用程序共享一个应用,不管谁激活该Activity都会进入同一个应用中。

其中standard是系统默认的启动模式。

下面通过实例来演示standard的运行机制:

1 private TextView text_show;

2 private Button btn_mode;

3

4 @Override

5 public void onCreate(Bundle savedInstanceState) {

6 superonCreate(savedInstanceState);

7 setContentView(Rlayoutactivity_main);

8

9 text_show = (TextView) thisfindViewById(Ridtext_show);

10

11 text_showsetText(thistoString());

12

13 btn_mode = (Button) thisfindViewById(Ridbtn_mode);

14

15 }

16

按钮单击事件

17 public void LaunchStandard(View v){

18 startActivity(new Intent(this,MainActivityclass));

19

20 text_showsetText(thistoString());

21 }

如何设置Activity的启动模式

Activity的四种启动模式:standard:这是默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中。 singleTop: 如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的 onNewIntent() ),否则就会创建新的实例并放

android 主activity用什么启动模式

在android里,有4种activity的启动模式,分别为:

“standard” (默认)

“singleTop”

“singleTask”

“singleInstance”

1 如何决定所属task

“standard”和”singleTop”的activity的目标task,和收到的Intent的发送者在同一个task内,除非intent包括参数FLAG_ACTIVITY_NEW_TASK。

如果提供了FLAG_ACTIVITY_NEW_TASK参数,会启动到别的task里。

2 是否允许多个实例

“standard”和”singleTop”可以被实例化多次,并且存在于不同的task中,且一个task可以包括一个activity的多个实例;

“singleTask”和”singleInstance”则限制只生成一个实例,并且是task的根元素。

singleTop要求如果创建intent的时候栈顶已经有要创建 的Activity的实例,则将intent发送给该实例,而不发送给新的实例。

3 是否允许其它activity存在于本task内

“singleInstance”独占一个task,其它activity不能存在那个task里;如果它启动了一个新的activity,不管新的activity的launch mode 如何,新的activity都将会到别的task里运行(如同加了FLAG_ACTIVITY_NEW_TASK参数)。

而另外三种模式,则可以和其它activity共存。

4 是否每次都生成新实例

“standard”对于没一个启动Intent都会生成一个activity的新实例;

“singleTop”的activity如果在task的栈顶的话,则不生成新的该activity的实例,直接使用栈顶的实例,否则,生成该activity的实例。

比如现在task栈元素为A-B-C-D(D在栈顶),这时候给D发一个启动intent,如果D是 “standard”的,则生成D的一个新实例,栈变为A-B-C-D-D。

如果D是singleTop的话,则不会生产D的新实例,栈状态仍为A-B-C-D

如果这时候给B发Intent的话,不管B的launchmode是”standard” 还是 “singleTop” ,都会生成B的新实例,栈状态变为A-B-C-D-B。

“singleInstance”是其所在栈的唯一activity,它会每次都被重用。

“singleTask”如果在栈顶,则接受intent,否则,该intent会被丢弃,但是该task仍会回到前台。

当已经存在的activity实例处理新的intent时候,会调用onNewIntent()方法

如果收到intent生成一个activity实例,那么用户可以通过back键回到上一个状态;如果是已经存在的一个activity来处理这个intent的话,用户不能通过按back键返回到这之前的状态。

总结如下:

standard 每次都会新建,每个Task都可以有,且每个Task都可以有多个实例(每个Task都可以有,且可以有多个)

singleTop 当前实例如果在栈顶,就不新建实例,调用其OnNewIntent。 如不在栈顶,则新建实例 (每个Task都可以有,且可以有多个,在栈顶时可复用)

singleTask 新建一个Task,如果已经有其他的Task并且包含该实例,那就直接调用那个Task的实例。(只有一个Task中会有)

singleInstance 新建一个Task,且在该Task中只有它的唯一一个实例。 (只有一个Task会有,且该Task中只有它)

FLAG_ACTIVITY_NEW_TASK 类似singleTask

FLAG_ACTIVITY_SINGLE_TOP 类似singleTop

FLAG_ACTIVITY_CLEAR_TOP 无对应

Android开发,activity的默认启动模式为标准启动模式,什么时候会用到其他的启动模式?

启动模式简单地说就是Activity启动时的策略,在AndroidManifestxml中的标签的android:launchMode属性设置;

启动模式有4种,分别为standard、singleTop、singleTask、singleInstance;

讲解启动模式之前,有必要先了解一下“任务栈”的概念;

一 :

standard 模式:这个就没有什么好说的了,Android默认Activity启动的模式 就是 standard,如果有3个 Activity,Act1,Act2,Act3, 如果从Act1 启动到Act2 ,在启动到Act3,那么Android 的任务栈(task stack)分别为 Act1、Act2、Act3,Act3 在栈顶,如果此时按手机返回键,则需要返回3次才能返回到桌面(假设是从桌面启动的demo),任务栈分销毁掉 Act3,Act2,最后Act1 。

二 :singleTop模式:

实验效果:

singleTop模式:该启动模式和standard模式相差不多,任务栈分配也很相似,如:现有 act1,act 2,在act2 清单文件中配置 android:launchMode="singleTop" ,其他都是默认standard 模式, 若从桌面启动该实验demo,从act 1,到act2 ,那么任务栈则分配为,act1,act2,此时该任务栈和 standard 模式任务栈分配则完全相同,接下来则说明不同的地方,如果在act2 界面中 启动 到act1, 此时的 任务栈 情况则为 act1,act2,act1,在由act1 启动到act2,在启动到act2,进行多次启动,(在act2界面)任务栈的情况则为,act1,act2,act1,act2,栈顶的act2 则不会重新创建,则会复用act2 该 Activit, 依次类推。

理论知识:

singleTop,如果任务栈的栈顶元素是要被激活的组件,不会创建新的Activity放在任务栈,而是会复用栈顶的Activity。 如果发现栈顶的元素不是要激活的Activity,就会创建新的Activity 放置到任务栈里面

singleTop模式应用场景 :

App程序中(或浏览器中)保存的书签,假如用户看到一个界面保存自己喜欢的标签,假如要保存10个,这个时候用户在返回键的时候,则会返回10次才能返回到App应用中, Android下singleTop 则解决该问题。

三 singleTask 模式 :

实验效果 相差不大,实验内容就不多说了,自己可以写个小demo,两个Activity,每个Activiy 有两个button,可以相互启动 打日志去动手查看,会理解更加深刻,可以参照着 SingleTop模式去实验,以下只是讲解下 和SingleTop的区别:

区别如下:(理论知识)

SingleTask *** 作模式,一般和singleTop *** 作模式类似,如果他发现任务栈里面已经有了要启动的这个Activity,他会清空这个Activity所在的任务栈上面的所有Activiy,然后直接复用这个已经存在的Activity 。

应用场景:

如果一个App中,有一个功能需要加载网页内容 ,打开一个 browserActiviy现在网页内容,则内存开销非常大,首先要初始化webkit /c++ 嵌入式浏览器内核broweractivity 配置了singleTask,空间换时间,使用该模式可以节省内存开销。

四 :singleinstance 模式 :

直接理论知识吧”:

singleInstance *** 作模式会新开启一个任务栈,跟其他普通Activity不是 同一个任务栈,比较牛,他的模式流程是 首先要新开启一个新的任务栈把要激活的Activity放置到新的 任务栈里,这个任务栈里面只有且 只有一个实例,也比较极端吧。说比较极端也跟他的应用场景有关系。

应用场景 :

App各种词典,向有道词典,什么金山词典,说极端是因为不想被放置到同一个任务栈里面,它是全局的系统程序应用,达到节省内存的使用目的。

win7 系统 怎么设置uefi启动模式

存有ghost版win7系统iso镜像文件的u启动uefi u盘启动盘插在电脑u 接口上,然后重启电脑,在出现开机画面时用一键u盘启动快捷键的方法进入到启动项选择窗口,然后将光标移至UEFI:开头的项(注意:一定要选择该项),按回车键执行等待进入到u启动win pe系统,u启动装机工具会自动开启,并加载到u启动uefi u盘启动盘中准备的win7系统安装程序,点击选择c盘为系统安装盘,再点击“确定”按钮继续

随即会d出一个询问是否执行该 *** 作的提示窗口,点击“确定”按钮执行 *** 作

然后耐心等待win7系统释放完成并自动重启电脑即可

电脑重启后会完成系统后续程序安装应用,直到进入win7系统桌面即可

android开发 activity启动模式中singleTop的疑问

楼主的这一段理论似乎有点不太准确 “在D完成 *** 作以后,我启动了系统内置的浏览器E,根据sdk的说法,浏览器E被放进了一个新任务。那么现在有两个任务” 你凭什么确定浏览器E被放进了一个新的Task呢? 在启动浏览器E的Intent里设置了flag? intentandroid开发 activity启动模式中singleTop的疑问

android-Android activity 的启动模式新人提问,大侠在哪

Activity的四种启动模式:standard:这是默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中。

singleTop: 如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的 onNewIntent() ),否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例,只要不在栈顶,都会创建新的实例。

singleTask:如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的 onNewIntent() )。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移出栈。如果栈中不存在该实例,将会创建新的实例放入栈中。

singleInstance:在一个新栈中创建该Activity的实例,并让多个应用共享该栈中的该Activity实例。一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例( 会调用实例的 onNewIntent() )。其效果相当于多个应用共享一个应用,不管谁激活该 Activity 都会进入同一个应用中。

位置在 AndroidManifestxml 文件中 Activity 元素的 android:launchMode 属性。

不知道你要问什么,为你解答

activity的启动模式有哪些

Activity的四种启动模式:standard:这是默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中。

singleTop: 如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的 onNewIntent() ),否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例,只要不在栈顶,都会创建新的实例。

singleTask:如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的 onNewIntent() )。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移出栈。如果栈中不存在该实例,将会创建新的实例放入栈中。

singleInstance:在一个新栈中创建该Activity的实例,并让多个应用共享该栈中的该Activity实例。一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例( 会调用实例的 onNewIntent() )。其效果相当于多个应用共享一个应用,不管谁激活该 Activity 都会进入同一个应用中。

位置在 AndroidManifestxml 文件中 Activity 元素的 android:launchMode 属性。

GUI,界面,与用户交互的可视接口。

当然Fragment,View也是,不过我把它看作是控件,Activity是开发中最基本的容器(窗口)。

目的是便于管理Activity生命周期。

新启动的Activity会压入栈顶,而处于栈顶的Activty处于Active活跃状态,即可以和用户做交互(可见可交互)。压在下面的Activity则处于可见不可交互,或不可见不可交互状态,并且系统可能会因为内存不足原因优先回收掉任务栈最下面的Activity,所以也有被回收状态。

1资源相关的系统配置发生改变导致Activty被杀死并重新创建

2资源内存不足导致低优先级的Activity被杀死

扩展:进程优先级

当Activity异常被回收的情况下,系统会调用onSaveIntanceState(Bundle),重新启动时会调用onRestoreInstanceState(Bundle),所以可以在Bundle做一些数据保存和恢复的工作。

数据恢复:onCreate()与onRestoreInstanceState()区别:

onCreate()需要判空,onRestoreInstanceState不需要。

启动模式简单来说就是定义Activity实例与Activity任务栈的关联方式。

目的:

设置方式:

有哪些启动模式?

TaskAffinity(任务相关性),这个参数标识了一个Activity所需要的任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用的名字。所有我们可以通过设置TaskAffinity为每个Activity单独指定任务栈。

启动Activity就两种,显示调用和隐式调用。

即在Intent中,显示传入要跳转的组件类名。这种方式比较简单直接,但也造成了关联耦合。

这样调用方式的好处是我不必知道我的目标组件具体的名字,只要有组件满足我设置的过滤条件即可找到我想要的组件。这种方式广泛应用在模块化开发,解决了模块之间的跳转问题。

隐式调用需要Intent能够匹配目标组件的IntentFilter中设置的过滤信息,如果不匹配将无法启动目标组件。IntentFilter中的过滤信息包括action、category、data

清单文件中,如果data仅指定了mimeType,没有指定URI,则data中URI的scheme的默认值为file和content,所以Intent中URI的scheme也必须为file或content才能匹配到。

类似URI的结构,就是匹配URI的。

URI结果: <scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]

使用PackageManager的两种方法判空。

第二个flag参数使用MATCH_DEFAULT_ONLY时,表示仅仅匹配那些在intent-filter中声明了androidintentcategoryDEFAULT这个category的组件。

1、查看最上层成activity名字:

adb shell dumpsys activity | findstr "mFocusedActivity"

或者 adb shell dumpsys window w | findstr / | findstr name=

2、查看Activity的任务栈:

3、显示所有的activities的信息,包括任务栈等:

adb shell dumpsys activity

4、查看Android应用包名package和入口activity名称 :

aapt dump badging E:\apk\es3apk

5、显示accounts信息:

adb shell dumpsys account

5、显示CPU信息 :

adb shell dumpsys cpuinfo

查看CPU使用信息

adb shell top -n 1 -d 05 | findstr proc_ id

6、显示键盘,窗口和它们的关系

adb shell dumpsys window

当我们需要知道设备的分辨率时

adb shell dumpsys window displays

查看UI绘制的各个层级信息

adb shell dumpsys SurfaceFlinger

7、显示wifi信息

adb shell dumpsys wifi

8、电量信息及CPU 使用时长

adb shell dumpsys batteryinfo $package_name

9、获取安装包信息

adb shell dumpsys package packagename

10、每个应用的启动次数和时间

adb shell dumpsys usagestats

11、显示状态栏相关的信息

adb shell dumpsys statusbar

12、内存信息(meminfo package_name or pid 使用程序的包名或者进程id显示内存信息)

adb shell dumpsys meminfo

得到comtelecarobintest进程使用的内存的信息 adb shell dumpsys meminfo comtelecarobintest

13、磁盘相关信息

adb shell dumpsys diskstats

14、电池相关信息

adb shell dumpsys battery

15、显示Alarm信息

adb shell dumpsys alarm

统计系统耗电量

adb shell dumpsys batterystats

设置线程的优先级

adb shell dumpsys activity|grep oom_adj

16、强制关闭一个应用程序;

adb shell am force-stop <PACKAGE>

17、查看内存信息

adb shell cat proc/meminfo

指定进程内存地址映射

adb shell cat proc/pid/maps

指定进程内存详细使用信息

adb shell cat proc/pid/smaps

VSS RSS PSS USS 信息

adb shell procrank

指定进程VSS RSS PSS USS 详细信息

adb shell procmem pid

18、查看可输入的设备

adb shell getevent -p

19、获得特定设备的输入信息

adb shell getevent /dev/input/event0

20、点击

adb shell input tap x y

21、发送按键

adb shell input keyevent 82(keycode)

22、输入文本

adb shell input text XXXX

23、查看报名中包含mobileqq的进程

adb shell ps | findstr mobileqq

24、远程进程ID

adb jdwp

25、获取序列号

adb get-serialno

26、重启到bootloader,即刷机模式

adb reboot bootloader

27、重启到recovery,即恢复模式

adb reboot recovery

28、获取机器MAC地址:

adb shell cat /sys/class/net/wlan0/address

29、获取CPU序列号

adb shell cat /proc/cpuinfo

30、覆盖安装(保留数据和缓存文件,重新安装apk)

adb install -r <apkfile>

31、安装apk到sd卡

adb install -s <apkfile>

32、卸载app但保留数据和缓存文件

adb uninstall -k <package>

33、查看设备cpu和内存占用情况

adb shell top

34、查看占用内存前6的app

adb shell top -m 6

35、刷新一次内存信息,然后返回

adb shell top -n 1

36、查询各进程内存使用情况

adb shell procrank

37、查看指定进程状态

adb shell ps -x [PID]

38、查看后台services信息

adb shell service list

39、查看当前内存占用(该方式只能得出系统整个内存的大概使用情况) 车

如果你想查看所有进程的内存使用情况

adb shell procrank

40、查看IO内存分区

adb shell cat /proc/iomem

41、查看wifi密码

adb shell cat /data/misc/wifi/conf

42、清除log缓存

adb logcat -c

43、查看设备信息

adb shell cat /system/buildprop

44、跑monkey

adb shell monkey -v -p yourpackagename 500

45、列出目标设备上安装的所有app的包名

adb shell pm list packages

46、截屏命令:

adb shell screencap -p /sdcard/screenpng

adb pull /sdcard/screenpng

adb shell rm /sdcard/screenpng

录制手机屏幕,视频格式为mp4,存放到手机sd卡里,默认录制时间为180s:

adb shell screenrecord

限制视频录制时间为10s,如果不限制,默认180s:

adb shell screenrecord --time-limit 10 /sdcard/demomp4

指定视频分辨率大小:

adb shell screenrecord --size 1280720 /sdcard/demomp4

指定视频的比特率:

adb shell screenrecord --bit-rate 6000000 /sdcard/demomp4

在命令行显示log:

adb shell screenrecord --time-limit 10 --verbose /sdcard/demomp4

47、设置、获取属性信息

adb shell getprop [key]

adb shell setprop [key] [value]

监听系统属性的变化,如果期间系统的属性发生变化则把变化的值显示出来

adb shell watchprops

48、adb logcat 每一条日志消息都有一个标记和优先级与其关联。

(1)标记是一个简短的字符串,用于标识原始消息的来源 (例如"View" 来源于显示系统)。优先级是下面的字符,顺序是从低到高:

V — 明细 (最低优先级)

D — 调试

I — 信息

W — 警告

E — 错误

F — 严重错误

S — 无记载 (最高优先级,没有什么会被记载)

(2)查看过滤日志

adb logcat ActivityManager:I :S

:S 用于设置所有标记的日志优先级为S,可以确保输出符合指定的过滤器设置的一种推荐的方式,

这样过滤器就成为了日志输出的“白名单”

显示所有优先级大于等于“warning”的日志

adb logcat :W

(3)日志消息在标记和优先级之外还有很多元数据字段,这些字段可以通过修改输出格式来控制输出结果, -v 选项加上下面列出的内容可以控制输出字段:

brief — 显示优先级/标记和原始进程的PID (默认格式)

process — 仅显示进程PID

tag — 仅显示优先级/标记

thread — 仅显示进程:线程和优先级/标记

raw — 显示原始的日志信息,没有其他的元数据字段

time — 显示日期,调用时间,优先级/标记,PID

long —显示所有的元数据字段并且用空行分隔消息内容

使用 thread 输出格式

adb logcat -v thread

(4)Android日志系统为日志消息保持了多个循环缓冲区,而且不是所有的消息都被发送到默认缓冲区,要想查看这些附加的缓冲区,可以使用-b 选项,以下是可以指定的缓冲区:

radio — 查看包含在无线/电话相关的缓冲区消息

events — 查看事件相关的消息

main — 查看主缓冲区 (默认缓冲区)

查看radio缓冲区

adb logcat -b radio

48、打印应用程序的log

adb logcat -b main -v time>applog

49、打印射频相关的log,SIM STK也会在里面,modem相关的ATcommand等,当然跟QXDM差的很远了

adb logcat -b radio -v time> radiolog

50、打印系统事件的日志,比如触屏事件

adb logcat -b events -v time

51、tcpdump 是很有用的,对于TCP/IP协议相关的都可以使用这个来抓

adb shell tcpdump -s 10000 -w /sdcard/capturepcap

52、状态信息,里面包含有dmesg,dumpstate和dumpsys

adb bugreport>bugreportlog

53、kernel的log凡是跟kernel相关的,比如driver出了问题(相机,蓝牙,usb,启动,等等吧)

adb shell dmesg > ldmesg_kernellog

54、dumpstate是系统状态信息,里面比较全,包括手机当前的内存信息、cpu信息、logcat缓存,kernel缓存等等 。

adb shell dumpstate

55、关于系统service的内容都在这个里面

adb shell dumpsys

56、显示内存信息

adb shell dumpsys meminfo system

我们在 App 中,通常会打开很多个任务栈,如果我们要退出 App,要点击返回键一步步的退出?有没有更简单的方法吗?答案是有的,我们创建一个 Activity 管理器,来统一管理 Activity。

新建一个 ActivityCollectior 类自作为活动管理器:

public class ActivityCollector {

/

创建一个集合保存

/

public static List<Activity> activities = new ArrayList<>();

}

创建一个基类,BaseActivity,让所有的 Activity 继承它。

public class BaseActivity extends AppCompatActivity {

}

随便一个 Activity 就可以退出 App,通过调用:

ActivityCollectorfinishAll();

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

superonCreate(savedInstanceState);

setContentView(Rlayoutactivity_second2);

ButterKnifebind(this);

init();

}

}

launch()这样写的好处:

1别的 Activity 可以一句话调用。

2可以清晰的看到传递过来的参数,直接接受即可(重点)。

LiveData是一种具有生命周期感知能力的可观察数据持有类。

LiveData可以保证屏幕上的显示内容和数据一直保持同步。

在项目中,LiveData一般是存放在ViewModel中,以保证app配置变更时,数据不会丢失。

使用流程其实很简单,就是自定义实现一个Observer观察者,然后在Activity或者Fragment中获取到ViewModel,通过ViewModel获取到对应的LiveData,然后给LiveData添加观察者监听,用来监听LiveData中的数据变化,在Observer的onChanged中使用监听回调数据。

在使用LiveData的时候需要注意,LiveData有两个设置数据的方法,一个是setValue,一个是postValue,setValue只能是在主线程使用,而postValue只能在子线程中使用。

LiveData添加观察者监听,可以看到LiveData的observe方法,使用了@MainThread注释,表明该观察者监听添加的方法,只能是在主线程中使用,如果不是在主线程中使用,则会抛出异常。

在LiveData添加观察者的时候,因为LifecycleBoundObserver实际上也是实现了LifecycleEventObserver接口的,所以在LifecyclinglifecycleEventObserver对观察者对象做封装的时候,也是直接返回传入的观察者对象,不做任何的处理

LifecycleBoundObserver中封装了LifecycleOwner对象和Observer对象,并且实现了LifecycleEventObserver接口,根据Lifecycle的原理,其实我们可以知道,LifecycleRegistryaddObserver方法,添加的就是LifecycleEventObserver实现了对象。

所以在Activity使用LiveData,添加观察者,其实其内部最终还是给Activity的LifecycleRegistry添加观察者,然后根据Activity的生命周期的变化对LiveData进行通知。

postValue的通知更新,其实就是调动任务栈分发任务,而被分发执行的任务实现如下:

从这里可以看到,其实postValue在分发的任务中,其内部实现的依然是setValue()方法,只不过是从子线程切换到了主线程进行执行。做了一次线程的切换。

在postValue方法中,其内部调用的是ArchTaskExecutor的postToMainThread方法。

在这里可以看到mDelegate其实就是DefaultTaskExecutor对象

所以mDelegatepostToMainThread(runnable)其实就是调用了DefaultTaskExecutorpostToMainThread方法。

在这里可以看到,mMainHandler其实就是通过主线程的Looper实例创建的Handler对象,所以这里Handler发送消息执行任务,就是在主线程中执行该任务。

LiveData在分发消息的时候,会调用dispatchingValue方法循环分发,当消息分发完成之后,其实并不会退出do-while循环,还会在调用considerNotify方法的内部调用observeractiveStateChanged(false);继续执行第二次dispatchingValue方法,也就是说递归执行,在第二次执行的时候,mDispatchingValue = true,就会执行将mDispatchInvalidated = true,那么就会完成dispatchingValue方法的第二次执行,被直接return,那么considerNotify()方法的执行也就完成,此时就会执行considerNotify之后的if条件,因为在dispatchingValue第二次执行的时候将mDispatchInvalidated设置为了true,就直接break跳出了循环,结束了消息的分发。

但是这样的情况,一般是在存在观察者处于ON_STOP或者已经是ON_DESTROY状态的时候。

如果观察者都是处于onResume,那么这个时候会因为mDispatchInvalidated=false而退出了循环,结束分发。

但是如果是先setValue,然后再设置Observer的话。

因为此时设置Observer的时候,当生命周期发生变化的时候,又会调用回调onStateChanged方法,进而调用activeStateChanged方法

因为在添加Observer之前,已经针对该LiveData设置了一个value,此时添加了观察者,那么又因为生命周期发生了变化,那么该观察者在调用dispatchingValue(this);传入的就不是null,则在do-while循环的if判断中,就会执行if条件,进而调用considerNotify()方法给传入的ObserverWrapper实现类分发消息,那么就会把之前设置的消息分发给了该观察者。

这样的情况就是LiveData的粘性事件。即后注册的观察者接收到了之前LiveData设置的value消息。

那么问题又一次来了,什么时候会触发调用LifecycleBoundObserver的onStateChanged方法呢?

通过LiveData的observe方法进行分析,我们可以知道给LiveData添加观察者的时候,其实就是通过给实现了LifecycleOwner接口的Activity的getLifecycle()方法获取到的LifecycleRegistry对象添加观察者,而LifecycleRegistry中的addObserver方法,就会先满足while条件,然后执行了ObserverWithStatedispatchEvent方法,此时就会调用到了LifecycleBoundObserveronStateChanged方法

这里为什么会满足while条件呢?calculateTargetState会获取当前Activity生命周期状态的前一个和后一个状态,然后取更小的那个状态,在addObserver的时候,calculateTargetState这里如果activity是onStart的状态,那么calculateTargetState取出的就是CREATED状态,如果activity是onResume的状态,那么这里取出的就是STARTED,不管怎么样都会大于INITIALIZED状态,那么就会满足while条件,此时第二个activity是在onCreate生命周期调用observe方法注册Observer

其实这里个人感觉,应该是在addObserver之后,因为第二个Activity(也就是添加addObserver的)发生了生命周期变化,从onCreate变成了onStart,从onStart变成onResume,此时就会调用moveToState,然后就会调用forwardPass(),然后就会分发消息,因为之前已经postValue或者setValue了,那么在这个LiveData里的mData就不会为null,有消息了,就可以优先分发一次。

满足while条件后,就会调用statefulObserverdispatchEvent(lifecycleOwner, upEvent(statefulObservermState));,这里最终就会调用LifecycleBoundObserver的

这里shouldBeActive(),在Activity的最后的生命周期是onResume的时候,就会满足true,那么此时activeStateChanged()传入的参数就是true,而初始的时候,mActive为false

此时mActive就会重新赋值为true,那么就会调用dispatchingValue()方法,此时dispatchingValue()的参数传入this,那么就不会为false。

一般常用的粘性事件解决方案,其实就是hook修改mLastVersion的值,让这个值变成与mVersion的值一致,但是如果是在onResume或者onStart的生命周期去添加注册观察者,那么常见的粘性事件解决方案中,因为会调用superobserve(),那么就会因为在LifecycleRegistryaddObserver方法中,满足while条件,从而又会进行LifecycleBoundObserver的onStateChanged方法的回调,这样又会出现粘性事件。这样的情况的解决方案,其实可以hook修改mVersion的值,在注册观察者之前,改成-1

在Android中每个界面都是一个Activity,切换界面 *** 作其实是多个不同Activity之间的实例化 *** 作。在Android中Activity的启动模式决定了Activity的启动运行方式。 Android总Activity的启动模式分为四种: Activity启动模式设置: <activity android:name="MainActivity" android:launchMode="standard" /> Activity的四种启动模式: 1 standard 模式启动模式,每次激活Activity时都会创建Activity,并放入任务栈中。 2 singleTop 如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。 3 singleTask 如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈中。 4 singleInstance 在一个新栈中创建该Activity实例,并让多个应用共享改栈中的该Activity实例。一旦改模式的Activity的实例存在于某个栈中,任何应用再激活改Activity时都会重用该栈中的实例,其效果相当于多个应用程序共享一个应用,不管谁激活该Activity都会进入同一个应用中。 其中standard是系统默认的启动模式。 下面通过实例来演示standard的运行机制: 1 private TextView text_show; 2 private Button btn_mode; 3 4 @Override 5 public void onCreate(Bundle savedInstanceState) { 6 superonCreate(savedInstanceState); 7 setContentView(Rlayoutactivity_main); 8 9 text_show = (TextView) thisfindViewById(Ridtext_show); 10 11 text_showsetText(thistoString()); 12 13 btn_mode = (Button) thisfindViewById(Ridbtn_mode); 14 15 } 16 //按钮单击事件 17 public void LaunchStandard(View v){ 18 startActivity(new Intent(this,MainActivityclass)); 19 20 text_showsetText(thistoString()); 21 }

以上就是关于Android——Fragment全部的内容,包括:Android——Fragment、android 怎么设置activity的启动模式、Android总结之Activity等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9437021.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-28
下一篇2023-04-28

发表评论

登录后才能评论

评论列表(0条)

    保存