IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 2021跳槽必备,程序员如何解决中年危机 -> 正文阅读

[移动开发]2021跳槽必备,程序员如何解决中年危机

  1. PhoneWindow中有一个ViewRoot(View或ViewGroup),是最初始的根视图

  2. ViewRoot通过addView()将View添加到根视图上,实际上是将View交给了PhoneWindow处理

  3. View的事件监听是由WindowManagerService来接受消息,并且回调Activity函数

[](

)Fragment面试题


[](

)1、Fragment为什么被称为第五大组件

Fragment比Activity更节省内存,其切换模式也更加舒适,使用频率不低于四大组件,且有自己的生命周期,而且必须依附于Activity

[](

)2、Activity创建Fragment的方式

  • 静态创建

  • 动态创建

[](

)3、FragmentPageAdapter和FragmentPageStateAdapter的区别

  • FragmentPageAdapter在每次切换页面的的时候,是将Fragment进行分离,适合页面较少的Fragment使用以保存一些内存,对系统内存不会多大影响

  • FragmentPageStateAdapter在每次切换页面的时候,是将Fragment进行回收,适合页面较多的Fragment使用,这样就不会消耗更多的内存

[](

)4、Fragment生命周期

Fragment的生命周期方法主要有onAttach()、onCreate()、onCreateView()、onActivityCreated()、onstart()、onResume()、onPause()、onStop()、onDestroyView()、onDestroy()、onDetach()等11个方法。

  • 切换到该Fragment,分别执行onAttach()、onCreate()、onCreateView()、onActivityCreated()、onstart()、onResume()方法。

  • 锁屏,分别执行onPause()、onStop()方法。

  • 亮屏,分别执行onstart()、onResume()方法。

  • 覆盖,切换到其他Fragment,分别执行onPause()、onStop()、onDestroyView()方法。

  • 从其他Fragment回到之前Fragment,分别执行onCreateView()、onActivityCreated()、onstart()、onResume()方法。

[](

)5、Fragment的通信

  • Fragment调用Activity中的方法:getActivity

  • Activity调用Fragment中的方法:接口回调

  • Fragment调用Fragment中的方法:FragmentManager.findFragmentById

[](

)6、Fragment的replace、add、remove方法

  • replace:替代Fragment的栈顶页面

  • add:添加Fragment到栈顶页面

  • remove:移除Fragment栈顶页面

[](

)Service面试题


[](

)1、Service是什么

Service是四大组件之一,它可以在后台执行长时间运行操作而没有用户界面的应用组件

[](

)2、Service和Thread的区别

  • Service是安卓中系统的组件,它运行在独立进程的主线程中,不可以执行耗时操作。Thread是程序执行的最小单元,分配CPU的基本单位,可以开启子线程执行耗时操作

  • Service在不同Activity中可以获取自身实例,可以方便的对Service进行操作。Thread在不同的Activity中难以获取自身实例,如果Activity被销毁,Thread实例就很难再获取得到

[](

)3、Service启动方式

  • startService

  • bindService

[](

)4、Service生命周期

  1. 手动调用startService()启动服务,自动调用内部方法:onCreate()、onStartCommand(),如果一个Service被startService()多次启动,那么onCreate()也只会调用一次。

  2. 手动调用stopService()关闭服务,自动调用内部方法:onDestory(),如果一个Service被启动且被绑定,如果在没有解绑的前提下使用stopService()关闭服务是无法停止服务的。

  3. 手动调用bindService()后,自动调用内部方法:onCreate()、onBind()。

  4. 手动调用unbindService()后,自动调用内部方法:onUnbind()、onDestory()。

  5. startService()和stopService()只能开启和关闭Service,无法操作Service,调用者退出后Service仍然存在;bindService()和unbindService()可以操作Service,调用者退出后,Service随着调用者销毁。

[](

)Broadcast Receiver面试题


[](

)1、Broadcast Receiver是什么

Broadcast是四大组件之一,是一种广泛运用在应用程序之间传输信息的机制,通过发送Intent来传送我们的数据

[](

)2、Broadcast Receiver的使用场景

  • 同一App具有多个进程的不同组件之间的消息通信

  • 不同App之间的组件之间的消息通信

[](

)3、Broadcast Receiver的种类

  • 普通广播

  • 有序广播

  • 本地广播

  • Sticky广播

[](

)4、Broadcast Receiver的实现

  • 静态注册:注册后一直运行,尽管Activity、进程、App被杀死还是可以接收到广播

  • 动态注册:跟随Activity的生命周期

[](

)5、Broadcast Receiver实现机制

  • 自定义广播类继承BroadcastReceiver,复写onReceiver()

  • 通过Binder机制向AMS进行注册广播

  • 广播发送者通过Binder机制向AMS发送广播

  • AMS查找符合相应条件的广播发送到BroadcastReceiver相应的循环队列中

  • 消息队列执行拿到广播,回调BroadcastReceiver的onReceiver()

[](

)6、LocalBroadcastManager特点

  • 本地广播只能在自身App内传播,不必担心泄漏隐私数据

  • 本地广播不允许其他App对你的App发送该广播,不必担心安全漏洞被利用

  • 本地广播比全局广播更高效

  • 以上三点都是源于其内部是用Handler实现的

[](

)WebView面试题


[](

)1、WebView安全漏洞

  • API16之前存在远程代码执行安全漏洞,该漏洞源于程序没有正确限制使用WebView.addJavascriptInterface方法,远程攻击者可通过使用Java反射机制利用该漏洞执行任意Java对象的方法

[](

)2、WebView销毁步骤

  • WebView在其他容器上时(如:LinearLayout),当销毁Activity时,需要在onDestroy()中先移除容器上的WebView,然后再将WebView.destroy(),这样就不会导致内存泄漏

[](

)3、WebView的jsbridge

  • 客户端和服务端之间可以通过Javascript来互相调用各自的方法

[](

)4、WebViewClient的onPageFinished

  • WebViewClient的onPageFinished在每次完成页面的时候调用,但是遇到未加载完成的页面跳转其他页面时,就会一直调用,使用WebChromeClient.onProgressChanged可以替代

[](

)5、WebView后台耗电

  • 在WebView加载页面的时候,会自动开启线程去加载,如果不很好的关闭这些线程,就会导致电量消耗加大,可以采用暴力的方法,直接在onDestroy方法中System.exit(0)结束当前正在运行中的java虚拟机

[](

)6、WebView硬件加速

Android3.0引入硬件加速,默认会开启,WebView在硬件加速的情况下滑动更加平滑,性能更加好,但是会出现白块或者页面闪烁的副作用,建议WebView暂时关闭硬件加速

[](

)7、WebView内存泄漏

由于WebView是依附于Activity的,Activity的生命周期和WebView启动的线程的生命周期是不一致的,这会导致WebView一直持有对这个Activity的引用而无法释放,解决方案如下

  • 独立进程,简单暴力,不过可能涉及到进程间通信(推荐)

  • 动态添加WebView,对传入WebView中使用的Context使用弱引用

[](

)Binder面试题


[](

)1、Linux内核的基本知识

  • 进程隔离/虚拟地址空间:进程间是不可以共享数据的,相当于被隔离,每个进程被分配到不同的虚拟地址中

  • 系统调用:Linux内核对应用有访问权限,用户只能在应用层通过系统调用,调用内核的某些程序

  • binder驱动:它负责各个用户的进程,通过binder通信内核来进行交互的模块

[](

)2、为什么使用Binder

  • 性能上,相比传统的Socket更加高效

  • 安全性高,支持协议双方互相校验

[](

)3、Binder通信原理

  1. Service端通过Binder驱动在ServiceManager的查找表中注册Object对象的add方法

  2. Client端通过Binder驱动在ServiceManager的查找表中找到Object对象的add方法,并返回proxy对象的add方法,add方法是个空实现,proxy对象也不是真正的Object对象,是通过Binder驱动封装好的代理类的add方法

  3. 当Client端调用add方法时,Client端会调用proxy对象的add方法,通过Binder驱动去请求ServiceManager来找到Service端真正对象,然后调用Service端的add方法

[](

)4、AIDL

  1. 客户端通过aidl文件的Stub.asInterface()方法,拿到Proxy代理类

  2. 通过调用Proxy代理类的方法,将参数进行封包后,调用底层的transact()方法

  3. transact()方法会回调onTransact()方法,进行参数的解封

  4. 在onTransact()方法中调用服务端对应的方法,并将结果返回

[](

)5、BpBinder和BBinder

BpBinder(客户端)对象和BBinder(服务端)对象,它们都从IBinder类中派生而来,BpBinder(客户端)对象是BBinder(服务端)对象的代理对象。

  • client端:BpBinder.transact()来发送事务请求

  • server端:BBinder.onTransact()会接收到相应事务

[](

)6.Binder有什么优势

性能方面

· 共享内存 0次数据拷贝

· Binder 1次数据拷贝

· Socket/管道/消息队列 2次数据拷贝

稳定性方面

· Binder:基于C/S架构,客户端(Client)有什么需求就丢给服务端(Server)去完成,架构清晰、职责明确又相互独立,自然稳定性更好

· 共享内存:虽然无需拷贝,但是控制复杂,难以使用

· 从稳定性的角度讲,Binder机制是优于内存共享的。

安全性方面

· 传统的IPC没有任何安全措施,安全依赖上层协议来确保。

· 传统的IPC方法无法获得对方可靠的进程用户ID/进程UI(UID/PID),从而无法鉴别对方身份。

· 传统的IPC只能由用户在数据包中填入UID/PID,容易被恶意程序利用。

· 传统的IPC访问接入点是开放的,无法阻止恶意程序通过猜测接收方地址获得连接。

· Binder既支持实名Binder,又支持匿名Binder,安全性高。

[](

)7.Binder是如何做到一次拷贝的

主要是因为Linux是使用的虚拟内存寻址方式,它有如下特性:

· 用户空间的虚拟内存地址是映射到物理内存中的

· 对虚拟内存的读写实际上是对物理内存的读写,这个过程就是内存映射

· 这个内存映射过程是通过系统调用mmap()来实现的 Binder借助了内存映射的方法,在内核空间和接收方用户空间的数据缓存区之间做了一层内存映射,就相当于直接拷贝到了接收方用户空间的数据缓存区,从而减少了一次数据拷贝

[](

)8.MMAP的内存映射原理了解吗

MMAP内存映射的实现过程,总的来说可以分为三个阶段:

(一)进程启动映射过程,并在虚拟地址空间中为映射创建虚拟映射区域

\1. 进程在用户空间调用库函数mmap,原型:void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

\2. 在当前进程的虚拟地址空间中,寻找一段空闲的满足要求的连续的虚拟地址

\3. 为此虚拟区分配一个vm_area_struct结构,接着对这个结构的各个域进行了初始化

\4. 将新建的虚拟区结构(vm_area_struct)插入进程的虚拟地址区域链表或树中

(二)调用内核空间的系统调用函数mmap(不同于用户空间函数),实现文件物理地址和进程虚拟地址的一一映射关系

\1. 为映射分配了新的虚拟地址区域后,通过待映射的文件指针,在文件描述符表中找到对应的文件描述符,通过文件描述符,链接到内核“已打开文件集”中该文件的文件结构体(struct file),每个文件结构体维护着和这个已打开文件相关各项信息。

\2. 通过该文件的文件结构体,链接到file_operations模块,调用内核函数mmap,其原型为:int mmap(struct file *filp, struct vm_area_struct *vma),不同于用户空间库函数。

\3. 内核mmap函数通过虚拟文件系统inode模块定位到文件磁盘物理地址。

\4. 通过remap_pfn_range函数建立页表,即实现了文件地址和虚拟地址区域的映射关系。此时,这片虚拟地址并没有任何数据关联到主存中。

(三)进程发起对这片映射空间的访问,引发缺页异常,实现文件内容到物理内存(主存)的拷贝 注:前两个阶段仅在于创建虚拟区间并完成地址映射,但是并没有将任何文件数据的拷贝至主存。真正的文件读取是当进程发起读或写操作时。

进程的读或写操作访问虚拟地址空间这一段映射地址,通过查询页表,发现这一段地址并不在物理页面上。因为目前只建立了地址映射,真正的硬盘数据还没有拷贝到内存中,因此引发缺页异常。

\1. 缺页异常进行一系列判断,确定无非法操作后,内核发起请求调页过程。

\2. 调页过程先在交换缓存空间(swap cache)中寻找需要访问的内存页,如果没有则调用nopage函数把所缺的页从磁盘装入到主存中。

\3. 之后进程即可对这片主存进行读或者写的操作,如果写操作改变了其内容,一定时间后系统会自动回写脏页面到对应磁盘地址,也即完成了写入到文件的过程。

注:修改过的脏页面并不会立即更新回文件中,而是有一段时间的延迟,可以调用msync()来强制同步, 这样所写的内容就能立即保存到文件里了。

[](

)9.Binder机制是如何跨进程的

1.Binder驱动

· 在内核空间创建一块接收缓存区,

· 实现地址映射:将内核缓存区、接收进程用户空间映射到同一接收缓存区

2.发送进程通过系统调用(copy_from_user)将数据发送到内核缓存区。由于内核缓存区和接收进程用户空间存在映射关系,故相当于也发送了接收进程的用户空间,实现了跨进程通信。

[](

)10.说说四大组件的通信机制

1.activity (1)一个Activity通常就是一个单独的屏幕(窗口)。 (2)Activity之间通过Intent进行通信。 (3)android应用中每一个Activity都必须要在AndroidManifest.xml配置文件中声明,否则系统将不识别也不执行该Activity。

2.service (1)service用于在后台完成用户指定的操作。service分为两种:

· started(启动):当应用程序组件(如activity)调用startService()方法启动服务时,服务处于started状态。

· bound(绑定):当应用程序组件调用bindService()方法绑定到服务时,服务处于bound状态。

(2)startService()与bindService()区别:

· started service(启动服务)是由其他组件调用startService()方法启动的,这导致服务的onStartCommand()方法被调用。当服务是started状态时,其生命周期与启动它的组件无关,并且可以在后台无限期运行,即使启动服务的组件已经被销毁。因此,服务需要在完成任务后调用stopSelf()方法停止,或者由其他组件调用stopService()方法停止。

· 使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。

(3)开发人员需要在应用程序配置文件中声明全部的service,使用标签。 (4)Service通常位于后台运行,它一般不需要与用户交互,因此Service组件没有图形用户界面。Service组件需要继承Service基类。Service组件通常用于为其他组件提供后台服务或监控其他组件的运行状态。

3.content provider (1)android平台提供了Content Provider使一个应用程序的指定数据集提供给其他应用程序。其他应用可以通过ContentResolver类从该内容提供者中获取或存入数据。 (2)只有需要在多个应用程序间共享数据是才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中。它的好处是统一数据访问方式。 (3)ContentProvider实现数据共享。ContentProvider用于保存和获取数据,并使其对所有应用程序可见。这是不同应用程序间共享数据的唯一方式,因为android没有提供所有应用共同访问的公共存储区。 (4)开发人员不会直接使用ContentProvider类的对象,大多数是通过ContentResolver对象实现对ContentProvider的操作。 (5)ContentProvider使用URI来唯一标识其数据集,这里的URI以content://作为前缀,表示该数据由ContentProvider来管理。

4.broadcast receiver (1)你的应用可以使用它对外部事件进行过滤,只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。广播接收器没有用户界面。然而,它们可以启动一个activity或serice来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力,例如闪动背灯、震动、播放声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。 (2)广播接收者的注册有两种方法,分别是程序动态注册和AndroidManifest文件中进行静态注册。 (3)动态注册广播接收器特点是当用来注册的Activity关掉后,广播也就失效了。静态注册无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器也是打开着的。也就是说哪怕app本身未启动,该app订阅的广播在触发时也会对它起作用。

[](

)11.为什么Intent不能传递大数据

Intent携带信息的大小其实是受Binder限制。数据以Parcel对象的形式存放在Binder传递缓存中。如果数据或返回值比传递buffer大,则此次传递调用失败并抛出TransactionTooLargeException异常。 Binder传递缓存有一个限定大小,通常是1Mb。但同一个进程中所有的传输共享缓存空间。多个地方在进行传输时,即时它们各自传输的数据不超出大小限制,TransactionTooLargeException异常也可能会被抛出。在使用Intent传递数据时,1Mb并不是安全上限。因为Binder中可能正在处理其它的传输工作。不同的机型和系统版本,这个上限值也可能会不同。

[](

)Handler面试题


[](

)1、Handler是什么

Handler通过发送和处理Message和Runnable对象来关联相对应线程的MessageQueue

[](

)2、Handler使用方法

  • post(runnable)

  • sendMessage(message)

[](

)3、Handler工作原理

[](

)4、Handler引起的内存泄漏

  • 原因:非静态内部类持有外部类的匿名引用,导致Activity无法释放

  • 解决:

    • Handler内部持有外部Activity的弱引用

    • Handler改为静态内部类

    • Handler.removeCallback()

    [](

)5、一个线程有几个 Looper?几个 Handler?

一个Thread只能有一个Looper,一个MessageQueen,可以有多个Handler 以一个线程为基准,他们的数量级关系是: Thread(1) : Looper(1) : MessageQueue(1) : Handler(N)



#### [](

)6、Handler 内存泄漏原因? 以及最佳解决方案?

泄露原因: Handler 允许我们发送延时消息,如果在延时期间用户关闭了 Activity,那么该 Activity 会泄露。 这个泄露是因为 Message 会持有 Handler,而又因为 Java 的特性,内部类会持有外部类,使得 Activity 会被 Handler 持有,这样最终就导致 Activity 泄露。



解决方案



\\1. 最直接的思路就是避免使用非静态内部类。使用Handler的时候,放在一个新建的文件中来继承Handler或者使用静态的内部类来替代。静态内部类不会隐含的持有外部类的引用,因此这个activity也就不会出现内存泄漏问题。



\\2. 如果你需要在Handler内部调用外部Activity的方法,你可以让这个Handler持有这个Activity的弱引用,这样便不会出现内存泄漏的问题了。



\\3. 另外,对于匿名类Runnable,我们同样可以设置成静态的,因为静态内部类不会持有外部类的引用。



\\4. 注意:如果使用Handler发送循环消息,最好是在Activity的OnDestroy方法中调用\*\*mLeakHandler.removeCallbacksAndMessages(null);\*\*移除消息。(这不是解决内存泄漏的方法)



#### [](

)7、为何主线程可以new Handler?如果想要在子线程中new Handler 要做些什么准备?

每一个handler必须要对应一个looper,主线程会自动创建Looper对象,不需要我们手动创建,所以主线程可以直接创建handler。 在new handler的时候没有传入指定的looper就会默认绑定当前创建handler的线程的looper,如果没有looper就报错。



因为在主线程中,Activity内部包含一个Looper对象,它会自动管理Looper,处理子线程中发送过来的消息。而对于子线程而言,没有任何对象帮助我们维护Looper对象,所以需要我们自己手动维护。 **所以要在子线程开启Handler要先创建Looper,并开启Looper循环**



如果在子线程中创建了一个Handler,那么就必须做三个操作:



\\1. prepare();



\\2. loop();



### [](

)\3. quit();

#### [](

)8、子线程中维护的Looper,消息队列无消息的时候的处理方案是什么?有什么用?

在Handler机制里面有一个Looper,在Looper机制里面有一个函数,叫做quitSafely()和quit()函数,这两个函数是调用的MessageQueue的quit()。



所以说,这个时候Looper就结束了(跳出了死循环),则达成了第二个作用:**释放线程**。



#### [](

)9、既然可以存在多个 Handler 往 MessageQueue 中添加数据(发消息时各个 Handler 可能处于不同线程),那它内部是如何确保线程安全的?

这里主要关注 MessageQueue 的消息存取即可,看源码内部的话,在往消息队列里面存储消息时,会拿当前的 MessageQueue 对象作为锁对象,这样通过加锁就可以确保操作的原子性和可见性了。

最后

今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。

最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。

还有?高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》

【算法合集】

【延伸Android必备知识点】

【Android部分高级架构视频学习资源】

了第二个作用:释放线程

#### [](

)9、既然可以存在多个 Handler 往 MessageQueue 中添加数据(发消息时各个 Handler 可能处于不同线程),那它内部是如何确保线程安全的?

这里主要关注 MessageQueue 的消息存取即可,看源码内部的话,在往消息队列里面存储消息时,会拿当前的 MessageQueue 对象作为锁对象,这样通过加锁就可以确保操作的原子性和可见性了。

最后

今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。

最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。

还有?高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》

[外链图片转存中…(img-N7hpDwrr-1630718722848)]

【算法合集】

[外链图片转存中…(img-INCvSqx3-1630718722850)]

【延伸Android必备知识点】

[外链图片转存中…(img-6tfCjVzK-1630718722851)]

【Android部分高级架构视频学习资源】

**Android精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-09-05 11:07:57  更:2021-09-05 11:10:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 17:07:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码