美文网首页
字节一面二面记录

字节一面二面记录

作者: next_discover | 来源:发表于2020-04-29 23:35 被阅读0次

    一面:

    算法:

    1、n!

    
    public static int recursive(int n){
    
            if(n<=1){
    
                return 1;
    
            }else{
    
                return n*recursive(n-1);
    
            }
    
        }
    

    2、实现 double base 的 int expand 次幂

    public class Solution {
       public double Power(double base, int exponent) {
             double mul=1.0;
             /* 如果exponent = 0 输出1 */
                if(exponent == 0)
                {
                    return 1.00000;
                }
     
                /* 如果base = 0 输出0 */
                if(base >= -0.000001 && base <= 0.000001)
                {
                    return 0;
                }
                /* 如果指数大于0 */
                if(exponent > 0)
                {
                    for(int index = 0; index < exponent; index++)
                    {
                        mul *= base;
                    }
                }
                else
                {
                    exponent = -exponent;
                    for(int index = 0; index < exponent; index++)
                    {
                        mul *= base;
                    }
                    mul = 1.0/mul;
                }
     
     
                return mul;
          }
    }
    

    retrofit原理:

    反观一下Retrofit,其内部的设计结构非常清晰,
    通过动态代理来处理接口,
    通过OkHttp来处理网络请求,
    通过CallAdapterFactory来适配OkHttpCall,
    通过ConverterFactory来处理数据格式的转换,
    这符合面对对象设计思想的\color{red}{单一职责原则},同时,Retrofit对CallAdpaterFactory和ConverterFactory的依赖都是依赖其接口的,这就让我们可以非常方便的扩展自己的CallAdpaterFactory和ConverterFactory,这符合\color{red}{依赖倒置原则};不管Retrofit内部的实现如何复杂,比如动态代理的实现、针对注解的处理以及寻找合适的适配器等,Retrofit对开发者隐藏了这些实现细节,只提供了简单的Api给开发者调用,开发者只需要关注通过的Api即可实现网络请求,这种对外隐藏具体的实现细节的思想符合\color{red}{迪米特原则}。另外,Retrofit内部大量使用了设计模式,比如构造Retrofit对象时使用了\color{red}{Builder模式},处理接口时是用来\color{red}{动态代理模式},适配OkHttpCall时使用了\color{red}{Adapter模式},生成CallAdpater和Converter时使用了\color{red}{工厂模式}。Retrofit的设计正是因为遵循了面向对象的思想,以及对设计模式的正确应用,才使得其具备结构清晰、易于扩展的特点。

    怎样保证两个线程不死锁

    执行顺序,避免循环等待,设置锁的超时时间

    1、activity生命周期 a启动b,2、如果b是透明的

    a的onpause——onstop——b的oncreate——onstart——onresume

    anr异常产生,分析

    当主线程在 Sleep 的时候,如果 UI线程不需要进行操作,也就是说没有消息会发送给UI线程并要求UI线程进行处理的时候 Sleep 30秒就不会导致ANR,因为没有 出现 ANR(应用没有响应)的情况啊,没有人向线程请求什么东西,也就不需要响应了,既然没有响应了,那怎么会有ANR呢?

    Android N 的 ANR时间

    • Service 超时
    // How long we wait for a service to finish executing.
    static final int SERVICE_TIMEOUT = 20*1000; // 前台
    
    // How long we wait for a service to finish executing.
    static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10; // 后台
    
    • Broadcast 超时
    // How long we allow a receiver to run before giving up on it.
    static final int BROADCAST_FG_TIMEOUT = 10*1000;  // 前台
    static final int BROADCAST_BG_TIMEOUT = 60*1000;  // 后台
    
    
    • InputDispatching 超时
     // How long we wait until we timeout on key dispatching.
     static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
    
    • ContentProvider 超时
    // How long we wait for an attached process to publish its content providers
    // before we decide it must be hung.
    static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000;
    

    绘制卡顿分析,解决

    自行补充

    除了jni,链接java和c的通信方式

    除了aidl 还有hidl

    使用过的设计模式:单例,代理,工厂方法,建造者

    单例也会产生内存泄露,为什么

    image.png

    不管外面传入什么Context,最终都会使用Applicaton的Context,而我们单例的生命周期和应用的一样长,这样就防止了内存泄漏。

    okhttp的责任链模式有哪些

    自行补充

    git和svn的优缺点

    1.SVN优缺点
    优点:
    1、 管理方便,逻辑明确,符合一般人思维习惯。
    2、 易于管理,集中式服务器更能保证安全性。
    3、 代码一致性非常高。
    4、 适合开发人数不多的项目开发。
    缺点:
    1、 服务器压力太大,数据库容量暴增。
    2、 如果不能连接到服务器上,基本上不可以工作,看上面第二步,如果服务器不能连接上,就不能提交,还原,对比等等。
    3、 不适合开源开发(开发人数非常非常多,但是Google app engine就是用svn的)。但是一般集中式管理的有非常明确的权限管理机制(例如分支访问限制),可以实现分层管理,从而很好的解决开发人数众多的问题。

    Git优缺点
    优点:
    1、适合分布式开发,强调个体。
    2、公共服务器压力和数据量都不会太大。
    3、速度快、灵活。
    4、任意两个开发者之间可以很容易的解决冲突。
    5、离线工作。
    缺点:
    1、学习周期相对而言比较长。
    2、不符合常规思维。
    3、代码保密性差,一旦开发者把整个库克隆下来就可以完全公开所有代码和版本信息。

    tcp三次握手和四次挥手

    自行补充

    recycleview listview的优缺点

    recycler:
    1、4级缓存
    2、局部刷新
    3、viewholder重用
    4、动画
    5、列表,瀑布流,
    6、自己实现onclicklistener()
    listview:
    1、二级缓存
    2、自己实现viewholder
    3、没有动画,
    4、不能局部刷新
    5、自定义瀑布流

    怎么设计一个框架,跨平台和不跨平台的方案

    业务层:具体的业务模块
    组件层:网络,图片,ui,mvp,打印机,扫描,推送等,数据库等等组件
    底盘层:apm,推送

    SharedPreferences进程间为什么不安全

    原因:只有在创建SharedPreferences对象的时候才会从磁盘中国进行读取,读取完以后值保存在内存(HashMap)当中,下次获取SharedPreferences对象优先从缓存当中获取,所以在当前进程修改了SharedPreferences的值,其他进程的SharedPreferences对象的值并不会改变。只有把当前另外的进程关闭(如:关闭手机、或杀死该app重新进入),再次创建进程时才会重新从磁盘中再次读取文件。

    sp在创建的时候会把整个文件全部加载进内存,如果你的sp文件比较大,那么会带来几个严重问题:
    
    第一次从sp中获取值的时候,有可能阻塞主线程,使界面卡顿、掉帧。
    解析sp的时候会产生大量的临时对象,导致频繁GC,引起界面卡顿。
    这些key和value会永远存在于内存之中,占用大量内存。
    

    SharedPreferences 是线程安全的吗?它的 commit 和 apply 方法有什么区别

    1.SharePreferences是线程安全的 里面的方法有大量的synchronized来保障。
    2.SharePreferences不是进程安全的 即使你用了MODE_MULTI_PROCESS 。

    3.第一次getSharePreference会读取磁盘文件,异步读取,写入到内存中,后续的getSharePreference都是从内存中拿了。
    4.第一次读取完毕之前 所有的get/set请求都会被卡住 等待读取完毕后再执行,所以第一次读取会有ANR风险。
    5.所有的get都是从内存中读取。
    6.提交都是 写入到内存和磁盘中 。apply跟commit的区别在于
    apply 是内存同步 然后磁盘异步写入任务放到一个单线程队列中 等待调用。方法无返回 即void commit 内存同步 只不过要等待磁盘写入结束才返回 直接返回写入成功状态 true or false

    7.从 Android N 开始, 不再支持 MODE_WORLD_READABLE & MODE_WORLD_WRITEABLE. 一旦指定, 会抛异常 。也不要用MODE_MULTI_PROCESS 迟早被放弃。
    8.每次commit/apply都会把全部数据一次性写入到磁盘,即没有增量写入的概念 。 所以单个文件千万不要太大 否则会严重影响性能。

    准备好要问的问题

    自行补充

    greendao的优缺点

    1、方便快速开发,提高效率
    缺点:有些复杂sql语句不支持

    事件分发机制,action_down,action_move,action_up的区别

    1,ACTION_DOWN 事件决定着接下来的一系列事件的传递方向。返回TRUE ,则该一系列操作事件将由当前View的onToucheEvent 处理。返回false 事件将继续传递。直至返回Activity. Activity接收到其分发出去的ACTION_DOWN返回值false,则不再分发接下来的MOVE UP 事件。

    2、dispatchTouchEvent 分两种情况:ACTION_DOWN 时return 和 ACTION_MOVE 、ACTION_UP return 。ACTION_DOWN:返回TRUE和该View 的onTouchEvent ACTION_DOWN返回true 是一样的即告诉activity 当前View可以处理接下来的事件流。 返回false 结束事件剩下的也不再传递。ACTION_MOVE 、ACTION_UP :这种情况说明其子View中已经开始处理事件流,在这里return直接导致该部分事件流不再继续传递,对于没有return的还按照正常的流程传递。

    3、onInterceptTouchEvent 不论什么时候拦截,接下来的事件都将传递给当前的onTouchEvent处理接下来的事件流。例如在当前View的onInterceptTouchEvent 的ACTION_MOVE 中返回了true,则接下来的ACTION_MOVE、ACTION_UP都将传递给当前view的onTouchEvent处理。其子View将不再接收处理剩下的事件。

    1.在所有的事件微观表现中,action_down是整个事件的基础,是任何宏观事件的起始事件,一旦action_down return false,表示事件继续向外层冒泡,当有某一层的action_down
    
    中return true,表示此层消费了此action_down事件,那么在接下里的action_move、action_up等事件中,将直接先传入此层中,且不管action_move、
    
    action_up等返回false还是true,事件都不会继续冒泡到外层。事件由此被消费掉。
    
    2.由此可以得知,action_down在整个事件传递中的重要作用。如果某层发生了action_move或者action_up微观事件,那么一定发发生过action_down微观事件。
    
     
    
    关于setOnTouchListener、setOnClickListener和setOnLongClickListener:
    
    Android中,有时候经常见到针对同一控件可能设置不同的事件监听器(如setOnTouchListener、setOnClickListener和setOnLongClickListener),对于这些事件监听器的执行顺序,
    
    setOnTouchListener是最先执行的。并且只有当此空间完整走完action_down和action_up流程后,才可能调用performClick()方法,及调用onclick执行。而onLongClick则是在action_down
    
    之后开始,并且是在一个新的线程中去判断按压的时间,条件满足则调用performLongClick()函数,及调用onLongClick()函数。
    
    

    二面:

    1、怎样检测内存泄露,生产上怎么定位内存泄露
    2、怎样定位native层叠内存泄露
    3、bindservice和startservice的区别
    4、怎样不让别人绑定我的service服务
    5、音乐播放器怎样实现退出页面还可以播放
    6、contentprovider插入一条数据要做那些操作

    1.继承contentprovider
    2.重写6个抽象方法
    ContentProvider的六个抽象方法的含义分别是:
    onCreate():代表ContentProvider的创建,可以用来进行一些初始化操作
    getType(Uri uri):用来返回一个Uri请求所对应的MIME类型
    insert(Uri uri, ContentValues values):插入数据
    query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):查询数据
    update(Uri uri, ContentValues values, String selection, String[] selectionArgs):更新数据
    delete(Uri uri, String selection, String[] selectionArgs):删除数据
    
    <provider
                android:name=".MyContentProvider"
                android:authorities="com.czy.contentprovideremo.MyContentProvider"
                android:exported="true" />
    name:ContentProvider的全称类名
    authorities:唯一标识了一个ContentProvider,外部应用通过该属性值来访问我们的ContentProvider。因此该属性值必须是唯一的,建议在命名时以包名为前缀
    exported:表明是否允许其他应用调用ContentProvider,true表示支持,false表示不支持。默认值根据开发者的属性设置而会有所不同,如果包含 Intent-Filter 则默认值为true,否则为false
    

    看栗子:https://www.jianshu.com/p/601086916c8f

    7、数据库事务和普通操作的区别,自己怎样实现事务
    8、内存泄露有哪些,handler,单例,webview,具体场景,怎样解决

    handler
    静态,弱引用,ondestroy移除removeallcallbacks
    单例传入applicaton的context,不要使用activity的或者是fragment的
    webview采用单独进程,使用完成干掉进程

    9、touch的事件传递


    image.png

    10、怎样在子线程启动handler

    创建looper:Looper.prepare()
    启动looper:Looper.loop()
    

    11、浮窗是怎么实现的,window是由什么管理的
    12、什么时候复写 measure layout draw
    13、measure方法是怎样将大小传递给系统的

    就是那个setMeasureDimension()

    image.png

    14、自定义控件的时候,canvas的save()和restore()的作用

    save() : 用来保存Canvas的状态,save()方法之后的代码,可以调用Canvas的平移、放缩、旋转、裁剪等操作!
    restore():用来恢复Canvas之前保存的状态(可以想成是保存坐标轴的状态),防止save()方法代码之后对Canvas执行的操作,继续对后续的绘制会产生影响,通过该方法可以避免连带的影响
    

    15、home按键的事件是怎么处理的
    16、音量键是怎样传递的
    17、aidl的oneway的作用
    oneway说明是异步调用

    18、怎样获取控件大小

    在oncreate的时候获取到的大小为0,需要使用
    imageView.measure(0, 0);
    int height = imageView.getMeasuredHeight();
    int width = imageView.getMeasuredWidth();
    

    相关文章

      网友评论

          本文标题:字节一面二面记录

          本文链接:https://www.haomeiwen.com/subject/urbjvhtx.html