Android 面试总结 (二)

前言

最近准备换工作,梳理和回顾被问及的技术问题和知识点 , 希望能为Android开发者提供有益的参考.
按照时间逆序整理

快手一面 Jul 19th, 2024

  1. git rebase 和 git commit 区别和场景
  • 在这里插入图片描述

  • 在这里插入图片描述

      	- rebase 逐个应用 mater 分支的更改,然后以 master 分支最后的提交作为基点,再逐个应用 feature/1的每个更改,冲突需要解决多次
    
      	- merge 多了一次合并信息
    
      - git 合并多次commit
    
      	- git rebase -i
    
  1. https 请求的过程

    • 在这里插入图片描述
  2. http可以预防 dns劫持吗

    - 不可以
    
  3. dns是哪一层的

    • 应用层
  4. 重载和重写的区别

    • 重载: 发生在本类,方法名相同,参数列表不同,与返回值无关,只和方法名,参数列表,参数的类型有关.

    • 重写(override):一般都是表示子类和父类之间的关系,其主要的特征是:方法名相同,参数相同,但是具体的实现不同。

  5. 抽象类和接口的区别

    • 1、默认的方法实现:抽象类可以有默认的方法实现完全是抽象的。接口根本不存在方法的实现。jdk1.8 接口有默认的方法

    • 2、实现抽象类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现

    • 3、抽象类可以有构造器,而接口不能有构造器

    • 4、抽象方法可以有public、protected和default这些修饰符,但是接口方法默认修饰符是public。你不可以使用其它修饰符。

    • 5、抽象类在java语言中所表示的是一种继承关系,一个子类只能存在一个父类,但是可以存在多个接口。(单继承多实现)

    • 6、抽象方法比接口速度要快

    • 7、如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。 如果你往接口中添加方法,那么你必须改变实现该接口的类。

  6. java.lang.string 和 custom.lang.string

  7. exception继承关系

在这里插入图片描述

  1. checkoutException和unCheckoutException

    - 非受检异常指的是java.lang.RuntimeException和java.lang.Error类及其子类,所有其他的异常类都称为受检异常。
    
    - 受检异常又叫编译时异常,编译时不能被忽略合法性,要在编译时刻由编译器来检查。但是需要注意的是,无论是受检异常还是非受检异常,都是发生在程序的运行阶段,不要错误地认为编译时异常就发生在编译阶段!!!
    
  2. ::fun

  3. out Any 和 in any 协变和逆变

  4. inflate.from参数

    • inflate.form()参数

      • 根节点是否是 mergeViewGroup rootboolean attachToRoot返回值
        notNullfalse返回的是 xml 布局的根节点 View 对象,并且对象上拥有根节点上的布局参数。
        notNulltrue返回的是添加了根节点 View 对象以及布局参数的 root 对象。
        nullfalse返回的是没有布局参数信息的根节点 View 对象。
        nulltrue返回的是没有布局参数信息的根节点 View 对象。
        notNull (必须)true (必须)返回的是 root 对象。
  5. handler delay 实现原理

  6. 消息屏障

  7. MessageQueue 是怎么的数据结构

  8. A Activity 跳到 B Activity 的生命

  9. activity 那些生命周期对用户可见

  10. service和thread 区别

    • 概念

      • Service:Android提供的可以在后台长期运行的组件

      • Thread:程序执行的最小单元,它是分配CPU的基本单元,可以执行异步的操作

    • 生命周期不同

      • Thread生命周期

      • Service生命周期

    • 相同点:都可以执行异步操作

  11. 如何分析app掉帧

  12. GPU模式分析

      - cpu、内存 、网络
    
    • profiler

    • systemtrace

  13. android hook

    • hide api

    • hook 可以修改别的进程的代码 沙盒机制

  14. 锁住不同的方法(锁住静态方法和普通方法)

  15. 里氏替换原则

    • 里氏替换原则的定义是:如果对每一个类型为 S 的对象 o1,都有类型为 T 的对象 o2,使得以 T 定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 S 是类型 T 的子类型。

    • 在这个例子中,类 B 继承自类 A,因此 B 是 A 的子类型。根据里氏替换原则,我们可以用类 A 的实例去替换类 B 的实例,而不会影响程序的行为。也就是说,类 A 的对象可以被用作类 B 的对象使用,因为类 B 是类 A 的子类型。在这个例子中,类 B 中的成员变量 a 覆盖了类 A 中的成员变量 a,但是这并不会影响到程序的行为。如果我们把类 B 的对象替换成类 A 的对象,程序的行为也不会发生变化。因此,类 B 是类 A 的子类型,符合里氏替换原则。

    • class A{
        int a = 1;
      }
      
      class B extends A{
        int a = 10;
      }
      
      A b = new B()
      b.a =?  //1
      
      B b = new B()
        b.a = ? //10 
      
       
        
      
      
  16. 创建对象步骤

    • class A {
          static { //静态初始化块
              System.out.println("static A");
          }
      
          { //实例初始化代码块:在每次创建类的实例时,都会执行实例初始化块,它可以用来初始化实例变量
              System.out.println("xxx A");
          }
      
          A() {
              System.out.println("constructor A");
          }
      }
      
      class B extends A {
          static {
              System.out.println("static B");
          }
      
          {
              System.out.println("xxx B");
          }
      
          B() {
              System.out.println("constructor B");
          }
      }
      
      
      A a = new B() 打印的结果
      static A
      static B
      xxx A
      constructor A
      xxx B
      constructor B
      
      
      B b = new B() 打印的结果
      xxx A
      constructor A
      xxx B
      constructor B
      
      
      

算法题

算法题:
一个楼梯有n阶,一次只能一阶或者两阶,爬到顶层有多少种路径?
如果有m阶是坏的,爬到顶层有多少种路径

    public int climbStairs(int n) {
        /**第一种方法:
         * 递归描述,但是n很大时会超时
         * */
/**        if(n <= 2) {
            return n;
        }
        return climbStairs(n-1)+climbStairs(n-2);*/

        /**第二种方法:
         * 使用非递归的方法,一个变量进行传递
         * 其中的first是从左向右,即first:相当于f(n-2),second:相当于f(n-1)
         * second:是靠近f(n) {sum}的第一个数
         * */
        int first = 1, second = 2, sum = 0;
        if (n <= 2){
            return n;
        }
        while (n-- >= 3){
//            请注意赋值的顺序
            sum = first + second;
            first = second;
            second = sum;
        }
        return sum;
    }

字节二面 Jul 18th, 2024

  1. 百度项目中使用的框架
  2. 网络库使用的框架、如何解决网络复用
  3. https请求的过程
  4. mvc、mvp、mvvm
  5. 内存泄漏、内存抖动
  6. 强软弱虚
  7. GC触发的时机
  8. GC垃圾回收算法
  9. 点击桌面图标后应用启动流程

算法题

	- 1.n阶台阶

	- 2.contains方法

字节一面 Jul 16th, 2024

  1. HashMap 源码

  2. ArrayList 和 LinkedList 源码

  3. kotlin比Java语言的优势和区别

  4. kotlin和Java方法互调,有没有遇到什么问题

  5. kotlin调用Java方法返回值是否可为空

  6. kotlin调用Java方法,Java方法返回值可为空,应该怎么封装比较好

  7. A->B Activity的生命周期

    • 启动模式不同,分别说明

    • B的启动模式为SingleTop,且在栈顶有实例。

    • 启动透明主题Activity的生命周期

      • A onPause() -> B onCreate() -> onStart() -> onResume()

      • Activity A不会进入onStop()状态,而是直接进入onPause()状态。这是因为Activity A仍然可见,但是失去了焦点。

    • Dialog的生命周期

  8. 事件分发机制

  9. 使用Intent有什么问题

  10. 简单聊一聊Binder

  11. 自定义View怎么实现图片圆角

      1. 获取原始图片的Bitmap对象。
      1. 创建一个与View大小相同的Bitmap对象,并使用Canvas对象将圆角矩形绘制到Bitmap上。
      1. 将Paint对象的Xfermode属性设置为PorterDuff.Mode.SRC_IN,表示保留原始图像和绘制的圆角矩形的交集部分。
      1. 使用Canvas对象将原始图像绘制到Bitmap上,并使用Paint对象绘制圆角矩形。
      1. 将Bitmap对象绘制到View上。
    • public class RoundImageView extends ImageView {
          private Paint paint;
          private Xfermode xfermode;
      
          public RoundImageView(Context context) {
              super(context);
              init();
          }
      
          public RoundImageView(Context context, AttributeSet attrs) {
              super(context, attrs);
              init();
          }
      
          public RoundImageView(Context context, AttributeSet attrs, int defStyle) {
              super(context, attrs, defStyle);
              init();
          }
      
          private void init() {
              paint = new Paint();
            // 取交集,显示上层
              xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
              paint.setAntiAlias(true); // 抗锯齿,边界变迷糊
          }
      
          @Override
          protected void onDraw(Canvas canvas) {
              Drawable drawable = getDrawable();
              if (drawable == null) {
                  super.onDraw(canvas);
                  return;
              }
              // 原始
              Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
              int width = getWidth();
              int height = getHeight();
              // 新的
              Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
              
             
              Canvas tempCanvas = new Canvas(output);
              RectF rectF = new RectF(0, 0, width, height);
              tempCanvas.drawRoundRect(rectF, 50, 50, paint);
             
              paint.setXfermode(xfermode);
              tempCanvas.drawBitmap(bitmap, 0, 0, paint);
              paint.setXfermode(null);
            
              canvas.drawBitmap(output, 0, 0, paint);
          }
      }
      
      
    • 自定义View怎么实现一行文本两端对齐,两行文本居中对齐的控件

      • public class AlignTextView extends View {
           
            private void init() {
                mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
                mPaint.setTextSize(50);
                mPaint.setColor(Color.BLACK);
                mText1 = "One line text";
                mText2 = "Two line text";
                mText1Bound = new Rect();
                mText2Bound = new Rect();
                // 返回一个包含中文的矩形边界
                mPaint.getTextBounds(mText1, 0, mText1.length(), mText1Bound);
                mPaint.getTextBounds(mText2, 0, mText2.length(), mText2Bound);
            }
        
            @Override
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
        
                int width = getWidth();
                int height = getHeight();
        
                // 计算第一行文本的宽度
                float text1Width = mPaint.measureText(mText1);
        
                // 计算两端空格的宽度:
                // 密           码:
              	// 
                float spaceWidth = (width - text1Width) / (mText1.length() - 1);
        
                // 绘制第一行文本
                float x = 0;
                for (int i = 0; i < mText1.length(); i++) {
                    String c = String.valueOf(mText1.charAt(i));
                    canvas.drawText(c, x, mText1Bound.height(), mPaint);
                    x += mPaint.measureText(c) + spaceWidth;
                }
        
                // 绘制第二行文本
                float text2Width = mPaint.measureText(mText2);
                float text2X = (width - text2Width) / 2;
                float text2Y = height - mText2Bound.height();
                canvas.drawText(mText2, text2X, text2Y, mPaint);
            }
        }
        
        
  12. 开放性需求,打开一个页面,网络环境差数据未及时返回,为了提高到达率,请设计一个网络请求重试功能

算法题

自定义数据结构实现LRU算法

美团一面 Jul 3rd, 2024

  1. LeakCanary原理
  2. activity的启动流程
  3. intent传递数据过大怎么解决
  4. android跨进程通信的方式
  5. ams通知孵化器进程fork时,为什么不使用binder,使用socket
  6. fork可以导致死锁吗
  7. binder、socket在android使用的场景
  8. 自定义圆角图片
  9. 了解Xfermode
  10. 热更新原理
  11. 点击事情的传递流程
  12. handler原理
  13. 手写 单例模式(懒汉、饿汉、dcl)

算法题

【108】将升序数组转化成平衡二叉搜索树
> 给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 平衡 二叉搜索树。

 BST 的中序遍历是升序的,因此本题等同于根据中序遍历的序列恢复二叉搜索树。
  因此我们可以以升序序列中的任一个元素作为根节点,
  以该元素左边的升序序列构建左子树,以该元素右边的升序序列构建右子树,
  这样得到的树就是一棵二叉搜索树啦~ 
  又因为本题要求高度平衡,因此我们需要选择升序序列的中间元素作为根节点奥~
		  
  class Solution {
      public TreeNode sortedArrayToBST(int[] nums) {
          return helper(nums, 0, nums.length - 1);
      }
  
      public TreeNode helper(int[] nums, int left, int right) {
          if (left > right) {
              return null;
          }
  
          // 总是选择中间位置左边的数字作为根节点
          int mid = left + (right - left) / 2;
  
          TreeNode root = new TreeNode(nums[mid]);
          root.left = helper(nums, left, mid - 1);
          root.right = helper(nums, mid + 1, right);
          return root;
      }
  }

最后

如果对您有一点点帮助,希望点点赞、支持一下。感谢感谢!!!
整理中。。。

  • 12
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值