• 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

  • 相关阅读:
    C# -- 使用线程池 ThreadPool 执行多线程任务
    Bootstrap -- 插件: 按钮状态、折叠样式、轮播样式
    C# -- 等待异步操作执行完成的方式
    Bootstrap -- 插件: 提示工具、弹出框、 警告框消息
    Bootstrap -- 插件: 模态框、滚动监听、标签页
    Bootstrap -- 缩略图、进度条、列表组、面板
    C# -- 使用委托 delegate 执行异步操作
    Bootstrap -- 导航栏样式、分页样式、标签样式、徽章样式
    Bootstrap -- 下拉菜单、输入框组、导航菜单
    Mutex
  • 原文地址:https://www.cnblogs.com/hustcser/p/11176151.html
Copyright © 2020-2023  润新知