前言
最近准备换工作,梳理和回顾被问及的技术问题和知识点 , 希望能为Android开发者提供有益的参考.
按照时间逆序整理
快手一面 Jul 19th, 2024
- git rebase 和 git commit 区别和场景
-
- rebase 逐个应用 mater 分支的更改,然后以 master 分支最后的提交作为基点,再逐个应用 feature/1的每个更改,冲突需要解决多次 - merge 多了一次合并信息 - git 合并多次commit - git rebase -i
-
https 请求的过程
-
http可以预防 dns劫持吗
- 不可以
-
dns是哪一层的
- 应用层
-
重载和重写的区别
-
重载: 发生在本类,方法名相同,参数列表不同,与返回值无关,只和方法名,参数列表,参数的类型有关.
-
重写(override):一般都是表示子类和父类之间的关系,其主要的特征是:方法名相同,参数相同,但是具体的实现不同。
-
-
抽象类和接口的区别
-
1、默认的方法实现:抽象类可以有默认的方法实现完全是抽象的。接口根本不存在方法的实现。jdk1.8 接口有默认的方法
-
2、实现抽象类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现
-
3、抽象类可以有构造器,而接口不能有构造器
-
4、抽象方法可以有public、protected和default这些修饰符,但是接口方法默认修饰符是public。你不可以使用其它修饰符。
-
5、抽象类在java语言中所表示的是一种继承关系,一个子类只能存在一个父类,但是可以存在多个接口。(单继承多实现)
-
6、抽象方法比接口速度要快
-
7、如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。 如果你往接口中添加方法,那么你必须改变实现该接口的类。
-
-
java.lang.string 和 custom.lang.string
-
exception继承关系
-
checkoutException和unCheckoutException
- 非受检异常指的是java.lang.RuntimeException和java.lang.Error类及其子类,所有其他的异常类都称为受检异常。 - 受检异常又叫编译时异常,编译时不能被忽略合法性,要在编译时刻由编译器来检查。但是需要注意的是,无论是受检异常还是非受检异常,都是发生在程序的运行阶段,不要错误地认为编译时异常就发生在编译阶段!!!
-
::fun
-
out Any 和 in any 协变和逆变
-
-
inflate.form()参数
-
根节点是否是 merge ViewGroup root
boolean attachToRoot
返回值 否 notNull
false
返回的是 xml 布局的根节点 View 对象,并且对象上拥有根节点上的布局参数。 否 notNull
true
返回的是添加了根节点 View
对象以及布局参数的root
对象。否 null
false
返回的是没有布局参数信息的根节点 View
对象。否 null
true
返回的是没有布局参数信息的根节点 View
对象。是 notNull
(必须)true
(必须)返回的是 root
对象。
-
-
-
handler delay 实现原理
-
消息屏障
-
MessageQueue 是怎么的数据结构
-
A Activity 跳到 B Activity 的生命
-
activity 那些生命周期对用户可见
-
service和thread 区别
-
概念
-
Service:Android提供的可以在后台长期运行的组件
-
Thread:程序执行的最小单元,它是分配CPU的基本单元,可以执行异步的操作
-
-
生命周期不同
-
Thread生命周期
-
Service生命周期
-
-
相同点:都可以执行异步操作
-
-
如何分析app掉帧
-
GPU模式分析
- cpu、内存 、网络
-
profiler
-
systemtrace
-
-
android hook
-
hide api
-
hook 可以修改别的进程的代码 沙盒机制
-
-
锁住不同的方法(锁住静态方法和普通方法)
-
里氏替换原则
-
里氏替换原则的定义是:如果对每一个类型为 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
-
-
创建对象步骤
-
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
- 百度项目中使用的框架
- 网络库使用的框架、如何解决网络复用
- https请求的过程
- mvc、mvp、mvvm
- 内存泄漏、内存抖动
- 强软弱虚
- GC触发的时机
- GC垃圾回收算法
- 点击桌面图标后应用启动流程
算法题
- 1.n阶台阶
- 2.contains方法
字节一面 Jul 16th, 2024
-
HashMap 源码
-
ArrayList 和 LinkedList 源码
-
kotlin比Java语言的优势和区别
-
kotlin和Java方法互调,有没有遇到什么问题
-
kotlin调用Java方法返回值是否可为空
-
kotlin调用Java方法,Java方法返回值可为空,应该怎么封装比较好
-
A->B Activity的生命周期
-
启动模式不同,分别说明
-
B的启动模式为SingleTop,且在栈顶有实例。
-
启动透明主题Activity的生命周期
-
A onPause() -> B onCreate() -> onStart() -> onResume()
-
Activity A不会进入onStop()状态,而是直接进入onPause()状态。这是因为Activity A仍然可见,但是失去了焦点。
-
-
Dialog的生命周期
-
-
事件分发机制
-
使用Intent有什么问题
-
简单聊一聊Binder
-
自定义View怎么实现图片圆角
-
- 获取原始图片的Bitmap对象。
-
- 创建一个与View大小相同的Bitmap对象,并使用Canvas对象将圆角矩形绘制到Bitmap上。
-
- 将Paint对象的Xfermode属性设置为PorterDuff.Mode.SRC_IN,表示保留原始图像和绘制的圆角矩形的交集部分。
-
- 使用Canvas对象将原始图像绘制到Bitmap上,并使用Paint对象绘制圆角矩形。
-
- 将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); } }
-
-
-
开放性需求,打开一个页面,网络环境差数据未及时返回,为了提高到达率,请设计一个网络请求重试功能
算法题
自定义数据结构实现LRU算法
美团一面 Jul 3rd, 2024
- LeakCanary原理
- activity的启动流程
- intent传递数据过大怎么解决
- android跨进程通信的方式
- ams通知孵化器进程fork时,为什么不使用binder,使用socket
- fork可以导致死锁吗
- binder、socket在android使用的场景
- 自定义圆角图片
- 了解Xfermode
- 热更新原理
- 点击事情的传递流程
- handler原理
- 手写 单例模式(懒汉、饿汉、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;
}
}
最后
如果对您有一点点帮助,希望点点赞、支持一下。感谢感谢!!!
整理中。。。