这里记录一下在Android中面试遇到的一些回答的不是很好的问题
Flutter为Android提供了一个FlutterActivity,可以通过startActivity的方式跳转到Flutter界面
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
}
Flutter的入口是main.dart这个文件。
通过写插件的方式可以实现与原生界面交互,主要是通过MethodChannel
,在插件写完之后要注册插件才能正常使用插件的功能
可以参考一下这个地址 一个简单的插件
可以参照一下dart的官方网站 dart官网对线程的描述
What’s the point?
可以发现dart是单线程编程的语言,任何可以阻塞线程执行的代码都会导致程序卡死。
Dart使用Future对象表示异步操作,也可以使用async和await来表示异步
这里使用一个官方的例子来说明一下,可能会更加清楚
import 'dart:html';
import 'dart:async';
Future printDailyNewsDigest() async {
String news = await gatherNewsReports();
print(news);
}
main() {
printDailyNewsDigest();
printWinningLotteryNumbers();
printWeatherForecast();
printBaseballScore();
}
printWinningLotteryNumbers() {
print('Winning lotto numbers: [23, 63, 87, 26, 2]');
}
printWeatherForecast() {
print('Tomorrow\'s forecast: 70F, sunny.');
}
printBaseballScore() {
print('Baseball score: Red Sox 10, Yankees 0');
}
Future gatherNewsReports() async {
String path =
'https://www.dartlang.org/f/dailyNewsDigest.txt';
return (await HttpRequest.getString(path));
}
第一步:app 开始执行
第二步: main方法调用了printDailyNewsDigest()
方法,这个方法被标记为async
,在其他代码执行之前,会返回一个Future对象
第三步:接着执行剩余的方法,由于他们是同步的,所以继续下一个打印功能之前,每个功能都会完全执行。举个例子,在打印天气预报之前打印中奖彩票的号码
第四步: printDailyNewsDigest()
方法被执行
第五步: 接着会执行await的方法gatherNewsReports
,程序会暂停,等待Future返回gatherNewsReports
的执行结果
第六步: 一旦Future完成执行,printDailyNewsDigest()
中的方法会继续执行,打印消息
第七步: 当printDailyNewsDigest()
方法执行完毕,Future将返回完成状态,接着app就会退出
Dart是Event-Looper以及Event-Queue的模型,所有的事件都是通过EventLooper的依次执行。
Dart的Loop就是
可以发现,用户的每一次操作都会产生一个Event
这里是不是可以联想到Handler,Handler中也有一个Looper,通过Looper不断循环,去处理MessageQueue中的消息。这里就引出了一个问题,为什么Handler中的Looper是一个死循环,但是不会导致程序ANR呢?那现在又有一个问题,大家都写过Java程序,当main方法中的代码执行完毕之后,便会退出程序。但是Android中的代码执行完毕之后,并没有退出app,而是等待。这里就是Android中Handler的功劳,通过不断的Looper,来保证主线程中的代码不会执行完,如果执行完毕,那么这个线程就会退出。而UI的所有操作,比如屏幕刷新,各种点击事件,都会通过Handler来分发。所以ANR的原因是阻塞了Handler执行下一个Event,这个才是导致ANR的罪魁祸首。还有一点,在没有消息的时候回通过linux的epoll机制来阻塞,这个是另外一方面的知识,这里就不描述了。
回到Dart的线程机制。在Dart中,如果一个Dart方法开始执行,便无法打断,Dart通过
isolate起到类似线程的作用,在main方法执行完毕之后,Main isolate便开始处理一个个的Event。这一点是不是和Android的Handler机制很像呢?
在Dart中存在两个EventQueue,一个是EventQueue,还有一个是MicrotaskQueue
Microtask Queue存在的意义是:希望通过这个Queue来处理稍晚一些的事情,但是在下一个消息到来之前需要处理完的事情。
Event-Looper挑选Task的执行顺序为:
当Event Looper正在处理Microtask Queue中的Event时候,Event Queue中的Event就停止了处理了,此时App不能绘制任何图形,不能处理任何鼠标点击,不能处理文件IO等等
Dart中只能知道Event处理的先后顺序,不能知道某一个Event执行的具体时间点。
当有代码可以在后续任务执行的时候,有两种方式,通过dart:async这个Lib中的API即可:
当使用EventQueue时,需要考虑清楚,尽量避免microtask queue过于庞大,否则会阻塞其他事件的处理
使用Future
new Future((){
// doing something
});
当然可以使用then的方式来拆解任务
void main(){
new Future(() => futureTask) // 异步任务的函数
.then((m) => "futueTask execute result:$m") // 任务执行完后的子任务
.then((m) => m.length) // 其中m为上个任务执行完后的返回的结果
.then((m) => printLength(m))
.whenComplete(() => whenTaskCompelete); // 当所有任务完成后的回调函数
}
int futureTask() {
return 21;
}
void printLength(int length) {
print("Text Length:$length");
}
void whenTaskCompelete() {
print("Task Complete");
}
使用scheduleMicrotask
async.scheduleMicrotask(() => microtask());
void microtask(){
// doing something
}
大家可以参考参考的地址1 参考地址2
这个问题问的我有点蒙蔽,大半年没有用dart和Flutter了。
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
可以发现,dart创建对象的方式类似于kotlin,可以使用new关键字,也可以不使用new关键字
个人的回答是,通过注解和apt的方式自动生成一些代码,包括sql等,这样可以节省简化sql的一些操作,不用自己手动写sql。但是面试官又问了一个问题?
加密
Room不支持SqlCipher加密,不过后续SqlCipher应该会提供针对Room的加密方式
GreenDao集成了SqlCipher加密。
效率
greendao的效率会高一些,但是Room是google的亲儿子,支持方面后期应该会好一些
livedata
Room支持livedata,greendao需要自己手写
sql的三种写入操作
int sqlite3_exec(sqlite3*, const char *sql, int (*callback)(void*,int,char**,char**), void *, char **errmsg)
中速——显式开启事务
所谓”事务“就是指一组SQL命令,这些命令要么一起执行,要么都不被执行。通过事务的方式,这样可以提高效率
高速——写同步(synchronous)
synchronous选项有三种可选状态,分别是full、normal、off
full写入速度最慢,但保证数据是安全的,不受断电、系统崩溃等影响,而off可以加速数据库的一些操作,但如果系统崩溃或断电,则数据库可能会损毁
极速——执行准备
虽然写同步设为off后,速度又有小幅提升,但是仍然较慢。我又一次踏上了寻找提高SQLite插入效率方法的道路上。终于,我发现,SQLite执行SQL语句的时候,有两种方式:一种是使用前文提到的函数sqlite3_exec(),该函数直接调用包含SQL语句的字符串;另一种方法就是“执行准备”(类似于存储过程)操作,即先将SQL语句编译好,然后再一步一步(或一行一行)地执行。如果采用前者的话,就算开起了事务,SQLite仍然要对循环中每一句SQL语句进行“词法分析”和“语法分析”,这对于同时插入大量数据的操作来说,简直就是浪费时间。因此,要进一步提高插入效率的话,就应该使用后者。
综上所述啊,SQLite插入数据效率最快的方式就是:事务+关闭写同步+执行准备(存储过程),如果对数据库安全性有要求的话,就开启写同步。
详细的可以看一下这篇文章。我这里只是从面试的角度简单的收集了一下。
参考地址
可以看一下
参考地址
携程
这个自己看一下
这个自己看一下