安卓面试问题记录

目录

  • 1. JNI和NDK
    • 1.谈谈你对JNI和NDK的理解
    • 2.简要的JNI调用过程:
  • 2. 线程、同步、异步
    • 1.Java创建线程的方式有几种?start()方法和 run()方法的区别
    • 2.Handler 机制和原理
    • 3.为什么在子线程中创建Handler会抛异常?
    • 4.Android中的ANR的解决方法
    • 5.intentservice有什么优点?
    • 6.okhttp异步请求流程
    • 7.Okhttp的同步请求
  • 3. UI
    • 1.谈谈你对 Bitmap 的理解,什么时候应该手动调用 bitmaprecycle():
    • 2.Android布局的五个常见类型:
  • 4. 组件
    • **1.Android四大组件是指Activity、Service、BroadcastReceiver和ContentProvider**。
  • 5. 四大组件详解
      • 1. **activity**
      • **2 .service**
      • **3 .content provider**
      • **4 .broadcast receiver**
    • 如果后台的activity由于某种原因被系统回收了,如何在被系统回收之前保存当前状态?
  • 6. 机制
    • 1.view的事件分发机制
  • 7. 性能
    • 1.GC是什么,为什么要有GC
  • 8. 数据库
    • 1.SQLite 数据库升级——新增字段处理

1. JNI和NDK

1.谈谈你对JNI和NDK的理解

答:JNI(Java Native Interface)是Java提供的一种机制,用于实现Java与其他编程语言(如C、C++)之间的交互。它允许Java代码调用本地代码(Native Code)并与其进行数据交换。
NDK(Native Development Kit)是Android提供的一个工具集,用于在Android应用中使用本地代码。它包含了一系列的工具和库,可以将C、C++代码编译成与特定平台相关的本地库文件(例如.so文件),然后通过JNI将这些本地库文件嵌入到Android应用中。
JNI和NDK的关系是,JNI提供了Java与本地代码交互的机制,而NDK则提供了将本地代码集成到Android应用中的工具和库。通过JNI和NDK,开发者可以在Android应用中使用C、C++等本地语言编写高性能、底层的功能模块,比如图像处理、音频处理、加密算法等。
使用JNI和NDK可以带来以下优势:
1.性能优化:某些计算密集型任务,使用本地代码可以提高执行效率。
2.跨平台开发:通过使用本地代码,可以在不同平台上共享代码和库。
3.重用现有代码:如果已经有了C、C++等语言的现有代码,可以通过JNI和NDK将其集成到Android应用中,避免重复开发。
需要注意的是,在使用JNI和NDK时,需要谨慎处理内存管理、类型转换和异常处理等问题,以确保代码的正确性和稳定性。

2.简要的JNI调用过程:

1、**编写本地代码:**首先,需要编写包含所需功能的本地代码,通常是用C或C++编写。这些本地代码将被编译成共享库(.so文件)。
2、创建JNI接口:在Java代码中,需要声明与本地代码对应的JNI接口。这些接口方法将与本地代码中的函数进行绑定,以便在Java中调用。
3、生成头文件:使用Java Development Kit(JDK)中的工具javah,生成包含JNI接口方法定义的头文件。
4、实现JNI接口:在本地代码中,需要实现JNI接口中声明的方法。这些方法将提供与Java代码之间的桥梁,使得Java可以调用本地代码。
5、编译本地代码:使用C/C++编译器将本地代码编译成共享库(.so文件)。
6、将共享库加载到应用程序:在Android应用程序中,可以使用System.loadLibrary()方法加载共享库。
7、调用JNI方法:在Java代码中,通过调用JNI接口中声明的方法来调用本地代码。可以使用native关键字标记这些方法。
8、运行应用程序:在应用程序运行时,当Java代码调用JNI方法时,将触发与本地代码的交互,完成相应的功能操作。
需要注意的是,JNI调用涉及到本地代码的编写和编译,因此需要对C/C++有一定的了解。此外,在JNI调用过程中,需要注意内存管理和数据类型转换等问题,以确保安全性和正确性。
JNI调用过程包括编写本地代码、创建JNI接口、生成头文件、实现JNI接口、编译本地代码、加载共享库、调用JNI方法等步骤,通过这些步骤可以实现Java代码与本地代码之间的交互

2. 线程、同步、异步

1.Java创建线程的方式有几种?start()方法和 run()方法的区别

答:在Java中,有两种主要的方式可以创建线程
1.继承Thread类:通过继承Thread类并重写其run()方法来创建线程。首先,创建一个继承自Thread的子类,并在子类中实现run()方法来定义线程的具体逻辑。然后,通过创建子类的实例对象,并调用其start()方法来启动线程。
2.实现Runnable接口:通过实现Runnable接口来创建线程。首先,创建一个实现了Runnable接口的类,并在该类中实现run()方法。然后,创建Thread类的实例对象,将实现了Runnable接口的类的实例作为参数传递给Thread的构造函数。最后,调用Thread对象的start()方法来启动线程。

区别

  • 使用继承Thread类的方式,线程的逻辑直接写在子类中的run()方法中,但这样会限制了子类的继承关系。
  • 使用实现Runnable接口的方式,线程的逻辑在实现了Runnable接口的类中定义,可以更灵活地共享代码和资源,并且避免了单继承的限制。

关于start()方法和run()方法的区别

  • start()方法用于启动线程并异步执行线程的逻辑。调用start()方法后,系统会为线程分配资源并调用线程的run()方法。
  • run()方法是线程的入口点,可以将线程的具体逻辑在run()方法中实现。但直接调用run()方法并不会启动新的线程,而是在当前线程中同步执行run()方法的代码块。

总结来说,Java创建线程的方式有继承Thread类和实现Runnable接口。start()方法用于启动线程并异步执行线程的逻辑,而run()方法是线程的入口点,在调用start()方法后由系统自动调用

2.Handler 机制和原理

Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分在消息队列中逐一将消息取出,然后对消息进行处理,也就是发送消息和接收消息不是同步的处理。

基础概念

  • UI线程
    主线程 ActivityThread ,主线程也是Ui线程,应用启动的时候会启动一个ui线程
  • Handler
    负责发送消息和处理消息。
  • Looper
    负责消息循环,循环取出 MessageQueue 里面的 Message,并交给相应的 Handler 进行处理。
  • MessageQueue
    消息队列,用来存放通过Hangdler 发送的消息,按照先进先出的顺序取出消息,内部使用的是单链表结构(

你可能感兴趣的:(android,android,studio)