Fork me on GitHub
image frame

面试-腾讯-基础开发

面试-腾讯-基础开发

一面

面试体验巨好,超级好,牛逼

  • js题
    • setTimeout
  • 算法题
    • sort 二分找最小
    • 合并有序节点
    • 查找第三大的节点
  • java 多线程
    • 生产者消费者
  • js模块化
  • electron
    • 进程通信
  • 开源项目
    • 看了我的简历写的开源项目,问了一下
      • 怎么编译kotlin到js
  • Android
    • Activity生命周期 ,应该是看到我简历有写,就简单问了一下
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      120
      121
      122
      123
      124
      125
      126
      127
      128
      129
      130
      131
      132
      133
      134
      135
      136
      137
      138
      139
      140
      141
      142
      143
      144
      145
      146
      147
      148
      149
      150
      151
      152
      153
      154
      155
      156
      157
      158
      159
      160
      161
      162
      163
      164
      165
      166
      167
      168
      169
      170
      171
      172
      173
      174
      175
      176
      177
      178
      179
      180
      181
      182
      183
      184
      185
      186
      187
      188
      189
      190
      191
      192
      193
      194
      195
      196
      197
      198
      199
      200
      201
      202
      203
      204
      205
      206
      207
      208
      209
      210
      211
      212
      213
      214
      215
      216
      217
      218
      219
      220
      221
      222
      223
      224
      225
      226
      227
      228
      229
      230
      231
      232
      233
      234
      235
      236
      237
      238
      239
      240
      241
      242
      243
      244
      245
      246
      247
      248
      249
      250
      251
      252
      253
      254
      255
      256
      257
      258
      259
      260
      261
      262
      263
      264
      265
      266
      267
      268
      269
      270
      271
      272
      273
      274
      275
      276
      277
      278
      279
      280
      281
      282
      283
      284
      285
      286
      287
      288
      289
      290
      291
      292
      293
      294
      295
      296
      297
      298
      299
      300
      301
      302
      303
      304
      305
      306
      307
      308
      309
      310
      311
      312
      313
      314
      315
      316
      317
      318
      319
      320
      321
      322
      323
      324
      325
      326
      327
      328
      329
      330
      331
      332
      333
      334
      335
      336
      337
      338
      339
      340
      341
      342
      343
      344
      345
      346
      347
      348
      349
      350
      351
      352
      353
      354
      355
      356
      357
      358
      359
      360
      361
      362
      363
      364
      365
      366
      367
      368
      // 45分钟

      题目1(js基础): 阅读下面代码,写出结果
      let data = { "a": 1, "b": 101 }
      function read(readUseTime) {
      return new Promise(resolve => {
      setTimeout(() => {
      resolve({...data})
      }, readUseTime)
      })
      }

      function write(value, writeUseTime) {
      console.info('write ',value)
      return new Promise(resolve => {
      setTimeout(() => {
      data = value
      resolve()
      }, writeUseTime)
      })
      }

      async function readAndWrite(key, value, readUseTime = 0, writeUseTime = 0) {
      let d = await read(readUseTime)
      d[key] = value
      await write(d, writeUseTime)
      }

      ;(() => {
      setTimeout(readAndWrite, 0, 'a', 2)
      setTimeout(readAndWrite, 0, 'b', 102)
      setTimeout(() => {
      // 输出结果
      console.log(data)
      }, 1000)
      })()
      { "a": 1, "b": 102 }

      进一步问:必需输出的是 { "a": 2, "b": 102 },怎么修改function readAndWrite

      var isdo = null
      async function readAndWrite(key, value, readUseTime = 0, writeUseTime = 0) {
      if (isdo != null)
      await isdo;

      isdo = new Promise(async (resolve,reject)=>{
      let d = await read(readUseTime)
      d[key] = value
      resolve(d)
      }).then((res)=> {
      return new Promise(async (resolve, reject)=>{

      await write(res, writeUseTime)
      isdo = false
      resolve()
      })
      })

      }

      var h = setTimeout(() => { h = null; }, 1000)
      if (h == undefined) { }
      isdo = new Promise


      ;(() => {
      setTimeout(readAndWrite, 0, 'a', 2)

      setTimeout(readAndWrite, 0, 'b', 102)
      setTimeout(() => {
      // 输出结果
      console.log(data)
      }, 1000)
      })()
      题目2(算法):合并两个从小到大链表的链表,使用的算法越快越好。
      比如:L1={1,3,5}, L2={2,4}, L1.merge(L2)后,L1={1,2,3,4,5}, L2={}
      class LinkNode {
      private int val;
      private LinkNode next;
      public void merge(LinkNode node) {
      // TODO 请完成实现部分
      }
      }


      function LinkNode () {

      this.val = 0;
      this.next = null
      this.merge = function (node) {
      let head = new LinkNode()
      let res = head
      let l1 = node
      let l2 = this

      //if

      while(l1 != null || l2 != null) {
      let nex
      if (l1.val < l2.val) {
      res.insert(l1)
      l1 = l1.next
      res = res.next
      } else if (l1.val > l2.val) {
      res.insert(l2)
      l2 = l2.next
      res = res.next
      }
      }

      if (l1 != null) {
      res = l1
      } else {
      res = l2
      }
      this.next = head.next
      this.val = head.val
      }

      this.insert = function (node) {
      let nex = this.next
      // let nodex = node.next
      this.next = node
      node.next = nex
      // node = nodex
      }
      }

      //bu yong new node
      function LinkNode () {

      this.val = 0;
      this.next = null
      this.merge = function (node) {

      let res = null
      let l1 = node
      let l2 = this



      let head = l1.val <= l2.val? l1:l2
      res = head
      //if
      if(head.val == l1.val) l1 = l1.next
      else l2 = l2.next

      while(l1 != null || l2 != null) {
      if (l1.val < l2.val) {
      l1.insert(l2)
      l1 = l1.next

      } else if (l1.val > l2.val) {
      l2 = l2.next
      }
      }

      if (l1 != null) {
      res = l1
      } else {
      res = l2
      }

      }

      this.insert = function (node) {
      let nex = this.next
      // let nodex = node.next
      this.next = node
      node.next = nex
      // node = nodex
      }
      }



      题目3(算法):给定一个递增循环整数数组,从里面找出最小的元素,使用的算法越快越好。特别地,最小的元素可能出现在数组中间。比如:50, 52, 63, 90, 3, 8, 15, 44。
      class Problem2 {
      int findmin(int[] array) {
      // TODO 请完成实现部分

      }
      }


      var findMin = function (arr) {
      return arr.sort((b,a) => b-a)[0]
      }

      var findMin = function (arr ) {
      let l =0
      let m = parseInt(arr.length/2)
      let r = arr.length-1
      if (arr.length==2) return Math.min(arr[0],arr[1])
      if (arr.length==1) return arr[0]
      console.info(arr)
      if (arr[l] <= arr[m]){
      return Math.min(arr[l],findMin(arr.slice(m+1)))
      }else {
      return Math.min(arr[m],findMin(arr.slice(0,m)))
      }
      }


      题目4(算法):在二叉排序树上面找出第3大的节点。注意:不能把二叉树全量存储到另外的存储空间,比如存储到数组中,然后取出数组的第三个元素。
      class TreeNode {
      int value;
      TreeNode left, right;
      };

      class Problem3 {
      TreeNode find(TreeNode root) {
      // TODO 请完成实现部分

      }
      }

      var res = []
      var find = function (root) {
      findMax(root)
      return res[0]
      }
      var add = function add(arr, v) {
      if (arr.length >2) {
      arr[0] = arr[1]
      arr[1] = arr[2]
      arr[2] = v
      }
      else {
      arr.push(v)
      }
      return arr
      }
      var finMax = function (root) {
      if (root.left != null) {
      res = add(res,root.left.value)
      }

      res = add(res,root.value)
      if (root.right != null) {
      return findMax(root.right)
      }
      }



      题目5(java多线程):阅读下面代码,在2线程环境下,设计一个方案,判断无限数据流(Stream)每个正整数是否素数,越快越好
      interface Stream {
      long get(); // 获取下一个需判断的整数
      void put(boolean result); // 返回整数是否素数的结果
      static boolean isPrimeNumber(long num) { // 判断一个整数是否素数
      if (num < 2) return false;
      for (long i = 2, s = (long) Math.sqrt(num); i <= s; i++) {
      if (num % i == 0) return false;
      }
      return true;
      }
      static Stream getInstance() {
      try {
      return (Stream) Class.forName("StreamImpl").newInstance(); // 运行环境保证不会异常
      } catch (Exception e) {
      return null;
      }
      }
      }
      比如:Stream={1,2,3,4,...}, Result={false,true,true,false,...},注意输出顺序。
      public class Problem5 {
      private Stream stream = Stream.getInstance();
      private long t1;
      public void thread1() throws InterruptedException {
      assert Thread.currentThread().getName() == "thread1";
      // TODO 请完成实现部分
      long t = stream.get()
      boolean b = Stream.isPrimeNumber(t)

      stream.notify()
      t1
      stream.put(

      )
      stream.wait();
      }
      public void thread2() throws InterruptedException {
      assert Thread.currentThread().getName() == "thread2";

      long t = stream.get()
      boolean b = Stream.isPrimeNumber(t)
      stream.wait();
      stream.put(
      Stream.isPrimeNumber(stream.get())
      )
      stream.notify()
      }
      // TODO 请完成实现部分

      public static void main(String[] args) {
      Problem5 p5 = new Problem5()
      new Thread(new Runnable() {
      @Override
      void run() {

      try {
      p5.thread1();
      } catch (Exception e) {

      }
      },"thread1").start();

      new Thread(new Runnable() {
      @Override
      void run() {
      try {
      p5.thread2();
      } catch (Exception e) {

      }
      },"thread2").start();

      }
      }


      js基础:js模块化有哪些
      引用js模块
      require
      require('xxx.js')
      import A from 'hjk.js'
      import AC from 'jjj.vue'

      一个得到的是引用
      一个得到的是一个对象

      import 大部分时候通过 babel 实现

      node不支持直接使用import

      为了支持es6 有一个新的js运行环境 deno ?



      electron基础:Main进程,Renderer进程如何通信


      ipcMain

      ipcMain.on('xxx-event',(event,arg) =>{
      //do some
      event.sender.send('')
      }

      ipcRender.send

      -- remote



      build.gradle
      task complieJs (type: Exec, group: 'custom') {
      workingDir '.'
      commandLine 'kotlinc-js', '-output', 'node-publish/lib/kfmd.js' , "build/source", '-module-kind', 'commonjs'
      }
      // A problem occurred starting process 'command 'kotlinc-js''

      var core = kfmd.Core()
      var html = core.setContainorClass('demo').trans(a)


      Android

二面 2020/03/30 8:30

  • 项目
  • 概率题
  • 老鼠吃药二进制
  • 打乱扑克牌

面试-美团-Android

美团 Android 一面

感觉问得有点奇怪

  • 冒泡
    • 排序算法时间复杂度
    • 优化
  • 哈夫曼 哈夫曼编码
    • 觉得我生成的结果反了
  • 瀑布模型
  • onclick
  • 自定义view属性
  • 点击渐变颜色
  • 聊了一下快应用 rn 容器
  • 看了下我的github的code
  • 主要聊天了

冒泡可以优化,忘了还能这样优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

let sort = function (arr) {
let change = true
let t = 0
while(change) {
change = false
for (let x = 0; x < arr.length-1; x++) {
if (arr[x] > arr[x+1]) {
t = arr[x]
arr[x] = arr[x+1]
arr[x+1] = t
change = true
}
}
}

return arr
}

// 优化过
let sort2 = function (arr) {
let change = true
let t = 0
let l = arr.length-1
while(change && l >0) {
change = false
for (let x = 0; x < l ; x++) {
if (arr[x] > arr[x+1]) {
t = arr[x]
arr[x] = arr[x+1]
arr[x+1] = t
change = true
}
}
l--
}

return arr
}

About Android 5 Service

About Android 5 Service

启动和生命周期

  • 启动方式
    • startService
      • 无限期运行
      • 生命周期
        • onCreate
        • onStartCommand
        • onDestory
    • bindService

      • onCreate
      • onBind
      • onUnbind
      • onDestory
  • 手动调用
    • startService
      • 单次
        • onCreate
        • onStartCommand
      • 多次
        • onCreate
        • onStartCommand
        • onStartCommand
    • stopService
      • onDestory
    • bindService
      • onCreate
      • onBind
    • unbindService
      • onUnbind
      • onDestory
  • 解绑绑定Service服务
    • unbindService() —> onUnbind(ture) —> bindService() —> onRebind()

Service 与 Thread

无相关,只是有点像。
Service运行与主线程,只要进程不消失则继续运行
Thread运行在其他线程,

IntentService

在IntentService的Oncreate中,开启一个新的线程,并绑定一个handler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

@Override
public void onCreate() {
super.onCreate()

HandlerThread thread = new Handler("IntenteService["+ mName+"]")
thread.start()

mServiceLooper = thread.getLooper()

mServiceHandler = new ServiceHandler(mServiceLooper);
}

public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent,startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;

msg.obj = intent;

mServiceHandler.sendMessage(msg)
}

ServiceHandler的源码

1
2
3
4
5
6
7
8
9
10
11
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper)
}

@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent) msg.obj);
stopSelf(msg.arg1);
}
}

Service 与Activity通信

  • onbind返回Ibinder对象
  • unbindService和bindService的时候参入ServiceConnection对象

Remote Service IPC

  • IPC
  • AIDL

参考
1
2
3

About Android 4 Handler

About Android 4 Handler

  • Handler
  • Message
  • MessageQueue
  • Looper
  • HandlerThread

Handler

handler 的使用方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//1 post postDelay
Handler.post / postDelay (new Runnable() {
@Override
void run() {
//todo
}
})

//2 sendMessage

创建handler
实现handlerMessage接口

handler.sendMessage(msg)

Activity finish时handler未执行完会引发Activity内存泄漏?

优化

  • 通过静态内部类+弱引用方式实现handler
  • 等等

HandlerThread

HandlerThread继承Thread.

run方法内进行Looper的初始化相关操作

Looper

  • Looper.prepare
    • 从TheadLocal中取得Looper对象,执行多次会抛出异常
1
2
3
4
5
6
7
8
9
10
11
12
13

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//...
public static void prepare() {
prepare(true);
}

private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only on lopper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
  • Looper.loop()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void loop() {
final Looper me = myLooper();
//..
final MessageQueue queue = me.mQueue;
//..
for(;;) {
Message msg = queue.next();
//..
msg.target.dispatchMessage(msg)
//ms.target 是一个handler对象
//Handler 在 enqueueMessage() 内为msg添加target
}
//..
msg.recycleUnchecked()
}

About Android 3 持久化存储

About Android 3 持久化存储

  • Android 持久化存储
    • Shared Preference
    • Internal Storage
    • External Storage
    • SQLite Database
    • Network Connection

Shared Preferences

  • 特点
  • 原理

SharedPreferences的特点

适合单线程,小批量数据存储和访问

SharedPreferences原理

通过维护一个xml文件存储

多进程使用

不推荐使用

Internal Storage & External Storage

sdcard数据读写需要注意权限

数据库

  • sqlite
  • greenDAO
  • realm

常问:
数据库的操作是线程安全的吗?
太久没操作了

网络

序列化支持

  • 序列化
    • Parceable
      • 高效 Android 特有 复杂
    • Serial
      • io操作多 性能影响大

参考
1
数据库的设计:深入理解 Realm 的多线程处理机制

About Android 2 进入Application

About Android 2 进入Application

上一篇总结(抄)了Android从开机到启动桌面的过程,接下来从Launcher展开。

  • 启动application过程
  • 启动Activity
  • activity启动模式

启动Application

在ActivityThread的main方法中创建了一个主线程Looper并开启循环。
在Looper.loop()之前,会创建一个ActivityThread对象并attach(false)

在attach内部,会获取mgr.attachApplication(mAppThread).
mgr是一个IBinder引用,其实也是ActivityManagerService的引用

在attachApplication内会调用attachApplicationLocked(thread, callingPid)
然后thread.bindApplication(…)
后续会在ActivityStackSupervisor.attachApplicaiontLocked(app)
=> realStartActiviityLocked()

bindApplication最终会sendMessage到一个handler

该handler内对bindapplication做出响应

  • 创建Application
    • ContextImpl.createAppContext(activityThread, this)
    • app = ..newApplicaiton(cl,appClass,appContext)
      • app.attach(context)
    • setOutterContext(app)
  • mInstrumenttation.callApplicationOnCreate(app)

启动Activity

startActivity通过Instrumentation来启动activity

  • startActivity
  • startActivityForResult
  • instrumentation.executeStartActivity
    • ActivityManager.getService().startActivity

ActivityManagerService中

  • getService()
  • startActivity()
  • startActivityAsUser()
  • ActivityStartController.obtainStarter.xxxx.execute()

ActivityStarter中

  • 拿到ActivityRecord
  • 判断启动模式
  • Application

activity启动模式

  • Android启动模式和场景
    • singleInstance 全局唯一
      • oncreate
      • onnewintent onrestart onstart
    • singleStack 已处于栈内 复用并弹出上层
    • singleTop 已处于栈内时复用
    • standard
1
2
3
4
5
一般会问一些简单的题,例如

栈[A,B,C]

用不同的模式启动A会发生什么变化

参考
1
2

About Android 1 从启动到桌面

about Android 1 启动到桌面

  • 启动系统
    • 开机键
      • 引导芯片加载BootLoader到内存,拉起Linux OS, 寻找init.rc启动init进程
      • init进程
        • 启动Zygote进程
          • 启动java虚拟机
          • jni
          • 找到ZygoteInit类调用main
      • Zygote
        • 通过fork复制进程来创建应用进程和SystemServer进程
        • 启动时会创建DVM获ART
        • main
          • 创建socket
          • 预加载
          • 启动SystemServer
          • 等待AMS请求
      • SystemServer
        • 用于创建系统服务
          • AMS
          • WMS
          • PMS
        • PathClassLoader
        • 启动binder线程池

AMS

  • SystemServer
    • 获取Context
      • 构造ActivityThread
        • thead.attach(true)
          • if (true)
            • setAppName system_process
            • 从systemContext的packageInfo获取对象然后makeApplication
            • application.onCreate
      • 取得ActivityThread实例的context
  • 启动各种Service
    • 启动AMS
      • newInstance ActivityManagerService
      • add service对象到mServices
      • service.onStart()
  • AMS onStart()
    • start()
    • systemReady()
      • startHomeActivityLocked
        • getHomeIntent
        • ActivityStartController.startHomeActivity
          • ActivityStarter
            • execute
      • 进行操作
      • mStackSupervisor.resumeTopActivitiesLocked()

HomeActivity

在 systemReady 后启动HomeActivity

  • 怎么启动HomeActivity
    • 通过flag 常量 XXXX_HOME

启动Activity

  • 启动组件的方式
    • 显式启动
    • 隐式启动
  • Activity 启动模式

启动方式

显式启动

1
2
3
4
5
6
7
Intent intent = new Intent(AActivity.this,BActivity.class);
startActivity(intent);

Intent intent2 = new Intent();
intent2.setClassName("","");
startActivity(intent2);
//需要在对应AndroidManifest.xml内设置exported = true

隐式启动
即通过IntentFilter寻找

  • action
  • category

AMS收到StartActivity请求,匹配组件action,检查category,检查数据,启动组件并传入数据

HomeActivity做了什么

也就是Launcher做了什么

  • 获取已安装的apk信息
  • 显式已安装的apk信息并响应点击事件

参考:
1
2
3

提起ES6-我知道什么

提起ES6-我知道什么

首先,es6是什么呢?

ECMAScript 6.0(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。它的目标,是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

let var const

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
let ii = 4
let ii = 3
// error

var a = 4
var a = 3
//ok

const o = {}

o.a = 'b'
//ok

const v = 0
v =1
//error



for(let i = 0 ; i < 3; i++){
setTimeout(() => {
console.info(i, new Date().getTime())
},1000)
}

for(var i = 0 ; i < 3; i++){
setTimeout(() => {
console.info(i, new Date().getTime())
},1000)
}

Promise

async await

symbol

CSS相关

CSS相关

CSS其实用得不深, 常规布局就已经满足了我接触到的需求了

  • 盒模型
    • content border padding margin
  • box-sizing

  • 选择器
    • id
    • 标签
    • 相邻选择器
      • xxx
    • 子选择器
    • 后代选择器
    • 通配符
    • 属性选择器
      • xxx
    • 伪类选择器
  • 可继承属性
    • font-szie
    • font-family
    • color
  • css3新增伪类
  • 居中div
    • margin auto
    • 浮动元素
      • xxx
    • 绝对定位
      • xxx

        flex-direction: column;
        justify-content: center;
        align-items: center;
  • © 2020 Kfdykme
  • Powered by Hexo Theme Ayer
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信