应用基本期末

  1. 以下哪些属于Java的三大特性:
    a. 抽象 b. 封装 c. 面向对象 d. 分布式 e. 安全性 f. 平台独立

  2. 以下哪些是Object的公用方法?
    a. equals() b. getContext() c. notify() d. toString() e. clone()

  3. int和integer两个谁更占用内存?
    a. Int b. integer

  4. “a == b” 和 “a.equals(b)” 是否有区别?
    a. Yes b. No

  5. 以下关于ArrayList的说法正确的是?
    a. 有序 b. 无序 c. 元素能重复 d. 元素不能重复 e. 查询快 f. 增删快

  1. 目前市面上最新Android版本: Android 12 ,对应SDK版本为: API Level 31

  2. Android四大组件(英语):
    Activity
    Service
    Broadcast Receiver
    Content Provider

  3. Android 广播的分类:
    Standard Broadcasts(标准广播)、Ordered Broadcasts(有序广播)、Sticky Broadcasts(粘性广播)、Local Broadcast(本地广播

  4. 请列举Android进程间通讯的几种方式:
    Binder(AIDL):Android 的主要进程间通讯机制,基于内核的 Binder 驱动进行跨进程通信。
    Messenger:一种轻量级的基于 Handler 和 Message 的 IPC 方式,通常用于一个进程向另一个进程发送消息。
    Content Provider:允许不同应用间共享数据的组件,可以通过 ContentResolver 来查询和操作不同应用的数据库。
    BroadcastReceiver:通过广播机制,应用可以接收系统或其他应用发出的广播信息。
    Intent:通过 Intent 发送数据进行跨进程通信,例如启动 Activity 或者 Service。
    SharedPreferences:虽然不常用于进程间通信,但多个进程也可以通过共享的 SharedPreferences 文件来进行简单的数据交换。

  5. Activity完整的生命周期:
    onCreate():Activity 被首次创建时调用,通常在此方法中执行初始化操作,如设置布局、初始化数据等。
    onStart():Activity 由不可见变为可见状态时调用,但还未与用户交互。
    onResume():Activity 开始与用户交互,此时 Activity 位于前台并处于可交互状态。
    onPause():Activity 失去焦点,但仍然部分可见(如另一个 Activity 以对话框形式弹出时)。
    onStop():Activity 对用户完全不可见时调用,可能正在进入后台。
    onRestart():Activity 由不可见状态重新变为可见时调用,通常紧接在 onStop() 之后。
    onDestroy():Activity 被销毁前调用,用于释放资源或做一些清理工作。
    简化的生命周期流程图:

onCreate()onStart()onResume()onPause()onStop()onDestroy()										      																	      
  1. Fragment的完整生命周期:
    onAttach(Context context):
    当 Fragment 与 Activity 关联时调用。此时可以获取到宿主 Activity 的上下文。
    onCreate(Bundle savedInstanceState):在 Fragment 被创建时调用。此时可以进行初始化操作,但还不能访问视图。
    onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState):

负责创建 Fragment 的视图,返回一个 View 对象。可以在此处加载布局文件。
onViewCreated(View view, Bundle savedInstanceState):

在视图创建后立即调用,适合在此处进行视图的设置和初始化。
onActivityCreated(Bundle savedInstanceState):

当 Activity 的 onCreate() 方法返回后调用,此时可以访问 Activity 的其他组件。
onStart():

Fragment 变得对用户可见时调用。适合在此处启动与 UI 相关的操作。
onResume():

Fragment 与用户交互的状态,此时 Fragment 可见并处于前台。
onPause():

Fragment 不再与用户交互,此时可以在此处保存数据或停止动画等操作。
onStop():

Fragment 不再可见,适合在此处释放资源或保存状态。
onDestroyView():

在 Fragment 的视图被销毁时调用,可以在此处进行视图的清理。
onDestroy():

在 Fragment 被销毁时调用,适合在此处进行资源释放。
onDetach():

当 Fragment 从 Activity 分离时调用,适合在此处清理与 Activity 相关的引用。

  1. Activity的启动方式:
  2. FLAG_ACTIVITY_NEW_TASK 和 FLAG_ACTIVITY_CLEAR_TOP分别有什
    么作用:

简答

对一个应用进行性能优化是一个系统性过程,通常可以从以下几个主要方面入手:

  1. 界面和用户体验优化
    减少布局复杂度:尽量减少嵌套布局的层级,使用约束布局(ConstraintLayout)来代替复杂的多层次布局。
    优化图像加载:使用适当的图片格式和分辨率,避免使用过大的图片。使用图像缓存库(如Glide或Picasso)来优化图像加载和缓存。
    减少主线程阻塞:避免在主线程进行耗时操作,使用异步处理(如AsyncTask、Handler、RxJava、Coroutines)来处理耗时任务。
    视图重用:在列表或网格布局中,使用视图重用机制(如RecyclerView)来避免频繁创建和销毁视图。
  2. 内存管理
    避免内存泄漏:检查是否存在未释放的资源,如未关闭的Cursor、流、数据库连接,或由于Activity、Fragment的持有导致的内存泄漏。使用工具如Android Profiler、LeakCanary进行内存泄漏检测。
    对象池和复用:对于经常创建和销毁的对象,考虑使用对象池技术来降低GC频率。
    减少Bitmap内存消耗:尽量使用压缩后的图片(缩略图)和采样图片(通过inSampleSize选项)。尽量避免在内存中加载全分辨率的Bitmap。
  3. 电池和能耗优化
    减少不必要的唤醒:避免频繁或不必要地唤醒设备,尽量合并网络请求和后台任务的调度。
    优化后台服务:确保后台服务和任务在不使用时及时停止,避免长时间占用CPU资源。
    使用JobScheduler或WorkManager:合并后台任务,尽量在设备处于空闲状态时执行。
  4. 网络和数据优化
    减少网络请求:合并多个网络请求为一个,或使用批量请求减少网络传输。使用缓存(HTTP缓存、数据缓存)来减少重复的网络访问。
    数据压缩:对于传输的数据,使用适当的压缩技术(如GZIP、Protobuf)来减少数据传输量。
    分页加载:对于大量数据(如分页的列表),尽量使用分页加载技术,避免一次加载过多的数据。
  5. 启动性能优化
    减少启动时间:避免在应用启动时进行复杂的初始化操作或加载大量数据。将非关键任务推迟到启动后进行(如使用Handler.postDelayed())。
    优化应用入口:尽量减少应用启动时的动画和图形处理,或者使用简化版的启动动画。
  6. 使用工具监测和分析
    Profiling:使用Android Profiler、Systrace、StrictMode等工具进行性能分析,识别性能瓶颈。
    Benchmarking:编写基准测试用例(如Jetpack Benchmark库),持续监控应用的关键性能指标(如响应时间、内存占用、启动时间)。
    通过从以上几个主要方面入手进行优化,可以有效提升应用的性能,改善用户体验,降低资源消耗。优化是一个持续的过程,通常需要根据应用的具体场景和用户反馈不断调整和改进。

Activity的显式启动和隐式启动有什么区别?显式广播和隐式广播又有什么区别?

1. Activity 的显式启动和隐式启动
显式启动 (Explicit Intent)
显式启动是指通过 明确指定 要启动的目标 Activity 类名来启动的方式。

特点:

通过目标 Activity 的类名(ComponentName)启动。
启动目标非常明确,直接指向某个特定的 Activity。
常用于应用内部的 Activity 之间的跳转。
使用示例:

Intent intent = new Intent(this, TargetActivity.class);
startActivity(intent);

上述代码中,TargetActivity.class 明确指定了要启动的目标 Activity。

隐式启动 (Implicit Intent)
隐式启动是通过 不直接指定目标 Activity,而是通过 Intent Filter(意图过滤器) 匹配的方式来启动合适的 Activity。
特点:

不指定具体的 Activity,而是通过 Action、Category、Data 等来匹配符合条件的 Activity。
可能会触发其他应用程序中的 Activity,只要匹配了所定义的 Intent Filter。
适合在应用间进行交互或让系统选择合适的应用来处理某个任务。
使用示例:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://www.example.com"));
startActivity(intent);

上述代码会启动任何符合 Intent.ACTION_VIEW 处理网页的 Activity,比如浏览器应用,而不限定为某个特定的 Activity。

  1. 显式广播和隐式广播
    显式广播 (Explicit Broadcast)
    显式广播是指通过明确指定 接收者(BroadcastReceiver)的类名 来发送广播,广播只能由这个特定的接收者处理。

特点:

通过接收者的 ComponentName(即类名)来明确指定要接收广播的 BroadcastReceiver
这种广播仅由指定的接收者处理,不会被其他 BroadcastReceiver 接收到。
常用于应用内部的广播发送与接收。
使用示例:

Intent intent = new Intent();
intent.setComponent(new ComponentName("com.example.app", "com.example.app.MyBroadcastReceiver"));
sendBroadcast(intent);

这里明确指定了 MyBroadcastReceiver 来接收该广播。

隐式广播 (Implicit Broadcast)
隐式广播是通过 Intent Filter 匹配接收者来发送广播的方式,系统会广播给所有符合条件的接收者。

特点:
通过广播的 Action、Category 等来匹配广播接收器(BroadcastReceiver)。
所有符合条件的接收者都可以接收到这条广播,适用于应用间或系统范围内的广播。
如一些系统广播(如网络状态变化、电量低等)通常是隐式广播。
使用示例:

Intent intent = new Intent(Intent.ACTION_BATTERY_LOW);
sendBroadcast(intent);

该广播将发送给所有注册了 ACTION_BATTERY_LOW 的接收者,不限定某一个。

Android 8.0 及之后的隐式广播限制
从 Android 8.0 (API Level 26) 开始,隐式广播受到了较大的限制。为了减少后台运行和提升设备性能,系统不再允许大部分应用在后台接收隐式广播,除非广播接收器是动态注册的或者广播属于特定的系统广播(例如 BOOT_COMPLETED 等)。
总结

类型 显式启动/广播 隐式启动/广播
通过明确指定 Activity 类名启动。仅启动特定的 Activity。 通过 Intent 匹配 Intent Filter 启动,系统决定启动哪个 Activity。
通过明确指定 BroadcastReceiver 类名发送广播。仅特定接收者接收。 通过 Intent Filter 匹配广播接收器,多个接收者可以同时接收广播。
应用内部的通信或需要精准控制接收者的情况。 系统级广播、应用间通信或需要动态决定接收者的情况。
限制 无限制。隐式广播在后台运行受到限制。

在实际开发中,使用显式或隐式的方式取决于你的使用场景。

请简述自定义View开发分为那些方式?流程有什么区别?

自定义 View 开发是一项重要的技能,它允许开发人员创建具有自定义外观和行为的视图。自定义 View 的开发主要分为以下几种方式,每种方式有不同的适用场景和开发流程:

  1. 继承现有控件进行定制化
    概念:通过继承现有的 View(如 TextView, Button, ImageView 等)并对其进行定制。
  2. 完全自定义View(继承View或ViewGroup)
    概念:从基础类 View 或 ViewGroup 继承,完全自定义控件的外观和行为。
  3. 组合控件(Custom Compound View)
    概念:通过组合多个现有控件,构建一个复合控件(Compound View),也就是将多个已有的 View 组合在一起,形成一个自定义的组件。
  4. 流程区别总结
    继承现有控件:开发较为简单,适合在已有控件的基础上进行修改和扩展,重用性较强。
    完全自定义 View:实现难度较高,适用于从零开始实现新的控件,控制力最大,但也需要更全面的 View 绘制和测量知识。
    组合控件:通过组合现有控件,适合构建较为复杂的 UI 组件,开发难度居中,但灵活性稍逊于完全自定义 View。

未知长度的单链表,如何快速找到链表中间位置?

可以使用经典的快慢指针法(也叫“龟兔赛跑”算法)来找到链表的中间位置。这是一种简单且高效的算法,其时间复杂度为 O(n),并且只需要 O(1) 的空间。
具体步骤如下:
定义两个指针:
一个慢指针(slow),每次向前移动一个节点。
一个快指针(fast),每次向前移动两个节点。
同时移动这两个指针:

当快指针到达链表末尾时,慢指针刚好处于链表的中间节点。
详细过程:

慢指针从链表的头部开始,每次向前走一步。
快指针从链表的头部开始,每次向前走两步。
当快指针走到链表的末尾时,慢指针会正好位于链表的中间节点。
代码实现(以 C++ 为例):

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
};

ListNode* findMiddle(ListNode* head) {
    if (head == nullptr) return nullptr;  // 如果链表为空,返回空指针
    
    ListNode* slow = head;
    ListNode* fast = head;
    
    // 当快指针到达链表末尾或其下一个节点为 null 时,慢指针正好处于中间
    while (fast != nullptr && fast->next != nullptr) {
        slow = slow->next;
        fast = fast->next->next;
    }
    
    return slow;  // 慢指针指向链表的中间节点
}

解释:
如果链表长度为奇数,则当快指针走到最后一个节点时,慢指针会停在正中间节点上。
如果链表长度为偶数,则当快指针走到 null 时,慢指针会指向靠近中间的前一个节点(如果需要中间两个节点中的后一个,可以根据具体需求调整)。
优点:
时间复杂度为 O(n):只需要遍历链表一次。
空间复杂度为 O(1):只使用了两个额外的指针,不需要额外的空间。

逻辑

在漆黑的夜里,四人过桥一共只带了一只手电筒,而桥窄得只够让两个人同时通过。如果各自单独过桥的话,四人所需要的时间分别是1,2,5,10分钟;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。
1,如果四人都过河,累计最少的时间是几分钟?请描述每个步骤;
2,如果是N个人过桥,每人需要的时间是t[i],过桥规则不变,请列出算式,计算所有人过桥所用的最短时间T。

1. 四人过桥的最少时间
四个人分别需要 1、2、5 和 10 分钟过桥,手电筒必须被带回,以确保所有人都能通过桥。

要确保时间最短的策略是采用最快的人带手电筒来返回,而让时间最长的两个人一起过桥。具体步骤如下:

我们用 A、B、C、D 来表示这四个人,他们需要的时间分别是 A = 1 分钟,B = 2 分钟,C = 5 分钟,D = 10 分钟。
策略:最快的人尽可能多地带手电筒返回,以节省整体时间。
步骤:

A 和 B 先一起过桥,耗时 2 分钟(因为 B 慢,所以耗时是 B 的时间)。
A 返回,耗时 1 分钟。
C 和 D 一起过桥,耗时 10 分钟(因为 D 慢,所以耗时是 D 的时间)。
B 返回,耗时 2 分钟。
A 和 B 再次一起过桥,耗时 2 分钟。
总时间 = 2(A 和 B 过桥) + 1(A 返回) + 10(C 和 D 过桥) + 2(B 返回) + 2(A 和 B 再次过桥) = 17 分钟。

2. N 个人过桥最短时间的计算
设有 N 个人过桥,每个人过桥所需的时间为 t[i],并且遵循同样的规则:每次只能两个人带手电筒过桥,返回时也需要带手电筒。

为了计算最短时间,我们可以采用类似的策略,快的人尽可能多次返回,时间最长的人尽可能少次过桥。

算式:
我们可以将问题归纳为以下两种基本模式来计算最少时间:

模式一:最慢的两个人(C 和 D)过桥,由最慢的返回,接着最快的带手电筒返回。这种情况下,最快的人(A 和 B)先过桥,再返回其中一个快的带手电筒,然后最慢的两个人过桥,再由次慢的返回。

模式二:最快的两个人(A 和 B)多次来回,帮助其他人过桥。

通用的算法推导(贪心算法):
对于排序好的时间数组 t = [t1, t2, t3, …, tn](已从小到大排序),采用以下贪心策略:

t1 和 t2 先过桥,然后 t1 返回。
tn 和 tn-1 过桥,t2 返回。

重复上述步骤。
对于一个排列好的时间数组 t,最短时间 T 公式为:

T = min( (t[1] + 2 * t[2] + t[N]), (2 * t[1] + t[N-1] + t[N]) )

解释:
两个策略的比较:一个是让最快的人多次返回,一个是让次慢的人返回,比较这两者的最小值。
这个公式会依次递归处理,直到剩下两个或三个人过桥,然后应用该公式计算总时间。
总结
对于 4 个人过桥的情况,最短时间为 17 分钟。
对于 N 个人过桥的通用计算公式,可以使用贪心算法将所有人过桥时间最小化

你可能感兴趣的:(Android系统及应用,应用,物联网)