总结
【Android 详细知识点思维脑图(技能树)】
其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。
这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司19年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。
由于篇幅有限,这里以图片的形式给大家展示一小部分。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
前言
我们都知道Flutter开发的app是可以同时在iOS和Android系统上运行的。显然Flutter需要有和Native通信的能力。比如说,你的Flutter app要显示手机的电量,而电量只能通过平台的系统Api获取。这时就需要有个机制使得Flutter可以通过某种方式来调用这个系统Api并且获得返回值。那么Flutter是如何做到的呢?答案是Platform Channels。
Platform Channels
先来看张图
上图来自Flutter官网,表明了Platform Channels的架构示意图。有细心的同学就要问了,你不是说Flutter和Native通信是通过Platform Channels吗?怎么架构图里面连接他们的是MethodChannel? 其实呢,MethodChannel是Platform Channels中的一种,顾名思义,MethodChannel用起来应该和方法调用差不多。那么还有别的channel?有的,还有EventChannel,BasicMessageChannel等。如果你需要把数据从Native平台发送给Flutter,推荐你使用EventChannel。Flutter framework也是在用这些通道和Native通信,具体可以参考一下FlutterView.java
,在这里能看到Platform Channels的更多用法。
这里需要注意一点,为了保证UI的响应,通过Platform Channels传递的消息都是异步的。
在Platform Channels上传递的消息都是经过编码的,编码的方式也有几种,默认的是用StandardMethodCodec
。其他的还有BinaryCodec
(二进制的编码,其实啥也没干,直接把入参给返回了), JSONMessageCodec
(JSON格式的编码),StringCodec
(String格式的编码)。这些编解码器允许的只能是以下这些类型:
所以如果你想把你自己定义的com.yourmodule.YourObject
类型的一个实例直接扔给Platform Channels传送是不行滴。
Platform Channels 怎么用
前面大概介绍了Flutter和Native通信的Platform Channels。那么我们用具体的例子来说说Platform Channels的使用。这里使用Flutter官方出的获取手机电量的Demo。相关源代码可以从Github下载。
Platform Channels是连接Flutter和Native的通道,那么我们如果要建立这样的通道显然要在两端都要写代码喽。
MethodChannel
先看Native 端怎么写
MethodChannel-Native 端
为简单起见,本例的Android端代码都直接写在MainActivity
中。Android平台下获取电量是通过调用BatteryManager来获取的,所以我们先在MainActivity
中增加一个获取电量的函数:
private int getBatteryLevel() {
int batteryLevel = -1;
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);
batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
} else {
Intent intent = new ContextWrapper(getApplicationContext()).
registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
batteryLevel = (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /
intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
}
return batteryLevel;
}
这个函数需要能被Flutter app调用,此时就需要通过MethodChannel
来建立这个通道了。 首先在MainActivity
的onCreate
函数中加入以下代码来新建一个MethodChannel
public class MainActivity extends FlutterActivity {
//channel的名称,由于app中可能会有多个channel,这个名称需要在app内是唯一的。
private static final String CHANNEL = “samples.flutter.io/battery”;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
// 直接 new MethodChannel,然后设置一个Callback来处理Flutter端调用
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, Result result) {
// 在这个回调里处理从Flutter来的调用
}
});
}
}
注意,每个
MethodChannel
需要有唯一的字符串作为标识,用以互相区分,这个名称建议使用package.module...
这样的模式来命名。因为所有的MethodChannel
都是保存在以通道名为Key的Map中。所以你要是设了两个名字一样的channel,只有后设置的那个会生效。
接下来我们来填充onMethodCall
。
@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals(“getBatteryLevel”)) {
int batteryLevel = getBatteryLevel();
if (batteryLevel != -1) {
result.success(batteryLevel);
} else {
result.error(“UNAVAILABLE”, “Battery level not available.”, null);
}
} else {
result.notImplemented();
}
}
onMethodCall
有两个入参,MethodCall
里包含要调用的方法名称和参数。Result
是给Flutter的返回值。方法名是两端协商好的。通过if语句判断MethodCall.method
来区分不同的方法,在我们的例子里面我们只会处理名为“getBatteryLevel”的调用。在调用本地方法获取到电量以后通过result.success(batteryLevel)
调用把电量值返回给Flutter。 Native端的代码就完成了。是不是很简单?
MethodChannel-Flutter 端
接下来看Flutter端代码怎么写: 首先在 State
中创建Flutter端的MethodChannel
import ‘dart:async’;
import ‘package:flutter/material.dart’;
import ‘package:flutter/services.dart’;
…
class _MyHomePageState extends State {
static const platform = const MethodChannel(‘samples.flutter.io/battery’);
// Get battery level.
}
channel的名称要和Native端的一致。 然后是通过MethodChannel调用的代码
String _batteryLevel = ‘Unknown battery level.’;
Future _getBatteryLevel() async {
String batteryLevel;
try {
final int result = await platform.invokeMethod(‘getBatteryLevel’);
batteryLevel = ‘Battery level at KaTeX parse error: Expected 'EOF', got '}' at position 14: result % .'; }̲ on PlatformExc…{e.message}’.";
}
setState(() {
_batteryLevel = batteryLevel;
});
}
final int result = await platform.invokeMethod('getBatteryLevel');
这行代码就是通过通道来调用Native方法了。注意这里的await
关键字。前面我们说过MethodChannel是异步的,所以这里必须要使用await
关键字。 在上面Native代码中我们把获取到的电量通过result.success(batteryLevel);
返回给Flutter。这里await
表达式执行完成以后电量就直接赋值给result
变量了。剩下的就是怎么展示的问题了,就不再细说了,具体可以去看代码。
需要注意的是,这里我们只介绍了从Flutter调用Native方法,其实通过MethodChannel
,Native也能调用Flutter的方法,这是一个双向的通道。
举个例子,我们想从Native端请求Flutter端的一个getName
方法获取一个字符串。在Flutter端你需要给MethodChannel
设置一个MethodCallHandler
_channel.setMethodCallHandler(platformCallHandler);
Future platformCallHandler(MethodCall call) async {
switch (call.method) {
case “getName”:
return “Hello from Flutter”;
break;
}
}
在Native端,只需要让对应的的channel调用invokeMethod
就行了
channel.invokeMethod(“getName”, null, new MethodChannel.Result() {
@Override
public void success(Object o) {
// 这里就会输出 “Hello from Flutter”
Log.i(“debug”, o.toString());
}
@Override
更多Android高级工程师进阶学习资料
进阶学习视频
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!