常见Android面试题及答案(详细整理)

对于Android的学习,很多⼈可能学了之后,不知道⾃⼰处于哪个阶段,也不到究竟要学到哪个程度,验证⾃⼰学得如何最好的⾯试,就是尝试去⾯试,⽽⾯试⽆⾮就是问你⼀些⾯试题。

所以呢,小编整理了这些 Android ⾯试题,从 Java 基础,并发,虚拟机到Android Framework,开源框架,性能优化,并且附带了详细的答案,⽆论是想⾯试还是想看看⾃⼰学得如何,那么这份⾯试题,都值得你去学习。

以下是一些常用的Android面试题及答案,有需要没需要都可以备着,希望能帮到大家。

1\. 请描述一下Activity 生命周期。

答: 如下图所示。共有七个周期函数,按顺序分别是: onCreate(), onStart(), onRestart(), onResume(), onPause(),onStop(), onDestroy()。

onCreate(): 创建Activity时调用,设置在该方法中,还以Bundle的形式提供对以前存储的任何状态的访问。

onStart(): Activity变为在屏幕上对用户可见时调用。

onResume(): Activity开始与用户交互时调用(无论是启动还是重新启动一个活动,该方法总是被调用。

onPause(): Activity被暂停或收回cpu和其他资源时调用,该方法用户保护活动状态的,也是保护现场。

onStop(): Activity被停止并转为不可见阶段及后续的生命周期事件时调用。

onRestart(): Activity被重新启动时调用。该活动仍然在栈中,而不是启动新的Activity。

1、完整生命周期: 即从一个Activity从出现到消失,对应的周期方法是从onCreate()到onDestroy()。

2、可见生命周期: 当Activity处于可以用户看见的状态,但不一定能与用户交互时,将多次执行从onStart()到onStop()。

3、前景生命周期: 当Activity处于Activity栈最顶端,能够与其他用户进行交互时,将多次执行从onResume()到onPause()。

2\. 两个Activity之间跳转时必然会执行的是哪几个方法。

答: 两个Activity之间跳转必然会执行的是下面几个方法。

onCreate()//在Activity生命周期开始时调用。

onRestoreInstanceState()//用来恢复UI状态。

onRestart()//当Activity重新启动时调用。

onStart()//当Activity对用户即将可见时调用。

onResume()//当Activity与用户交互时,绘制界面。

onSaveInstanceState()//即将移出栈顶保留UI状态时调用。

onPause()//暂停当前活动Activity,提交持久数据的改变,停止动画或其他占用GPU资源的东西,由于下一个Activity在这个方法返回之前不会resume,所以这个方法的代码执行要快。

onStop()//Activity不再可见时调用。

onDestroy()//Activity销毁栈时被调用的最后一个方法。

3\. 横竖屏切换时候Activity的生命周期。

答:

1、不设置Activity的android: configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次。

2、设置Activity的android: configChanges=“orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次。

3、设置Activity的android: configChanges=“orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfiguration方法

4\. 如何将一个Activity设置成窗口的样式。

答: 第一种方法,在styles.xml文件中,可以新建如下的类似Dialog的style。

第二种方法,在AndroidManifest.xml中在需要显示为窗口的Activity中添加如下属性: android: theme=“@style/Theme.FloatActivity”即可。也可以直接添加对应需要展示为Dialog style的Activity的android: theme属性为android: theme=“@ android: style/Theme.Dialog”。

`5. 两个Activity之间怎么传递数据?```

答: 可以在Intent对象中利用Extra来传递存储数据。

在Intent的对象请求中,使用putExtra(“键值对的名字”,”键值对的值”);在另外一个Activity中将Intent中的请求数据取出来:

Intent intent = getIntent();

String value = intent.getStringExtra(“testIntent”);

6\. 怎么让在启动一个Activity是就启动一个service?

答: 首先定义好一个service,然后在Activity的onCreate里面进行连接并bindservice或者直接startService。

7\. Activity怎么和service绑定,怎么在activity中启动自己对应的service?

答:

1、activity能进行绑定得益于Serviece的接口。为了支持Service的绑定,实现onBind方法。

2、Service和Activity的连接可以用ServiceConnection来实现。需要实现一个新的ServiceConnection,重现onServiceConnected和OnServiceDisconnected方法,一旦连接建立,就能得到Service实例的引用。

3、执行绑定,调用bindService方法,传入一个选择了要绑定的Service的Intent(显示或隐式)和一个你实现了的ServiceConnection的实例

8.什么是Service以及描述下它的生命周期。Service有哪些启动方法,有什么区别,怎样停用Service?

答: Android Service是运行在后台的代码,不能与用户交互,可以运行在自己的进程,也可以运行在其他应用程序进程的上下文里。需要通过某一个Activity或者Context对象来调用。Service有两个启动方法,分别是Context.startService()和Context.bindService()。如果在Service执行耗时的操作需要启动一个新线程来执行。

Android Service只继承了onCreate(), onStart(),onDestroy()三个方法,当我们第一次启动Service时,先后调用onCreate(), onStart()这两个方法,当停止Service时,则执行onDestroy()方法时。如果Service已经启动了,当我们再次启动Service时,不会再执行onCreate()方法,而是直接执行onStart()方法。

``9. 什么时候使用Service?```

答: 比如播放多媒体的时候,用户启动了其他Activity,这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你的地理信息位置的改变等等。

10\. 请描述一下Intent 和 Intent Filter。

答: Intent在Android中被翻译为”意图”,他是三种应用程序基本组件-Activity,Service和broadcast receiver之间相互激活的手段。在调用Intent名称时使用ComponentName也就是类的全名时为显示调用。这种方式一般用于应用程序的内部调用,因为你不一定会知道别人写的类的全名。而Intent Filter是指意图过滤,不出现在代码中,而是出现在android Manifest文件中,以的形式。(有一个例外是broadcast receiver的intent
filter是使用Context.registerReceiver()来动态设定的,其中intent filter也是在代码中创建的)

一个intent有action,data,category等字段。一个隐式intent为了能够被某个intent filter接收,必须通过3个测试,一个intent为了被某个组件接收,则必须通过它所有的intent filter中的一个。

11\. Intent传递数据时,可以传递哪些类型数据?

答: intent间传送数据一般有两种常用的方法: 1、extra 2、data。

extra可以用Intent.putExtra放入数据。新启动的Activity可用Intent.getExtras取出Bundle,然后用Bundles.getLong,getInt,getBoolean,getString等函数来取放进去的值。

Data则是传输url。url可以是指我们熟悉的http,ftp等网络地址,也可以指content来指向ContentProvider提供的资源。Intent.setData可以放入数据,Intent.getData可以取出数据。

12\. 说说Activity,Intent,Service是什么关系 ?

答: 一个Activity通常是一个单独的屏幕,每一个Activity都被实现为一个单独的类,这些类都是从Activity基类中继承而来的。Activity类会显示由视图控件组成的用户接口,并对视图控件的事件做出响应。

Intent的调用是用来进行屏幕之间的切换。Intent描述应用想要做什么。Intent数据结构中两个最重要的部分是动作和动作对应的数据,一个动作对应一个动作数据。

Service是运行在后台的代码,不能与用户交互,可以运行在自己的进程里,也可以运行在其他应用程序进程的上下文里。需要一个Activity或者其他Context对象来调用。

Activity跳转Activity,Activity启动Service,Service打开Activity都需要Intent表明意图,以及传递参数,Intent是这些组件间信号传递的承载着。

13\. 请描述一下BroadcastReceiver。

答: Broadcast Receiver用于接收并处理广播通知(broadcast announcements)。多数的广播是系统发起的,如地域变换、电量不足、来电短信等。程序也可以播放一个广播。程序可以有任意数量的broadcast receivers来响应它觉得重要的通知。Broadcast receiver可以通过多种方式通知用户: 启动activity、使用NotificationManager、开启背景灯、振动设备、播放声音等,最典型的是在状态栏显示一个图标,这样用户就可以点它打开看通知内容。通常我们的某个应用或系统本身在某些事件(电池电量不足、来电短信)来临时会广播一个Intent出去,我们利用注册一个broadcast
receiver来监听这些Intent并获取Intent中的数据。

14\. 在manifest和代码中如何注册和使用 broadcast receiver 。

答: 在android的manifest中注册

 <intent-filter>

     <!----和Intent中的action对应--->

     <actionandroid: name=“com.forrest.action.mybroadcast”/>

 </intent-filter>

在代码中注册

1、 IntentFilter filter = new IntentFilter(“com.forrest.action.mybroadcast”);//和广播中Intent的action对应;

2、 MyBroadcastReceiver br= new MyBroadcastReceiver();

3、 registerReceiver(br, filter);

15\. 请介绍下ContentProvider是如何实现数据共享的。

答: 一个程序可以通过实现一个Content provider的抽象接口将自己的数据完全暴露出去,而且Content provider是以类似数据库中的表的方式将自己的数据暴露。Content provider存储和检索数据,通过它可以让所有的应用程序访问到,这也是应用程序之间唯一共享数据的方法。

要想使应用程序的数据公开化,可通过2种方法:创建一个数据自己的Content Provider或者将你的数据添加到一个已经存在的Content Provider中,前提是有相同数据类型并且有写入Content Provider的权限,Android提供了Content Resolverr,外界的程序可以通过Content Resolver接口访问Content Provider提供的数据。

16\. 请介绍下Android的数据存储方式。

答: Android提供了5中存储数据的方式,分别是以下几种

1、使用Shared Preferences存储数据,用来存储key-value,pairs格式的数据,它是一个轻量级的键值存储机制,只可以存储基本数据类型。

2、使用文件存储数据,通过FileInputStream和FileOutputStream对文件进行操作。在Android中,文件是一个应用程序私有的,一个应用程序无法读写其他应用程序的文件。

3、使用SQLite数据库存储数据,Android提供的一个标准数据库,支持SQL语句。

4、使用Content Provider存储数据,是所有应用程序之间数据存储和检索的一个桥梁,它的作用就是使得各个应用程序之间实现数据共享。它是一个特殊的存储数据的类型,它提供了一套标准的接口用来获取数据,操作数据。系统也提供了音频、视频、图像和个人信息等几个常用的Content Provider。如果你想公开自己的私有数据,可以创建自己的Content Provider类,或者当你对这些数据拥有控制写入的权限时,将这些数据添加到Content Provider中实现共享。外部访问通过Content Resolver去访问并操作这些被暴露的数据。

5、使用网络存储数据

17\. 请介绍下Android中常用的五种布局。

答: 最常用的布局方式为Absolute Layout、Relative Layout、Linear Layout、FrameLayout、TableLayout。其中Linear Layout和Relative Layout是最常用的方式,他们可以通过在xml配置文件或者代码中进行布局。

1、Frame Layout是最简单的布局方式,放置的控件都只能罗列到左上角,控件会有重叠,不能进行复杂的布局。

2、Linear Layout可以通过orientation属性设置线性排列的方向是垂直还是纵向的,每行或每列只有一个元素,可以进行复杂的布局。

3、Absolute Layout可以让子元素指定准确的x、y坐标值,并显示在屏幕上。Absolute Layout没有页边框,允许元素之间相互重叠。它是绝对坐标,所以在实际中不提倡使用。

4、Relative Layout允许子元素制定他们相对于其他元素或父元素的位置(通过ID制定)。因此,你可以以右对齐,或上下,或置于屏幕中央的形式来排列两个元素。元素按顺序排列,因此如果第一个元素在屏幕的中央,那么相对于这个元素的其他元素将以屏幕中央的相对位置来排列。这个是相对于Absolute Layout的,采用相对坐标,所以在实际中比较常用。

5、Table Layout将以子元素的位置分配到行或列。一个Table Layout由许多的Table Row组成,每个Table Row都会定义一个row。Table Layout容器不会显示row、column或者cell的边线框。每个row拥有0个或多个的cell; 和html中的table差不多。在实际中也经常使用。

18\. 谈谈UI中, Padding和Margin有什么区别?

答: Padding是控件的内容相对控件的边缘的边距,而Margin是控件边缘相对于其他控件的边距。如下图所示:

19. android本身的一些限制,比如apk包大小限制,读取大文件时的时间限。

答:apk包大小限制不好说,有的apk为100M,还是能装到手机上。一般的apk大小为5~10M左右。读取大文件的时间应该是在main线程里面,时间限制为5秒左右。

20\. ListView如何提高其效率?

答:1、使用分页加载,不要一次性加载所有数据。

2、复用convertView。在getItemView中,判断converView是否为空,如果不为空,可复用。

3、异步加载图片。Item中如果包含有webimage,那么最好异步加载。

4、快速滑动时,不显示图片。当快速滑动列表(SCROLL_STATE_FLING),item中的图片或获取需要消耗资源的view,可以不显示出来;而处于其他两种状态(SCROLL_STATE_IDLE和SCROLL_STATE_TOUCH_SCROLL),则将那些view显示出来

21\. Android程序与Java程序的区别?

区别

Java程序

Android程序

执行入口点

Main

Android Mainfest.xml配置文件中的intent-filter

UI

Frame·

Activity

是否基于配置文件

是否基于组件

是Activity,Service,Broadcast Receiver,Content Provider

22\. 谈谈对Android NDK的理解。

答: android NDK是一套工具,允许Android应用开发者嵌入从C、C++源代码编译来的本地机器代码到各自的应用软件包中。

1、 NDK是一系列工具的集合。

NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者帮助时巨大的。

NDK集成了交叉编辑器,并提供了相应的mk文件隔离CPU、平台、API等差异,开发人员只需要简单修改mk文件(指出“那些文件需要编译”、“编译特性要求”等),就可以创建出so。NDK可以自动将so和Java应用一起打包,极大的减轻了开发人员的打包工作。

2、NDK提供了一份稳定、功能有限的API头文件声明。这些API支持的功能非常有限,包含有:C标准库(libc)、标准数学库(libm)、压缩库(libz)、log库(liblog)。

```23. 谈谈Android的优点和不足之处。``

答: 优点如下所示:

1、android是开源、市场占有率大。

2、android能够有丰富的硬件选择。

3、android是一款基于Linux平台的开源操作系统,从而避免了专利壁垒,是一款完全免费的只能手机平台。

4、由于android是google开发的,因此能够无缝结合Google应用。

缺点如下所示:

1、安全与隐私。手机与互联网紧密联系,个人隐私很难得到保守。

24\. Android系统中GC什么情况下会出现内存泄露呢?

答: 导致内存泄露主要的原因是,先前申请了内存空间而忘记了释放。如果程序中存在无用对象的引用,那么这些对象就会驻留内存,消耗内存,因为无法让垃圾回收器GC验证这些对象是否不再需要。如果存在对象的引用,这个对象就被定义为“有效的活动”,同时不会被释放。要确定对象所占内存将被回收,我们就要确认该对象不会再被使用。典型的做法是把对象数据成员设为null或者从集合中移除该对象。当出现以下情况时,会造成内存泄露:

1、 数据库的cursor没有关闭。

2、 构造adapter时,没有使用缓存contentview。

3、 Bitmap对象不使用时,采用recycle()释放内存。

4、 Activity中的对象的生命周期大于activity。

调试方法: DDMS==>HEAPSIZE==>dataobject==>[TotalSize]

25\. Android UI中的View如何刷新。

答: Android中对View的更新方式有很多种,使用时要区分不同的应用场合。要分清的是:多线程和双缓冲。

1、不使用多线程和双缓冲

这种情况最简单,一般只希望View在发生改变时对UI进行重绘。你只需要Activity中显式调用View对象中的invalidate()方法即可。系统会自动调用View的onDraw()方法。

2、使用多线程和不使用双缓冲

这种情况下需要开启新的线程,新开的线程就不好访问View对象了。强行访问的话会报错:android.view.ViewRoot$ CalledFromWrongThreadException: only theoriginal thread that created a view hierarchy can touch its views。

这时候你需要创建一个继承了android.os.handler的子类,并重写handleMessage方法。Android.os.Handle是能发送和处理消息的,你需要在Activity中发出更新UI的消息,然后再你的Handler(可以使用匿名内部类)中处理消息(因为匿名内部类可以访问父类变量,你可以直接调用View对象中的invalidate()方法。也就是说:在新线程中创建并发送一个Message,然后在主线程中捕获、处理该消息。

3、使用多线程和双缓冲

Android的SurfaceView是View的子类,她同时也实现了双缓冲。你可以定义一个她的子类并实现Surfaceholder.Callback接口。由于SurfaceHolder.Callback接口,新线程就不要android.os.Handler帮忙了。SurfaceHolder中lockCanvas()方法可以锁定画布,绘制完新的图像后调用unlockCanvasand Post解锁。

(来自威哥干Java的微信文章)

由于篇幅原因,这里还有我整理的2021秋招到2023年春招各一、二线互联网公司的Android面试题,内容包括Java基础、Activity、Fragment、Service、IPC、View、性能优化、 设计模式、第三方开源框架、Framework源码等相关面试题就没展示了,需要的威信扫码下方直接获取。

面试题

第一章 算法和数据结构面试题

  • 请说一说HashMap,SparseArrary原理,SparseArrary相比HashMap的优点、ConcurrentHashMap如何实现线程安全?
  • 请说一说HashMap原理,存取过程,为什么用红黑树,红黑树与完全二叉树对比,HashTab、concurrentHashMap,concurrent包里有啥?
  • 请说一说hashmap put()底层原理,发生冲突时,如何去添加(顺着链表去遍历,挨个比较key值是否一致,如果一致,就覆盖替换,不一致遍历结束后,插入该位置) ?
  • 请说一说ArrayList 如何保证线程安全,除了加关键字的方式 ?
  • 请说一说ArrayList、HashMap、LinkedHashMap ?
  • 请说一说HashMap实现原理,扩容的条件,链表转红黑树的条件是什么 ?

  • 在这里插入图片描述

第二章 Java核心基础面试题

  • Java中提供了抽象类还有接口,开发中如何去选择呢?
  • 重载和重写是什么意思,区别是什么?
  • 静态内部类是什么?和非静态内部类的区别是什么?
  • Java中在传参数时是将值进行传递,还是传递引用?
  • 使用equals和==进行比较的区别
  • String s = new String(“xxx”);创建了几个String对象?

在这里插入图片描述

第三章 Java深入泛型与注解面试题

  • 泛型是什么,泛型擦除呢?
  • List<String>能否转为List<Object>
  • Java的泛型中super 和 extends 有什么区别?
  • 注解是什么?有哪些使用场景?

  • 在这里插入图片描述

第四章 Java并发编程面试题

  • 假如只有一个cpu,单核,多线程还有用吗 ?
  • sychronied修饰普通方法和静态方法的区别?什么是可见性?
  • Synchronized在JDK1.6之后做了哪些优化
  • CAS无锁编程的原理
  • AQS原理
  • ReentrantLock的实现原理

在这里插入图片描述



第十章 Framework内核解析面试题

  • Android中多进程通信的方式有哪些?
  • 描述下Binder机制原理?
  • 为什么 Android 要采用 Binder 作为 IPC 机制?
  • Binder线程池的工作过程是什么样?
  • AIDL 的全称是什么?如何工作?能处理哪些类型的数据?
  • Android中Pid&Uid的区别和联系

在这里插入图片描述

第十一章 Android组件内核面试题

  • Acitvity的生命周期,如何摧毁一个Activity?
  • Activity的4大启动模式,与开发中需要注意的问题,如onNewIntent() 的调用
  • Intent显示跳转与隐式跳转,如何使用?
  • Activity A跳转B,B跳转C,A不能直接跳转到C,A如何传递消息给C?
  • Activity如何保存状态的?
  • 请描诉Activity的启动流程,从点击图标开始。

在这里插入图片描述

第十二章 程序性能优化与数据持久化面试题

  • 一张图片100x100在内存中的大小?
  • 内存优化,内存抖动和内存泄漏。
  • 什么时候会发生内存泄漏?举几个例子
  • Bitmap压缩,质量100%与90%的区别?
  • TraceView的使用,查找CPU占用
  • 内存泄漏查找

在这里插入图片描述

第十三章 开源框架面试题

  • 组件化在项目中的意义
  • 组件化中的ARouter原理
  • 谈一下你对APT技术的理解
  • 谈谈Glide框架的缓存机制设计
  • 谈谈你对Glide生命周期的理解
  • 项目中使用Glide框架出现内存溢出,应该是什么原因?

在这里插入图片描述

  • 6
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一些常见的数据库面试题及其答案: 1. 什么是数据库的 ACID 特性? ACID 是数据库事务的四个特性的缩写,包括原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。原子性指事务是不可分割的单位,要么全部执行成功,要么全部回滚;一致性指事务将数据库从一个一致状态转换到另一个一致状态;隔离性指同时运行的事务之间应该相互隔离,互不干扰;持久性指一旦事务提交成功,其对数据库的更新将永久保存。 2. 什么是数据库索引?它有什么作用? 数据库索引是一种数据结构,用于加速对数据库表中数据的检索。它类似于书籍的目录,通过建立索引可以快速定位到特定值。索引可以提高查询效率,并且可以加速排序和聚合操作。 3. 什么是数据库事务?如何确保事务的完整性和一致性? 数据库事务是一组被视为单个逻辑工作单元的操作。事务应具有原子性、一致性、隔离性和持久性(ACID 特性)。通过使用事务日志和回滚操作,可以确保事务的完整性和一致性。 4. 什么是数据库连接池?为什么需要使用连接池? 数据库连接池是一组预先创建的数据库连接对象,它们被缓存在内存中以供应用程序重复使用。使用连接池可以减少数据库连接的创建和关闭开销,提高数据库访问的性能和效率,并且可以更好地管理并发连接数。 5. 请解释关系型数据库和非关系型数据库的区别。 关系型数据库(如MySQL、Oracle)使用表和行的结构来存储和组织数据,具有严格的结构和事务支持。非关系型数据库(如MongoDB、Redis)则以键值对、文档、图形或列族的形式存储和组织数据,具有更灵活的数据模型和可伸缩性。 6. 请解释什么是数据库范式化(Normalization)。 数据库范式化是一种设计方法,通过将数据分解成不同的表并建立关系,以减少数据冗余和提高数据存储的效率。常见的范式包括第一范式(1NF)、第二范式(2NF)、第三范式(3NF)等。 7. 请解释数据库的连接(Join)操作。 数据库连接操作用于将多个表中具有关联关系的数据进行合并查询。常见的连接类型包括内连接(Inner Join)、外连接(Left Join、Right Join、Full Outer Join)和交叉连接(Cross Join)。 8. 什么是数据库索引的选择性?为什么选择性很重要? 数据库索引的选择性是指索引列中不同值的数量与总行数之间的比率。选择性越高,索引的效果越好。选择性很重要,因为低选择性的索引可能导致查询优化器不使用索引,从而影响查询性能。 9. 请解释数据库的事务隔离级别。 数据库的事务隔离级别定义了事务在进行并发访问时的隔离程度。常见的隔离级别包括读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)。隔离级别越高,数据一致性越好,但并发性能可能降低。 10. 请解释数据库的备份和恢复。 数据库备份是指将数据库的副本创建并存储在另一个位置,以防止数据丢失。数据库恢复是指在数据库损坏或数据丢失时,将备份数据重新导入数据库以恢复数据。常见的备份和恢复策略包括完全备份、增量备份和差异备份等。 这些是一些常见的数据库面试题及其答案,希望对您有所帮助。在面试前,建议您复习数据库基本概念、SQL 语言、事务处理、数据库设计和性能优化等方面的知识,并准备一些实际项目经验的案例来展示您在数据库方面的能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值