android FragmentPagerAdapter与FragmentStatePagerAdapter的区别

Android 项目总结(FragmentPagerAdapter与FragmentStatePagerAdapter的区别) Android 项目总结(FragmentPagerAdapter与FragmentStatePagerAdapter的区别(方法已过时)) 阅读详情

很多app的主界面都是底部几个按钮,然后点击切换显示不同的UI展现,这种可以使用Viewpager+fragment的方式实现,但是一不注意就会有问题,

比如是使用FragmentPagerAdapter的话,如果viewpager设置了setCurrentItem(index);会先把index-1,index+1以及index中对应的Fragment中的view加载出来,如果index=0的话,就只加载2个fragment中的view了.当viewpager滑动到那个界面就会加载那个fragment的view,比如你从第一个滑动到第四个,然后又从第四个滑动到第一个,这个时候第四个view就会被回收,view就为null,意味着你来回切换,fragment中的view会重复的,因为之前Fragment中的onDestroyView()生命周期方法会执行,导致view就会被回收了,如果你再viewpager的滑动监听通过view做什么业务很容易导致NullPointerException异常,我之前项目就有遇到过,重复加载view的问题怎么解决呢?

第一:设置viewpager的缓存为你fragment的个数.

viewpager.setOffscreenPageLimit(fragment的个数);

这些现象,你可以通过打log自己去分析,

如果使用的是FragmentStatePagerAdapater,viewpager滑动的时候会把fragment从内存中清除,这个可以从源代码上去分析:

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    Fragment fragment = (Fragment) object;

    if (mCurTransaction == null) {
        mCurTransaction = mFragmentManager.beginTransaction();
    }
    if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object
            + " v=" + ((Fragment)object).getView());
    while (mSavedState.size() <= position) {
        mSavedState.add(null);
    }
    mSavedState.set(position, fragment.isAdded()
            ? mFragmentManager.saveFragmentInstanceState(fragment) : null);
    mFragments.set(position, null);

    mCurTransaction.remove(fragment);
}

最后一行就是移除了Fragment,而FragmentPagerAdapter的源代码:

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    if (mCurTransaction == null) {
        mCurTransaction = mFragmentManager.beginTransaction();
    }
    if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
            + " v=" + ((Fragment)object).getView());
    mCurTransaction.detach((Fragment)object);
}

最后一行就是把Fragment中View移除了,这就是二者很大的区别,所以说当Fragment比较多的时候就用FragmentStatePagerAdapter,因为它会之前的Fragment从内存中移除,这样就节省了内存,如果Fragment不多的情况下就使用FragmentPagerAdapter,

还有一个问题就是动态的加载Fragment,就是viewpager增加或者删除Fragment,这个在我项目中也遇到了,如果是FragmentStatePagerAdapter的话就要重写

@Override
public int getItemPosition(Object object) {
    return PagerAdapter.POSITION_NONE;
}

如果是FragmentPagerAdapter的话就要重写:

@Override
public long getItemId(int position) {
    int hashCode = mFragment.get(position).hashCode();
    return hashCode;
}
然后记得把viewpager指向显示那一个fragment,比如viewpager.setCurrentItem(0);如果不调用这个,会发现他还是会显示当前删除的fragment,只有滑动后,那个fragment才会消失.





【Android面试八股文】你能说说FragmentPagerAdapter 和 FragmentStatePagerAdapter的区别吗? 的:仅仅调用detach(),将Fragment从 UI 中移除,但Fragment本身仍然保留在内存和中。因此,Fragment没有被销毁,这解释了为什么会保持所有Fragment实例在内存中。这种设计的目的为了避免每次页面切换时重新创建Fragment,从而提升性能,适用于页面较少且页面之间切换频繁的情况。通过保持Fragment在内存中,可以避免重新创建Fragment的开销,从而加快页面切换速度。的:不仅调用remove()彻底销毁Fragment,还保存Fragment的状态。这样,虽然。 阅读详情

相关推荐

RocketMQ源码分析之消息轨迹

文章目录前言一、消息轨迹二、消息轨迹源码分析1、producer端2、consumer端三、消息轨迹中存储的信息1.TraceContext2.TraceBean3.TraceType四、总结 前言   本篇文章将会从以下方面介绍消息轨迹:什么是消息轨迹?如何启用消息轨迹?示例demo、消息轨迹的源码分析和消息轨迹中存储的信息。最后会用一张图来总结消息轨迹的工作原理。 一、消息轨迹 1.什么是消息轨迹? 消息轨迹是用来跟踪记录消息发送、消息消费的轨迹。 2.如何启用消息轨迹? broker端 需要在b

不爱学习的小妞博客 1076

FragmentPagerAdapter对于app.Fragment的兼容

需要引用v13包下的FragmentPagerAdapter,拿其中的源码来改就可以了。或者重写FragmentPagerAdapter,写v4的Fragment改成app.Fragment

星星的专栏 1289

如何制作Mike21溢油模型围油栏文件

这段时间群友在做海洋环评的做了一个MIKE21的溢油模型,溢油模型其实也是ECOLAB模块的应用,而在海上发生溢油事件的时候,为防止溢油对海洋生态的破坏,经常使用的一种手段就是使用围油栏技术将溢油控制在一定范围并进行处理。今天小编就给大家说说在MIKE21里怎么实现围油栏文件的制作

zhuzhujiayoua的博客 1332

FragmentStatePagerAdapter使用不当引起的内存泄漏问题

FragmentStatePagerAdapter使用不当引起的内存泄漏问题 首先来看看问题的复现的代码 class InnerPagerAdapter( fm: FragmentManager, private val fragments: ArrayList<out Fragment>, private val titles: List<CharSequence> ) : FragmentStatePagerAdapter(fm) { overr

TE28093163的专栏 4157

基于PINN的一个简单的求解偏微分方程实例

本人是做化工模拟的一名学生,最近在学习PINN(Physics-Informed Neural Networks,物理信息神经网络)对管道动力学进行建模研究,PINN由于其对机理与数据的良好兼顾性非常热门,本文是作者对PINN入门研究过程的一个练手小题目,main code也是作者代码是基于pytorch2.6.0写的,发上来供各位参考,欢迎研究管道动力学和PINN的小伙伴一起讨论~

weixin_64491760的博客 1741

【Agent】多智能体框架MetaGPT入门教程

创建一个 Action 类的子类 SimpleWriteCode,子类中定义好 prompt,并解析返回结果。在 MetaGPT 中,

酒酿小圆子呀~ 3140

Android ViewPager+Fragment遇到系统主题更换时Fragment不正常刷新

Android ViewPager+Fragment遇到系统主题更换时Fragment不正常刷新前言解决方法完事 前言 最近有个UI布局需要用到ViewPager+Fragment来做首页左右滑动切换,开发时一直正正常常的,开开心心无忧无虑,结果到最后适配深色模式的时候,一切换系统主题,activity重建,崩溃。。。 年轻的我就想是不是fragment还没add到Viewpager就调用了,一顿操作。 结果在Fragment中判断isAdded一直是false,瞬间蒙圈。 在百度搜索了一下,基本确定是Ac

杨迪龙的博客 2272

给麒麟KylinOS服务器加把锁:手把手配置符合等保要求的密码强度策略

本文详细介绍了如何在麒麟KylinOS服务器上配置符合等保要求的密码强度策略,包括pwquality.conf和login.defs的核心参数设置、等保合规的进阶配置技巧以及企业环境中的平衡艺术。通过实战案例和测试方法,帮助管理员构建坚固的密码防线,确保系统安全。

weixin_33749242的博客 419

Android适配器之FragmentPagerAdapter

FragmentPagerAdapter FragmentPagerAdapter extends PagerAdapter java.lang.Object    ↳ android.support.v4.view.PagerAdapter      ↳ android.support.v4.app.Fr

Weven-blog 1953

探索Vortex开源GPGPU:RISC-V SIMT架构(4-1),Execute SFU(1)

本文详细分析了Vortex RISC-V内核6级流水线中Execute阶段的SFU(特殊功能单元)模块。重点介绍了SFU的数据流结构,包含dispatch_unit、pe_switch、csr_unit、wctl_unit和gather_unit五个子模块。文章深入解析了warp控制指令wspawn和tmc的实现机制:wspawn用于激活指定数量的warp并设置新PC值,tmc则用于控制线程掩码和warp状态。通过C代码和汇编指令的对照分析,阐明了这些指令在并行计算中的关键作用,包括线程激活、状态切换和执行

weixin_55313207的博客 1363

[毕设项目-MCP+ENSP]一句话搞定ENSP自动化:MCP + LLM实战(架构图、工具清单、踩坑全解)

用 MCP + LLM 把“人话”变成对华为 ENSP 的安全自动化操作,三款工具覆盖配置/查询/落盘,配套架构、实战与排坑清单。

逐梦苍穹的博客 2544

1、关于FragmentPagerAdapter 2、关于FragmentStatePagerAdapter本质区别

1、关于FragmentPagerAdapter 1、它的onCreate跟onAttach只会执行一次,哪怕不存在缓存中了也只会执行一次; 2、关于getUserVisibleHint(); 关于getUserVisibleHint 对于没在跳转到的fragment 没在缓存中的话 如果之前都没有初始化过 : Fragment03: =========setUserVisibleHint----...

kazike_it的博客 185

飞腾平台(FT2000/4 D2000/8)配置GPIO引脚

飞腾平台配置CPU的引脚为GPIO工作模式的方式有永久型和暂时型: - 永久型是通过UEFI中的MmioWrite32函数来实现的,该方法可以在UEFI阶段就对复用引脚的工作模式配置为GPIO,并且在进入操作系统后仍然不会发生便会; - 临时型是通过rw工具,在系统下手动修改复用引脚的工作模式,该方法在系统重启后会失效,所以是暂时型的。

qq_30135687的博客 5617

android之FragmentPagerAdapter 和FragmentStatePagerAdapter的区别

android之FragmentPagerAdapter 和FragmentStatePagerAdapter的区别FragmentPagerAdapter 该类内的每一个生成的 Fragment 都将保存在内存之中,因此适用于那些相对静态的页,数量也比较少的那种;如果需要处理有很多页,并且数据动态性较大、占用内存较多的情况,应该使用FragmentStatePagerAdapter。Fragme...

starzhangkiss的博客 745

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Android——FragmentPagerAdapter与FragmentStatePagerAdapter区别

在一个 Android 应用中,我们使用 FragmentPagerAdapter 来处理多 Fragment 页面的横向滑动。不过我碰到了一个问题,即当 Fragment 对应的数据集发生改变时,我希望能够通过调用 mAdapter.notifyDataSetChanged() 来触发 Fragment 页面使用新的数据调整或重新生成其内容,可是当我调用 notifyDataSetChanged...

小欣儿的专栏 709

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

【Android界面实现】FragmentPagerAdapter与FragmentStatePagerAdapter使用详解与区别

转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992     FragmentPagerAdapter是android-support-v4支持包里面出现的一个新的适配器,继承自PagerAdapter,是专门用来给支持包中出现的ViewPager进行数据适配的。     PagerAdapter在之前的文章中进行过简单的介绍,不记得怎么使用的可以

a5597942的专栏 738

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Android——PagerAdapter和FragmentPagerAdapter和FragmentStatePagerAdapter区别

转自:http://blog.csdn.NET/dreamzml/article/details/9951577ViewPagerViewPager 如其名所述,是负责翻页的一个 View。准确说是一个 ViewGroup,包含多个 View 页,在手指横向滑动屏幕时,其负责对 View 进行切换。为了生成这些 View 页,需要提供一个 PagerAdapter 来进行和数据绑定以及生成最终的 V

Li_peilun的博客 484

android FragmentpagerAdapter和FragmentStatePagerAdapter的区别

1.FragmentPagerAdapter FragmentPagerAdapter 继承自 PagerAdapter。相比通用的 PagerAdapter,该类更专注于每一页均为 Fragment 的情况。如文档所述,该类内的每一个生成的 Fragment 都将保存在内存之中,因此适用于那些相对静态的页,数量也比较少的那种;如果需要处理有很多页,并且数据动态性较大、占用内存较多的情况,应

xiangzhihong8的专栏 1328

【Android】FragmentPagerAdapter与FragmentStatePagerAdapter使用详解与区别

转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992     FragmentPagerAdapter是android-support-v4支持包里面出现的一个新的适配器,继承自PagerAdapter,是专门用来给支持包中出现的ViewPager进行数据适配的。     PagerAdapter在之前的文章中进行过简单的介绍,不记得怎么使用的可以

u011494050的专栏 1175

android FragmentPagerAdapter和FragmentStatePagerAdapter的区别

1. PagerAdapter分析与Fragment懒加载的几种实现简记1. FragmentPagerAdapter: 超出可视范围和缓存范围之外的Fragment,它的视图将会被销毁,但是它的实例将会保留在内存中,所以每一页的Fragment至始至终都只需要构造一次而已。通常是在主页中使用FragmentPagerAdapter2. FragmentStatePagerAdapter: 当使用...

dzning123的专栏 430

android fragmentstatepageradapter框架,Android 中 FragmentPagerAdapter 与 FragmentStatePagerAdapter的区别...

1、博文介绍2、FragmentPagerAdapter中设置不让Fragment视图重新创建image.pngimage.pngFragmentPagerAdapter完整代码如下/*** 主页ViewPager适配器* Created by _Smile on 2017/5/9.*/public class TabFragmentPagerAdapter extends FragmentPag...

weixin_42514288的博客 444

Android FragmentPagerAdapter和FragmentStatePagerAdapter的区别

FragmentPagerAdapter官方解释: This version of the pager is best for use when there are a handful of typically more static fragments to be paged through, such as a set of tabs. The fragment of each page t

xuewater的专栏 1167

Android中FragmentPagerAdapter与FragmentStatePagerAdapter使用和区别

FragmentPagerAdapter 和 FragmentStatePagerAdapter区别: 在使用方式上两者没有区别,区别主要体现在缓存上 FragmentPagerAdapter : 1、getItem只调用一次,调用一次将返回位置的Fragment缓存到mFragmentManager,下次切换调用instantiateItem直接从mFragmentManager的缓存...

MG_ZXC的专栏 660
上一篇: android fragment中EditText长按和点击无效的解决方案
下一篇: android 使用代理模式切换不同的框架
zhoushenxian
博客等级 码龄12年 453粉丝 549原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值