zoukankan      html  css  js  c++  java
  • Android

    2.1 Activity
    1.Activity是什么?
    Activity是Android的四大组件之一。是用户操作的可视化界面;它为用户提供了一个完成操作指令的窗口。
    当我们创建完毕Activity之后,需要调用setContentView()方法来完成界面的显示;以此来为用户提供交互的入口。


    2.典型情况下的Activity生命周期?
    Activity启动–>onCreate()–>onStart()–>onResume()
    点击home键回到桌面–>onPause()–>onStop()
    再次回到原Activity时–>onRestart()–>onStart()–>onResume()
    退出当前Activity时–>onPause()–>onStop()–>onDestroy()


    3.异常情况下的Activity的生命周期 & 数据如何保存和恢复?
    在onStop之前调用onSaveInstanceState保存当前Activity状态,当Activity被重新创建后,系统调用
    onRestoreInstanceState,并且把Activity销毁时onSaveInstanceState方法所保存的Bundle对象
    作为参数传递给onRestoreInstanceState和onCreate方法
    onRestoreInstanceState的调用时机发生在onStart之后


    4.从Activity A跳转到Activity B之后,然后再点击back键之后,它们的生命周期调用流程是什么?
    从Activity A跳转到Activity B
    Activity A -> onPause()
    Activity B -> onCreate()
    Activity B -> onStart()
    Activity B -> onResume()
    Activity A -> onStop()

    点击back键
    Activity B -> onPause()
    Activity A -> onRestart()
    Activity A -> onStart()
    Activity A -> onResume()
    Activity B -> onStop()
    Activity B -> onDestroy()


    5.如何统计Activity的工作时间?
    Activity开始工作的起点是onResume()而工作的停止点为onPause(),
    因此当每次Activity调用onResume()的时候记录一个时间a,每次调用onPause()的时候再记录一个时间b,
    那么由b-a可得当次Activity工作的时间。


    6.给我说说Activity的启动模式 & 使用场景。
    系统默认的启动模式:standard
    系统的默认模式,每次启动一个Activity都会重新创建一个新的实例
    栈顶复用模式:singleTop
    如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的 onNewIntent() ),
    否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例,只要不在栈顶,都会创建新的实例。
    使用场景如新闻类或者阅读类App的内容页面。
    栈内复用模式:singleTask
    如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的 onNewIntent() )。
    重用时,会让该实例回到栈顶,因此在它上面的实例将会被移出栈。如果栈中不存在该实例,将会创建新的实例放入栈中。
    使用场景如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,
    并且会清空主界面上面的其他页面。
    单实例模式:singleInstance
    在一个新栈中创建该Activity的实例,并让多个应用共享该栈中的该Activity实例。
    一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例
    ( 会调用实例的 onNewIntent() )。其效果相当于多个应用共享一个应用,不管谁激活该 Activity 都会进入同一个应用中。
    使用场景如闹铃提醒,将闹铃提醒与闹铃设置分离。singleInstance不要用于中间页面,如果用于中间页面,跳转会有问题,
    比如:A -> B (singleInstance) -> C,完全退出后,在此启动,首先打开的是B。


    7.如何在任意位置关掉应用所有Activity & 如何在任意位置关掉指定的Activity?
    封装一个类,成员变量有一个List集合,当Activity执行onCreate()方法时将当前的Activity实例加入,
    遍历这个List且逐一调用finish()即可
    给每个启动的Activity一个tag,根据这个tag和集合可达到在任意位置关闭指定Activity的效果。


    8.Activity的启动流程(从源码角度解析)?
    app启动的过程有两种情况,第一种是从桌面launcher上点击相应的应用图标,
    第二种是在activity中通过调用startActivity来启动一个新的activity。
    我们创建一个新的项目,默认的根activity都是MainActivity,而所有的activity都是保存在堆栈中的,
    我们启动一个新的activity就会放在上一个activity上面,而我们从桌面点击应用图标的时候,由于launcher本身也是一个应用,
    当我们点击图标的时候,系统就会调用startActivitySately(),一般情况下,我们所启动的activity的相关信息都会保存在intent中,
    比如action,category等等。我们在安装这个应用的时候,系统也会启动一个PackaManagerService的管理服务,
    这个管理服务会对AndroidManifest.xml文件进行解析,从而得到应用程序中的相关信息,比如service,activity,Broadcast等等,然后获得相关组件的信息。
    当我们点击应用图标的时候,就会调用startActivitySately()方法,而这个方法内部则是调用startActivty(),
    而startActivity()方法最终还是会调用startActivityForResult()这个方法。
    因为startActivityForResult()方法是有返回结果的,所以系统就直接给一个-1,就表示不需要结果返回了。
    而startActivityForResult()这个方法实际是通过Instrumentation类中的execStartActivity()方法来启动activity,
    Instrumentation这个类主要作用就是监控程序和系统之间的交互。而在这个execStartActivity()方法中会获取ActivityManagerService的代理对象,
    通过这个代理对象进行启动activity。启动会就会调用一个checkStartActivityResult()方法,如果说没有在配置清单中配置有这个组件,就会在这个方法中抛出异常了。
    当然最后是调用的是Application.scheduleLaunchActivity()进行启动activity,而这个方法中通过获取得到一个ActivityClientRecord对象,
    而这个ActivityClientRecord通过handler来进行消息的发送,系统内部会将每一个activity组件使用ActivityClientRecord对象来进行描述,
    而ActivityClientRecord对象中保存有一个LoaderApk对象,通过这个对象调用handleLaunchActivity来启动activity组件,
    而页面的生命周期方法也就是在这个方法中进行调用。


    9.启动一个其它应用的Activity的生命周期分析。
    同4


    10.Activity任务栈是什么?在项目中有用到它吗?说给我听听
    -android任务栈又称为Task,它是一个栈结构,具有后进先出的特性,用于存放我们的Activity组件。
    -我们每次打开一个新的Activity或者退出当前Activity都会在一个称为任务栈的结构中添加或者减少一个Activity组件,因此一个任务栈包含了一个activity的集合, android系统可以通过Task有序地管理每个activity,并决定哪个Activity与用户进行交互:只有在任务栈栈顶的activity才可以跟用户进行交互。
    -在我们退出应用程序时,必须把所有的任务栈中所有的activity清除出栈时,任务栈才会被销毁。当然任务栈也可以移动到后台, 并且保留了每一个activity的状态. 可以有序的给用户列出它们的任务, 同时也不会丢失Activity的状态信息。
    -需要注意的是,一个App中可能不止一个任务栈,某些特殊情况下,单独一个Actvity可以独享一个任务栈。还有一点就是一个Task中的Actvity可以来自不同的App,同一个App的Activity也可能不在一个Task中。



    11.什么情况下Activity不走onDestory?
    当 Activity 被另外一个 Activity 覆盖、失去焦点并不可见时处于 Stoped 状态。
    9.0的时候如果强行终止activity,那么也不会执行onDestory


    12.什么情况下Activity会单独执行onPause?
    同11


    13.a->b->c界面,其中b是SingleInstance的,那么c界面点back返回a界面,为什么?
    SingleInstance 这是一种加强的singleTask模式,它除了具有singleTask模式所有的特性外,还加强了一点,那就是具有此种模式的Activity只能单独位于一个任务栈中,换句话说,比如Activity A是singleInstance模式,当A启动后,系统会为它创建一个新的任务栈,然后A独自在这个新的任务栈中,由于栈内复用的特性,后续的请求均不会创建新的Activity,除非这个独特的任务栈被系统销毁了


    14.如果一个Activity弹出一个Dialog,那么这个Acitvity会回调哪些生命周期函数呢?
    是否弹出 Dialog,并不影响 Activity 的生命周期,所以这时和正常启动时 Activity 的生命回调方法一致: onCreate() -> onStart() -> onResume()。


    15.Activity之间如何通信 & Activity和Fragment之间通信 & Activity和Service之间通信?
    1.Activity->Activity
    [1]Intent/Bundle
    这种方式多用于Activity之间传递数据
    [2]类静态变量
    在Activity内部定义静态的变量,这种方式见于少量的数据通信,如果数据过多,还是使用第一种方式
    [3]全局变量
    创建一个类,里面定义一批静态变量,Activity之间通信都可以访问这个类里面的静态变量,这就是全局变量。

    2.Activity->Service
    [1]绑定服务的方式,利用ServiceConnection这个接口
    [2]Intent
    这种方式很简单,我们在启动和停止Service时所调用的方法都需要传入一个Intent实例对象,通过这个传入的Intent对象,我们就可以与Service进行通信。
    [3]CallBack + Handler,监听服务的进程变化

    3.Activity->Fragment
    [1]Bundle
    在创建Fragment实例的时候,调用方法setArguments将一个Bundle对象传递给Fragment,然后在Fragment中先去判断是否和当前Activity绑定上了,如果绑定上了,就可以拿出这个Bundle中的数据
    [2]直接进行方法调用
    在Activity里通过Fragment的引用,可以直接调用Framgent中的定义的任何方法。


    16.说说Activity横竖屏切换的生命周期。
     onPause
     onSaveInstanceState //这里可以用来横竖屏切换的保存数据
     onStop
     onDestroy
     onCreate
     onStart
     onRestoreInstanceState//这里可以用来横竖屏切换的恢复数据
     onResume


    17.前台切换到后台,然后在回到前台时Activity的生命周期。
    点击home键回到桌面–>onPause()–>onStop()
    再次回到原Activity时–>onRestart()–>onStart()–>onResume()


    18.下拉状态栏时Activity的生命周期?
    首先,通知栏下拉一点点,符合一般描述中“Activity被部分遮挡”——onPause()
    然后,通知栏完全落下之后,“Activity被全部遮挡”——onStop()


    19.Activity与Fragment的生命周期比较?
    onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume();
    Fragment变为不可见状态(锁屏、回到桌面、被Activity完全覆盖):onPause()->onSaveInstanceState()->onStop();
    Fragment变为部分可见状态(打开Dialog样式的Activity):onPause()->onSaveInstanceState();
    Fragment由不可见变为活动状态:onStart()->OnResume();
    Fragment由部分可见变为活动状态:onResume();
    退出应用:onPause()->onStop()->onDestroyView()->onDestroy()->onDetach()
    Fragment被回收又重新创建:被回收执行onPause()->onSaveInstanceState()->onStop()->onDestroyView()->onDestroy()->onDetach(),重新创建执行onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume()->setUserVisibleHint();
    横竖屏切换:与Fragment被回收又重新创建一样。


    20.了解哪些Activity常用的标记位Flags?
    1.Intent.FLAG_ACTIVITY_NEW_TASK,是为Activity指定“singleTask”启动模式
    2.Intent.FLAG_ACTIVITY_SINGLE_TOP,是为Activity指定“singleTop”启动模式
    3.FLAG_ACTIVITY_CLEAR_TOP,如果跟singleTask启动模式一起出现,如果被启动的Activity已经存在实例,则onNewIntent方法会被回调,如果被启动的Activity采用standard模式启动,那么连同它跟它之上的Activity都要出栈,并且创建新的实例放入栈顶。
    4.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS,新的Activity不会在最近启动的Activity的列表中保存。等同于指定属性android:excludeFromRecents="true"


    21.谈谈隐式启动和显示启动Activity的方式?
    显式启动:直接指定要跳转的Activity类名,不用过滤,效率高,适用于同一个应用中的不同Activity跳转
    隐式启动:需要过滤,相对耗时,但可以找到所有之匹配的应用。适用于不同应用之间的Activity跳转。
    隐式启动会找到所匹配到的应用,并提示用户选择打开方式,如果有多个组件被匹配成功,就会以对话框列表的方式让用户进行选择。


    22.Activity用Intent传递数据和Bundle传递数据的区别?为什么不用HashMap呢?
    要把值通过A经过B传给C
    如果用Intent的话 A-B先写一遍 再在B中都取出来 然后在把值塞到Intent中 再跳到C 累吗?
    如果我在A中用了 Bundle 的话  我把Bundle传给B 在B中再转传到C  C就可以直接去了
    这样的话 还有一个好处 就是在B中 还可以给Bundle对象添加新的 key - value 同样可以在C中取出来

    为什么不用HashMap呢?
    Bundle内部是由ArrayMap实现的,ArrayMap的内部实现是两个数组,一个int数组是存储对象数据对应下标,一个对象数组保存key和value,内部使用二分法对key进行排序,所以在添加、删除、查找数据的时候,都会使用二分法查找,只适合于小数据量操作,如果在数据量比较大的情况下,那么它的性能将退化。而HashMap内部则是数组+链表结构,所以在数据量较少的时候,HashMap的Entry Array比ArrayMap占用更多的内存。因为使用Bundle的场景大多数为小数据量
    在Android中如果使用Intent来携带数据的话,需要数据是基本类型或者是可序列化类型,HashMap使用Serializable进行序列化,而Bundle则是使用Parcelable进行序列化。而在Android平台中,更推荐使用Parcelable实现序列化,虽然写法复杂,但是开销更小,所以为了更加快速的进行数据的序列化和反序列化,系统封装了Bundle类,方便我们进行数据的传输。


    23.在隐式启动中Intent可以设置多个action,多个category吗 & 顺便讲讲它们的匹配规则?
    一个Intent对象中最多只能包括一个Action属性,但可以包含多个Category属性


    24.Activity可以设置为对话框的形式吗?
    在mainifest中对应的activity上配置如下的代码,即可让activity以对话框的方式表现出来
    < android:theme="@android:style/Theme.Dialog">


    25.如何给Activity设置进入和退出的动画?
    一种是直接在代码中设置,这需要使用到Activity的overridePendingTransition方法;
    另一种是通过自定义Activity的主题来实现。


    26.Activity使用Intent传递数据是否有限制 & 如果传递一个复杂的对象,例如一个复杂的控件对象应该怎么做?
    1 传512K以下的数据的数据可以正常传递。
    2 传512K~1024K的数据会出错,闪退。
    3 传1024K以上的数据会报错:TransactionTooLargeException。
    4 考虑到Intent还包括要启动的Activity等信息,实际可以传的数据略小于512K

    如果传递一个复杂的对象,例如一个复杂的控件对象应该怎么做?
    1)将对象转换为Json字符串
    2)使用Serializable,Parcelable序列化对象
    1.Serializable实现:
        ①业务Bean实现:Serializable接口,写上getter和setter方法
        ②Intent通过调用putExtra(String name, Serializable value)传入对象实例 当然对象有多个的话多个的话,我们也可以先Bundle.putSerializable(x,x);
        ③新Activity调用getSerializableExtra()方法获得对象实例: eg:Product pd = (Product) getIntent().getSerializableExtra("Product");
        ④调用对象get方法获得相应参数
    2.Parcelable实现:
    一般流程:
        ①业务Bean继承Parcelable接口,重写writeToParcel方法,将你的对象序列化为一个Parcel对象;
        ②重写describeContents方法,内容接口描述,默认返回0就可以
        ③实例化静态内部对象CREATOR实现接口Parcelable.Creator
        ④同样式通过Intent的putExtra()方法传入对象实例,当然多个对象的话,我们可以先 放到Bundle里Bundle.putParcelable(x,x),再Intent.putExtras()即可
    3.使用数据库

    2.2 BroadcastReceiver
    1.广播是什么?
    它是一种广泛运用在应用程序之间传输信息的机制,Android中我们发送广播内容是一个Intent,这个Intent中可以携带我们要发送的数据。


    2.广播的注册方式有哪些?
    1 静态注册:创建一个广播接收器类,广播接收器在AndroidManifest.xml文件中注册
    2 动态注册:新建一个类,让它继承自BroadcastReceiver,并重写父类的onReceive()方法就行了


    3.广播的分类 & 特性 & 使用场景?
    3.1 无序广播
      context.sendBroadcast(Intent)方法发送的广播,不可被拦截,当然发送的数据,接收者是不能进行修改的。
    3.2 有序广播
    context.sendOrderBroadcast(Intent)方法发送的广播,可被拦截,而且接收者是可以修改其中要发送的数据,修改和添加都是可以的,这就意味着优先接收者对数据修改之后,下一个接收者接受的数据是上一个接收者已经修改了的,这必须明白。
    3.3 本地广播
      localBroadcastManager.sendBroadcast(Intent),只在app内传播。


    4.说说系统广播和本地广播的原理 & 区别 & 使用场景。
    4.1 系统广播的源码角度分析
      a.自定义广播接收者BroadcastReceiver,并且重写onReceiver()方法。
      b.通过Binder机制向AMS(Activity Manager Service)进行注册。
      c.广播发送者通过Binder机制向AMS发送广播。
      d.AMS查找符合条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到相应的BroadcastReceiver(一般情况下是Activity)的消息队列中。
      e.消息循环执行拿到此广播,回调BroadcastReceiver中的onReceiver()方法。
    4.2 本地广播的源码角度分析
    相比于系统广播而言,本地广播更加安全,更加高效,以下是本地广播的特点以及内部的实现机制:
    特点:
      a.使用它发送的广播将只在自身app内传播,因此你不必担心泄漏隐私的数据。
      b.其他app无法对你的app发送该广播,因此你的app根本不可能收到非自身app发送的该广播,因此你不必担心有安全漏洞可以利用。
      c.比系统广播更加高效。


    5.有两个应用注册了一样的广播,一个是静态,一个是动态,连优先级也一样,那么当广播从系统发出来后,哪个应用先接收到广播?
    动态注册的接收者会先执行


    2.3 ContentProvider
    1.什么是内容提供者?
    (Content Provider)主要用于在不同的应用程序之间实现数据共享的功能


    2.说说如何创建自己应用的内容提供者 & 使用场景。
    新建一个类去继承ContentProvider类的方式来创建一个自己的内容提供器。ContentProvider类有6个抽象方法,我们在使用子类继承它的时候,需要将这6个方法全部重写。


    3.说说ContentProvider的原理。
    一种进程间通信的方式,其实它原理核心就是Binder。


    4.ContentProvider,ContentResolver,ContentObserver之间的关系?
    ContentProvider——内容提供者, 在android中的作用是对外共享数据,也就是说你可以通过
    ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider 对你应用中的数据进行添删改查。
    ContentResolver——内容解析者, 其作用是按照一定规则访问内容提供者的数据(其实就是调用内容提供者自定义的接口来操作它的数据)。 ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它


    5.说说ContentProvider的权限管理。
    android:grantUriPermssions:临时许可标志。
    android:permission:Provider读写权限。
    android:readPermission:Provider的读权限。
    android:writePermission:Provider的写权限。
    android:enabled:标记允许系统启动Provider。
    android:exported:标记允许其他应用程序使用这个Provider。
    android:multiProcess:标记允许系统启动Provider相同的进程中调用客户端。

    2.4 Service
    1.什么是Service?
    Service(服务)是一个一种可以在后台执行长时间运行操作而没有用户界面的组件。它运行于UI线程,因此不能进行耗时的操作。


    2.说说Service的生命周期。
    bindService:onCreate()-onBind()-unBind()-onDestroy()
    这种方式进行启动service好处是更加便利activity中操作service,通过ServiceConnection来获取service中内部类的类对象,然后通过这个类对象就可以调用类中的方法
    startService:onCreate()-onStartCommon()-onDestroy()
    当我们通过startService被调用以后,多次在调用startService(),onCreate()方法也只会被调用一次,而onStartConmon()会被多次调用


    3.Service和Thread的区别?
    Service的运行是在UI线程当中的,是绝对绝对不能进行耗时操作的,而Thread开启的子线程则可以进行耗时操作,但是Thread开启的子线程是不能直接对UI进行操作的,否则极有可能发生直接让程序崩掉,这就是它们的区别。


    4.Android 5.0以上的隐式启动问题及其解决方案。
    1 将隐式启动转换为显式启动,兼容编译sdk5.0以后版本
    2 直接写上包名以及标志
    3 判断应用是否安装


    5.给我说说Service保活方案
    1)onStartCommand方法,返回START_STICKY
    2)提升service优先级
    在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = "1000"这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时适用于广播。
    3)提升service进程优先级
    Android中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收。Android将进程分为6个等级,它们按优先级顺序由高到低依次是:
    复制代码
    1.前台进程( FOREGROUND_APP)
    2.可视进程(VISIBLE_APP )
    3.次要服务进程(SECONDARY_SERVER )
    4.后台进程 (HIDDEN_APP)
    5.内容供应节点(CONTENT_PROVIDER)
    6.空进程(EMPTY_APP)
    4)onDestroy方法里重启service
    5)Application加上Persistent属性


    6.IntentService是什么 & 原理 & 使用场景 & 和Service的区别。
    IntentService是继承处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentServiced的方式和启动传统的Service一样,同时,当任务执行完成后,IntentService会自动停止,而不需要我们手动去控制或stopSelf()。
    a.它本质是一种特殊的Service,继承自Service并且本身就是一个抽象类。
    b.它内部是由HandlerThread和Handler实现异步操作。


    7.创建一个独立进程的Service应该怎样做?
    创建远程服务
    1)定义AIDL接口
    2)新建Remote Service
    3)在AndroidManifest.xml中对Remote Service进行配置


    8.Service和Activity之间如何通信?
    1、Intent传值,onStartCommand()接收。
    2、通过onBind()获取Service实例,然后再调用Binder中的相关方法。
    3、通过回调函数达到侦听Service中数据变化。


    9.说说你了解的系统Service。
    https://blog.csdn.net/geyunfei_/article/details/78851024


    10.谈谈你对ActivityManagerService的理解。
    从系统运行的角度看,AmS可以分为Client端和Service端:Client端运行在各个app进程,app进程实现了具体的Activity,Service等,告诉系统我有那些Activity,Service等,并且调用系统接口来完成显示;Service端运行在SystemServer进程,是系统级别的ActivityManagerService的具体实现,其响应Client端的系统调用请求,并且管理Client端各个app进程的生命周期。
    https://www.cnblogs.com/xingchenkn/p/3637137.html


    11.在Activtiy中创建一个Thread和在一个Service中创建一个Thread的区别?
    Activtiy中的线程是前台线程,它的生命周期往往是随着Activity的,Activity销毁的时候,那个线程也应该被销毁,否则就会出现内存泄漏现象。而Service中开启的线程,它是工作在后台的,一般来讲,后台线程的生存期是比较长的。

    2.5 Handler
    1.子线程一定不能更新UI吗?
    是否有些控件支持在子线程更新UI呢?比如:SurfaceViw
    在Activity的onResume()生命周期函数之前是可以在子线程中更新UI的。


    2.给我说说Handler的原理
    Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
    Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
    MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
    Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。
    Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
    Handler是可以通过发送和处理Message和Runnable对象来关联相应线程的MessageQueue。通常我们认为它是一种异步机制。
    a.可以让对应的Message和Runnable在未来的某个时间点进行相应的处理。
    b.让自己想要的耗时操作在子线程中完成,让更新UI的操作在主线程中完成,而子线程与主线程之间的通信就是靠Handler来完成。


    3.Handler导致的内存泄露你是如何解决的?
    Handler导致内存泄漏的原因是:非静态内部类持有外部类的引用,导致外部类在没有被使用的时候,迟迟不能被回收,从而导致内存泄漏。即非静态Handler内部类持有外部Activity的引用,导致外部Activity退出/销毁的时候,它迟迟不能被回收,最终导致Activity的内存泄漏。 解决方法:将Handler类声明为静态,如果Handler需要访问外部类Activity的成员变量或者成员方法,可以用弱引用的方式解决。


    4.如何使用Handler让子线程和子线程通信?
    在ThreadA中准备一个Looper,也就是消息轮询大管家,然后准备发送消息的Handler,准备发送消息的Handler很容易理解,那就是在ThreadA中生成一个Handler对象即可,
    那么准备Looper怎么做呢?在ThreadA中调用Looper.prepare(),然后再调用Looper.loop()即可


    5.你能给我说说Handler的设计原理?

    6.HandlerThread是什么 & 原理 & 使用场景?
    a.HandlerThread本质上是一个线程类,它继承了Thread。
    b.HandlerThread有自己内部的Looper对象,可以进行Looper循环。
    c.通过获取HandlerThread的Looper对象传递给Handler对象,可以在handlerMessage方法中执行异步任务。
    d.优点是不会有堵塞,减少对性能的消耗,缺点是不能进行多任务的处理,需要等待进行处理,处理效率较低。
    e.与线程池注重并发不同,HandlerThread是一个串行队列,HandlerThread背后只有一个线程


    7.IdleHandler是什么?
    IdleHandler 可以用来提升性能,主要用在我们希望能够在当前线程消息队列空闲时做些事情(譬如 UI 线程在显示完成后,如果线程空闲我们就可以提前准备其他内容)的情况下,不过最好不要做耗时操作。


    8.一个线程能否创建多个Handler,Handler和Looper之间的对应关系?
    一个线程可以有多个Handler,但是一个线程只能有一个Looper,一个MessageQueue。因此它们之间的关系是一个线程只能有一个Looper,一个MessageQueue,多个Handler。


    9.为什么Android系统不建议子线程访问UI?
    UI控件不是线程安全的,如果多线程并发访问UI控件可能会出现不可预期的状态
    那为什么系统不对UI控件的访问加上锁机制呢?
    加上锁机制会让UI访问的逻辑变得复杂; 锁机制会降低UI访问的效率,因为锁机制会阻塞某些线程的执行;


    10.Looper死循环为什么不会导致应用卡死?
    ActivityThread的main方法主要就是做消息循环,一旦退出消息循环,那么你的应用也就退出了。


    11.使用Handler的postDealy后消息队列有什么变化?
    https://blog.csdn.net/qingtiantianqing/article/details/72783952


    12.可以在子线程直接new一个Handler出来吗?
    1(需先在该线程中手动开启Looper(Looper.prepare()-->Looper.loop()),然后将其绑定到Handler对象上
    2(通过Looper.getMainLooper(),获得主线程的Looper,将其绑定到此Handler对象上

    13.Message对象创建的方式有哪些 & 区别?
    https://blog.csdn.net/dfskhgalshgkajghljgh/article/details/52672115

  • 相关阅读:
    (双指针 二分) leetcode 167. Two Sum II
    (双指针) leetcode 485. Max Consecutive Ones
    (双指针) leetcode 27. Remove Element
    (String) leetcode 67. Add Binary
    (数组) leetcode 66. Plus One
    (N叉树 BFS) leetcode429. N-ary Tree Level Order Traversal
    (N叉树 递归) leetcode 590. N-ary Tree Postorder Traversal
    (N叉树 递归) leetcode589. N-ary Tree Preorder Traversal
    (N叉树 DFS 递归 BFS) leetcode 559. Maximum Depth of N-ary Tree
    (BST 递归) leetcode98. Validate Binary Search Tree
  • 原文地址:https://www.cnblogs.com/hustcser/p/11176151.html
Copyright © 2011-2022 走看看