Activity四种启动模式

复习Activity的四种启动模式

最近刚刚开始练习书写博客,先从Activity的四种启动模式开始练起吧!首先介绍一下Android对Activity的管理:

  • Android采用Task管理多个Activity,当我们启动一个Activity的,系统会创建一个Task,然后会启动这个Activity的入口,也就是栈 。Task是以栈来管理Activity。

  • 当启动一个Activity时,系统会创建多个实例,并按照先进后出的原则一一放入任务栈,当我们再回退的时候,在任务栈中最顶层的activity会被移除,到任务栈中为空的时候系统就会回收这个任务栈。

  • 所以在系统启动同一个Activity的时候会创建多个实例,所以就有了android的四种启动模式。

Activity的四种启动模式如下:

standard、singleTop、singleTask、singleInstance

学习前辈代码书写方式,为了打印方便,定义一个基础Activity,在其onCreate方法和onNewIntent方法中打印出当前Activity的日志信息,主要包括所属的task,当前类的hashcode,以及taskAffinity的值。之后我们进行测试的Activity都直接继承该Activity

public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("practice", "*****onCreate()方法******");
        Log.i("practice", "onCreate:" + getClass().getSimpleName() + " TaskId: " + getTaskId() + " hasCode:" + this.hashCode());
        dumpTaskAffinity();

    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.i("practice", "*****onNewIntent()方法*****");
        Log.i("practice", "onNewIntent:" + getClass().getSimpleName() + " TaskId: " + getTaskId() + " hasCode:" + this.hashCode());
        dumpTaskAffinity();
    }

    private void dumpTaskAffinity() {
        try {
            ActivityInfo info = this.getPackageManager()
                    .getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
            Log.i("practice", "taskAffinity:" + info.taskAffinity);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }
}

下面我们正式开始分享Android四大启动模式:


standard-默认模式

standard模式是默认的启动模式,即标准模式。当活动设置了此模式,每次启动都会创建一个新的实例,而不在乎该活动是否已经在返回栈中存在,谁启动了该模式下的Activity,该Activity它启动Activity任务栈中。同时这个Activity的onCreate(),onStart(),onResume()方法都会被调用。

配置形式

 <activity
            android:name=".standard.Activity_Standard"
            android:launchMode="standard" />

StandardActivity 的代码如下,入口Activity中有一个按钮进入该Activity,这个Activity中又有一个按钮启动StandardActivity。

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.practice.day_12_5_practiceinitiating.utils.BaseActivity;
import com.practice.day_12_5_practiceinitiating.R;
import com.practice.day_12_5_practiceinitiating.utils.ViewFindUtils;

public class Activity_Standard extends BaseActivity {

    private View view;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_standard);
        //View显示的最顶层View
        view = getWindow().getDecorView();
        Button btnJump = ViewFindUtils.find(view, R.id.btn_jump);

        btnJump.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(Activity_Standard.this, Activity_Standard.class));
            }
        });
    }
}

首先进入Activity_Standard界面再点击按钮再按返回键不断返回。

输出的日志如下:

I/Liang_Demo: *****onCreate()方法******
I/Liang_Demo: onCreate:Activity_Standard TaskId: 913 hasCode:207685195
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating
I/Liang_Demo: *****onCreate()方法******
I/Liang_Demo: onCreate:Activity_Standard TaskId: 913 hasCode:624164130
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating
I/Liang_Demo: *****onCreate()方法******
I/Liang_Demo: onCreate:Activity_Standard TaskId: 913 hasCode:210709
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating
I/Liang_Demo: *****onCreate()方法******
I/Liang_Demo: onCreate:Activity_Standard TaskId: 913 hasCode:505663380
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating

由上述输出的日志可以看出,其中所属的任务栈的id都是913,这也验证了“谁启动了该模式的Activity,该Activity就属于启动它的Activity的任务栈”这句话,因为启动ActivityStandard的是MainActivity,而MainActivity的TaskId是913,因此启动的ActivityStandard也属于id为913这个task,后续的3个StandardActivity是被StandardActivity这个对象启动的,因此id也还是913,所以说TaskId都是913.并且每一个Activity的hashcode都是不一样的,说明他们是不同的实例,及验证了“每次启动一个Activity都会重写创建一个新的实例”

singleTop-栈顶复用模式

这个模式下,如果新的activity已经位于栈顶,那么这个Activity不会被重写创建,同时它的onNewIntent方法会被调用,通过此方法的参数我们可以去除当前请求的信息。如果栈顶不存在该Activity的实例,则情况与standard模式相同。需要注意的是这个Activity它的onCreate(),onStart()方法不会被调用,因为它并没有发生改变。

配置形式

 <activity
            android:name=".singletop.SingletopActivity"
            android:launchMode="singleTop" />

使用案例

SingleTopActivity.java

package com.practice.day_12_5_practiceinitiating.singletop;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.practice.day_12_5_practiceinitiating.R;
import com.practice.day_12_5_practiceinitiating.utils.BaseActivity;
import com.practice.day_12_5_practiceinitiating.utils.ViewFindUtils;

public class SingletopActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_singletop);

        View view = getWindow().getDecorView();

        Button btnTop = ViewFindUtils.find(view, R.id.single_top);

        Button btnOther = ViewFindUtils.find(view, R.id.other_Activity);

        btnTop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(SingletopActivity.this, SingletopActivity.class);
                startActivity(intent);
            }
        });

        btnOther.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(SingletopActivity.this, OtherTopActivity.class));
            }
        });
    }
}

OtherTopActivity.java

package com.practice.day_12_5_practiceinitiating.singletop;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.practice.day_12_5_practiceinitiating.R;
import com.practice.day_12_5_practiceinitiating.utils.BaseActivity;

public class OtherTopActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_other_top);

        Button btnBack = (Button) findViewById(R.id.back);

        btnBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(OtherTopActivity.this, SingletopActivity.class));
            }
        });
    }
}

操作步骤与Standard类似,输出日志:

12-06 09:25:07.674 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: *****onCreate()方法******
12-06 09:25:07.677 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: onCreate:MainActivity TaskId: 320 hasCode:740093156
12-06 09:25:07.679 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating
12-06 09:29:29.686 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: *****onCreate()方法******
12-06 09:29:29.687 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: onCreate:SingletopActivity TaskId: 320 hasCode:1024857734
12-06 09:29:29.689 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating
12-06 09:29:36.215 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: *****onNewIntent()方法*****
12-06 09:29:36.216 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: onNewIntent:SingletopActivity TaskId: 320 hasCode:1024857734
12-06 09:29:36.217 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating
12-06 09:29:37.925 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: *****onNewIntent()方法*****
12-06 09:29:37.926 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: onNewIntent:SingletopActivity TaskId: 320 hasCode:1024857734
12-06 09:29:37.927 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating
12-06 09:29:39.875 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: *****onNewIntent()方法*****
12-06 09:29:39.876 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: onNewIntent:SingletopActivity TaskId: 320 hasCode:1024857734
12-06 09:29:39.884 20585-20585/com.practice.day_12_5_practiceinitiating I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating

由上面的输出日志我们可以看出程序只有在第一次进入SingleTopActivity的时候执行了一次onCreate方法,等我们再次进入SingleTopActivity的时候执行时onNewIntent方法。
由此可以看出来,程序在第一次进入Activity的时候,栈中并没有该Activity的实例,从而创建一个新的实例,执行了onCreate方法,当我们再次进入这个Activity的时候,在栈的顶部已经存在了这个Activity的实例,就去复用这个实例,从而执行了onNewIntent的方法。

那当我们第一次创建的实例已经在栈中存在,但位置并不是在栈的顶部的时候又是什么样的情况呢!!

首先我们先从MainActivity进入SingleTopActivity中,再从SingleTopActivity中跳入OtherTopActivity中,在从OtherTopActivity跳转到SingleTopActivity中,最后再从SingleTopActivity中再次跳入SingleTopActivity中,我们再来查看一下日志:

I/Liang_Demo: *****onCreate()方法******
I/Liang_Demo: onCreate:MainActivity TaskId: 321 hasCode:740093156
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating

I/Liang_Demo: *****onCreate()方法******
I/Liang_Demo: onCreate:SingletopActivity TaskId: 321 hasCode:1024857734
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating

I/Liang_Demo: *****onCreate()方法******
I/Liang_Demo: onCreate:OtherTopActivity TaskId: 321 hasCode:877067584
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating

I/Liang_Demo: *****onCreate()方法******
I/Liang_Demo: onCreate:SingletopActivity TaskId: 321 hasCode:778071203
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating

I/Liang_Demo: *****onNewIntent()方法*****
I/Liang_Demo: onNewIntent:SingletopActivity TaskId: 321 hasCode:778071203
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating

我们在从MainActivity中进入SingleTopActivity中时会新建一个SingleTopActivity的对象,然后再从SingleTopActivity跳入OtherTopActivity中,同样会新建一个OtherTopActivity的对象,这样在栈中我们可以知道有下到上的顺序分别是:MainActivity、SingleTopActivity、OtherTopActivity的对象实例,如果此时再次跳入SingleTopActivity ,即使栈中已经存在SingleTopActivity 的实例,但是还是会新建一个新的SingleTopActivity的实例,这一点我们从上面日志的hashCode可以看出,此时栈顶的实例是SingleTopActivity,所以在次进入SingleTopActivity的时候则调用栈顶部的实例,不需要重新创建新的实例,所以我们看见了onNewIntent的方法。

对以上的总结

1、Standard启动模式是Android中默认的启动模式,无论栈中存不存在进入的Activity实例,都会创建一个新的Activity实例。
2、SingleTop的启动有三种
①当Task中存在Activity的实例,但是并不在Task顶部,那么在一次进入该Activity中时会创建新的Activity的实例;
②当Task中存在Activity的实例,并且已经在Task的顶部,那么在下一次进入该Activity 的时候不会新建Activity的实例,而是调用其中的onNewIntent方法;
③当Task中不存在Activity的实例时,该启动模式与Standard的方式相同。

singleTask-栈内复用模式

singleTask启动模式比较复杂。在这个模式下,如果栈中存在Activity的实例就会复用这个Activity,不管它是否存在于栈的顶部,复用的同时,他会将该Activity上部的Activity全部出栈,并且回掉onNewIntent方法。
其实这其中还存在一个任务栈的匹配的过程,因为这个模式启动时,会在自己需要的任务栈中寻找实例,通过TaskAffinity这个属性指定。如果这个Task不存在,那么就要重新创建一个新的Task。

首先们先看一下默认的TaskAffinity的情况(默认的情况TaskAffinity的属性是该应用程序的包名)

配置形式

<activity
            android:name=".singletask.SingleTaskActivity"
            android:launchMode="singleTask" />

使用案例

SingleTaskActivity.java

package com.practice.day_12_5_practiceinitiating.singletask;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.practice.day_12_5_practiceinitiating.R;
import com.practice.day_12_5_practiceinitiating.utils.BaseActivity;
import com.practice.day_12_5_practiceinitiating.utils.ViewFindUtils;

public class SingleTaskActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_single_task);

        View view = getWindow().getDecorView();

        Button btnSingleTask = ViewFindUtils.find(view, R.id.btn_singleTask);

        Button btnOtherTask = ViewFindUtils.find(view, R.id.btn_otherTask);

        btnSingleTask.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(SingleTaskActivity.this, SingleTaskActivity.class));
            }
        });


        btnOtherTask.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(SingleTaskActivity.this, OtherTaskActivity.class));
            }
        });
    }
}

OtherTaskActivity.java

package com.practice.day_12_5_practiceinitiating.singletask;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.practice.day_12_5_practiceinitiating.R;
import com.practice.day_12_5_practiceinitiating.utils.BaseActivity;
import com.practice.day_12_5_practiceinitiating.utils.ViewFindUtils;

public class OtherTaskActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_other_task);

        View view = getWindow().getDecorView();

        Button btnSingleTask = ViewFindUtils.find(view, R.id.back_singleTask);

        btnSingleTask.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(OtherTaskActivity.this, SingleTaskActivity.class));
            }
        });

    }
}

这时我们使用SingleTop相同的操作步骤,先从MainActivity中进入SingleTaskActivity中,在进入OtherTaskActivity中,然后再跳到SingleTaskActivity中,查看日志信息。

I/Liang_Demo: *****onCreate()方法******
I/Liang_Demo: onCreate:MainActivity TaskId: 331 hasCode:719987172
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating
I/Liang_Demo: *****onCreate()方法******
I/Liang_Demo: onCreate:SingleTaskActivity TaskId: 331 hasCode:596104160
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating
I/Liang_Demo: *****onCreate()方法******
I/Liang_Demo: onCreate:OtherTaskActivity TaskId: 331 hasCode:721013962
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating
I/Liang_Demo: *****onNewIntent()方法*****
I/Liang_Demo: onNewIntent:SingleTaskActivity TaskId: 331 hasCode:596104160
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating
I/Liang_Demo: *****onNewIntent()方法*****
I/Liang_Demo: onNewIntent:SingleTaskActivity TaskId: 331 hasCode:596104160
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating

当我们从MainActivity中进入到SingleTaskActivity中,然后再进入OtherTaskActivity中,这是我们知道Task中存在三个Activity的实例,并且SingleTaskActivity不再Task的顶部,而当我们从OtherTaskActivity跳到SingleTaskActivity中的时候Task并没有创建一个新的Activity,而是复用了之前的已经存在过的实例,并且回调了onNewIntent方法。原来OtherTaskActivity已经出栈了,这是我们查看命令信息。使用命令adb shell dumpsys activity activites

    Running activities (most recent first):
      TaskRecord{bcab529 #331 A=com.practice.day_12_5_practiceinitiating U=0 sz=2}
        Run #1: ActivityRecord{61b9605 u0 com.practice.day_12_5_practiceinitiating/.singletask.SingleTaskActivity t331}
        Run #0: ActivityRecord{27da4a23 u0 com.practice.day_12_5_practiceinitiating/.MainActivity t331}

我们可以观察到栈中只有两个Activity,所以OtherTaskActivity已经出栈了。
我们之前说过,这其中存在一个匹配栈的过程,是通过TaskAffinity属性来查找的。其实是这样的,我们并没有指定taskAffinity属性,这说明和默认值一样,也就是包名,当MainActivity启动时创建的Task的名字就是包名,因为MainActivity也没有指定taskAffinity,而当我们启动SingleTaskActivity ,首先会寻找需要的任务栈是否存在,也就是taskAffinity指定的值,这里就是包名,发现存在,就不再创建新的task,而是直接使用。当该task中存在该Activity实例时就会复用该实例,这就是栈内复用模式。
这时候,如果我们指定SingleTaskActivity 的taskAffinity值。

 <activity
            android:name=".singletask.SingleTaskActivity"
            android:launchMode="singleTask"
           android:taskAffinity="com.practice.day_12_5_practiceinitiating.singletask"
            />

操作步骤同上

I/Liang_Demo: *****onCreate()方法******
I/Liang_Demo: onCreate:MainActivity TaskId: 332 hasCode:719987172
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating
I/Liang_Demo: *****onCreate()方法******
I/Liang_Demo: onCreate:SingleTaskActivity TaskId: 333 hasCode:596104160
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating.singletask
I/Liang_Demo: *****onCreate()方法******
I/Liang_Demo: onCreate:OtherTaskActivity TaskId: 333 hasCode:721013962
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating
I/Liang_Demo: *****onNewIntent()方法*****
I/Liang_Demo: onNewIntent:SingleTaskActivity TaskId: 333 hasCode:596104160
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating.singletask
I/Liang_Demo: *****onNewIntent()方法*****
I/Liang_Demo: onNewIntent:SingleTaskActivity TaskId: 333 hasCode:596104160
I/Liang_Demo: taskAffinity:com.practice.day_12_5_practiceinitiating.singletask

我们看到SingleTaskActivity所属的任务栈的TaskId发生了变换,也就是说开启了一个新的Task,并且之后的OtherActivity也运行在了该Task上
打印出信息也证明了存在两个不同的Task


    Running activities (most recent first):
      TaskRecord{136e7194 #333 A=com.practice.day_12_5_practiceinitiating.singletask U=0 sz=1}
        Run #1: ActivityRecord{3927407a u0 com.practice.day_12_5_practiceinitiating/.singletask.SingleTaskActivity t333}
      TaskRecord{423b432 #332 A=com.practice.day_12_5_practiceinitiating U=0 sz=1}
        Run #0: ActivityRecord{3aaeb27d u0 com.practice.day_12_5_practiceinitiating/.MainActivity t332}

当我们将MainActivity中的TaskAffinity属性设置成和SingleTaskActivity一样,通过信息我们可以知道该种情况和第一次默认的时候是一样的。
这时候,就有了下面的结论
singleTask启动模式启动Activity时,首先会根据taskAffinity去寻找当前是否存在一个对应名字的任务栈
如果不存在,则会创建一个新的Task,并创建新的Activity实例入栈到新创建的Task中去
如果存在,则得到该任务栈,查找该任务栈中是否存在该Activity实例
如果存在实例,则将它上面的Activity实例都出栈,然后回调启动的Activity实例的onNewIntent方法
如果不存在该实例,则新建Activity,并入栈
此外,我们可以将两个不同App中的Activity设置为相同的taskAffinity,这样虽然在不同的应用中,但是Activity会被分配到同一个Task中去。

singleInstance-全局唯一模式

该模式具备singleTask模式的所有特性外,与它的区别就是,这种模式下的Activity会单独占用一个Task栈,具有全局唯一性,即整个系统中就这么一个实例,由于栈内复用的特性,后续的请求均不会创建新的Activity实例,除非这个特殊的任务栈被销毁了。以singleInstance模式启动的Activity在整个系统中是单例的,如果在启动这样的Activiyt时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。

配置形式:

 <activity
            android:name=".singletask.OtherTaskActivity"
            android:launchMode="singleInstance" />

使用案例

增加一个Activity
SingleInstanceActivity.java

配置属性如下:
<activity
    android:name=".SingleInstanceActivity"
    android:launchMode="singleInstance">

    <intent-filter>
        <action android:name="com.practice.day_12_5_practiceinitiating.singleinstance" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

使用下面的方式分别在两个应用中启动它

Intent intent = new Intent();
intent.setAction("com.practice.day_12_5_practiceinitiating.singleinstance");
startActivity(intent);

我们看到,第一个应用启动SingleInstanceActivity时,由于系统中不存在该实例,所以新建了一个Task,按home键后,使用另一个App进入该Activity,由于系统中已经存在了一个实例,不会再创建新的Task,直接复用该实例,并且回调onNewIntent方法。可以从他们的hashcode中可以看出这是同一个实例。因此我们可以理解为:SingleInstance模式启动的Activity在系统中具有全局唯一性。

参考链接:http://m.blog.csdn.net/article/details?id=51491074

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值