Android Activity相关知识总结

本文深入讲解Android中的Activity组件,包括其基本概念、四种状态、生命周期方法及其触发条件,并通过示例代码展示了不同场景下Activity生命周期的变化,同时探讨了数据保存与恢复的方法。

一、 前言
Activity是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播接收器)之一 。
Activity是一个应用程序组件,提供一个屏幕,用户可以用来交互为了完成某项任务。
Activity中所有操作都与用户密切相关,是一个负责与用户交互的组件,可以通过setContentView(View)来显示指定控件。
在一个android应用中,一个Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应。Activity之间通过Intent进行通信。
学习Activity的关键是掌握它的生命周期,四种启动模式,start方式。在这之前还要先了解它的基本状态、Task栈。
二、 基本状态
在android 中,Activity 拥有四种基本状态:
1、Active/Running
一个新 Activity 启动入栈后,它显示在屏幕最前端,处理是处于栈的最顶端(Task栈顶),此时它处于可见并可和用户交互的激活状态,叫做活动状态或者运行状态(active or running)。
2、Paused
当 Activity失去焦点, 被一个新的非全屏的Activity 或者一个透明的Activity 被放置在栈顶,此时的状态叫做暂停状态(Paused)。此时它依然与窗口管理器保持连接,Activity依然保持活力(保持所有的状态,成员信息,和窗口管理器保持连接),但是在系统内存极端低下的时候将被强行终止掉。所以它仍然可见,但已经失去了焦点故不可与用户进行交互。
3、 Stopped
如果一个Activity被另外的Activity完全覆盖掉,叫做停止状态(Stopped)。它依然保持所有状态和成员信息,但是它不再可见,所以它的窗口被隐藏,当系统内存需要被用在其他地方的时候,Stopped的Activity将被强行终止掉。
4、Killed
如果一个Activity是Paused或者Stopped状态,系统可以将该Activity从内存中删除,Android系统采用两种方式进行删除,要么要求该Activity结束,要么直接终止它的进程。当该Activity再次显示给用户时,它必须重新开始和重置前面的状态。
三、 Task栈
Android 是通过一种Task栈的方式来管理 Activity 的,一个 Activity 的实例的状态决定它在栈中的位置。处于前台的 Activity 总是在栈的顶端,当前台的 Activity 因为异常或其它原因被销毁时,处于栈第二层的 Activity 将被激活,上浮到栈顶。当新的 Activity 启动入栈时,原 Activity 会被压入到栈的第二层。一个 Activity 在栈中的位置变化反映了它在不同状态间的转换。Activity的Task栈如下图所示:

这里写图片描述
如上所示,除了最顶层第三个Activity处在 Active 状态的 Activity 外,其它的 Activity 都有可能在系统内存不足时被回收,一个 Activity 的实例越是处在栈的底层,它被系统回收的可能性越大。系统负责管理栈中 Activity 的实例,它根据 Activity 所处的状态来改变其在栈中的位置。
四、 Activity生命周期
1、生命周期6+1方法
简单来说,6+1的组成的模式(6分为三对)
6个常见的生命周期方法:
• onCreate() 当Activity创建时执行
• onStart() 当Activity可见时执行(可见了,但是看不到,没获得焦点)
• onResume() 当Activity获取焦点是执行
• onPause() 当Activity失去焦点时执行
• onStop() 当Activity不可见时执行
• onDestroy() 当Activity销毁时执行
加1就是加上这个:
• onRestart() 当Activity正在重新启动时执行。
就上面的6个常见的生命周期:
为便于记忆它们可以分成三组:
onCreate() 与 onDestroy() 创建和销毁
onStart() 与onStop() 可见和不可见
onResume() 与 onPause() 获取焦点和失去焦点
2、 生命周期流程图
这里写图片描述
Activity生周期流程图
3、生命周期方法逐个分析
最普通的正常的情况下我们点开一个新的Activity,然后关了这个Activity生命周期是这样子走的:
开启一个新的Activity:
执行:onCreate→ onStart→ onResume→ onResume,Activity此时处于运行状态。
关闭这个Activity:
执行:onPause→ onStop→ onDestroy→ onDestroy,此后Activity也就销毁了。
3.1、onCreate()
当Activity被创建时的调用的方法。只在创建的时候调用一次。
可以在这个方法里面做一些初始化的工作,比如setContentView加载布局文件,初始化一些变量的值等。这个是开发中最常见的方法。
3.2、onStart()
Activity已经可见了,但是还没办法进行交互
3.3、 onResume()
Activity已经获取焦点了,Activity处于可见的前台了。用户可以进行交互了,在这个阶段。也可以理解为,必须获取焦点才能进行交互。
假设甲Activity是可见的可交互的,但是这时我们的乙Activity(一个新的非全屏的Activity或者一个透明的Activity)至于栈顶时,即在任务栈里我们的乙位于甲的上方,此刻我们的甲Activity就会处于Paused状态了,也就是可见但是没能进行交互。
3.4、 onPause()
Activity已经失去焦点了。用户没有办法在这个Activity进行操作了。一般来说当用户按下Home键或者按下Back键就会执行这个方法,这个方法执行后紧跟着都是执行onStop()
onPause方法不能进行回收工作,简单说就是这里进行回收工作很可能会拖慢影响其他Activty的显示,后面会涉及到。回收和清理工作轻一点的交给onStop,重一些的交给onDestroy。
3.5、 onStop()
Activity不可见了。在这个方法我们可以进行一些比较简单的回收工作。
3.6、 onDestroy()
Activity被销毁,同时也出栈了。在这里我们可以做一些最终的回收和资源释放的工作。
3.7、 onRestart()
Activity正在重新启动,也就是从不可见变为可见的一个过程。当用户按下Home键然后有回到当前程序,就会执行这个方法,或者当用户从当前甲Activity打开一个新的Activity,然后又back键返回到甲Activity,又或者用户按下任务列表,然后选择了刚刚打开过的那个程序,那么这个方法也会执行。
4、常见的Activity的操作涉及的生命周期
Activity代码定义如图所示:
MainActivity:
public class MainActivity extends Activity {
private static final String TAG=”Lifecycle”;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, “MainActivity onCreate 创建 执行”);
findViewById(R.id.mTvOpen).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,SecondActivity.class));
}
});
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, “MainActivity onStart 可见 执行”);
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, “MainActivity onResume 获取焦点 执行”);
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, “MainActivity onPause 失去焦点 执行”);
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, “MainActivity onStop 不可见 执行”);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, “MainActivity onDestroy 销毁 执行”);
}
// 以上6个 加 另外一个 onRestart
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, “MainActivity onRestart 重新打开Activity”);
}
// 重写两个方法,数据的恢复和保存
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, “MainActivity onSaveInstanceState 保存数据”);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d(TAG, “MainActivity onRestoreInstanceState 恢复数据”);
}
}
SecondActivity:
public class SecondActivity extends Activity{
private static final String TAG=”Lifecycle”;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, “SecondActivity onCreate 创建 执行”);
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, “SecondActivity onStart 可见 执行”);
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, “SecondActivity onResume 获取焦点 执行”);
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, “SecondActivity onPause 失去焦点 执行”);
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, “SecondActivity onStop 不可见 执行”);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, “SecondActivity onDestroy 销毁 执行”);
}
// 以上6个 加 另外一个 onRestart
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, “SecondActivity onRestart 重新打开Activity”);
}
}
这两份代码里面我们在每一个6+1个生命周期的方法都进行了对应的log打印语句,另外,我们还给MainActivity添加了onSaveInstanceState(数据保存)和onRestoreInstanceState(数据恢复)的方法的log打印。
4.1、打开一个全新的Activity
执行:onCreate → onStart → onResume
12-02 22:23:42.052 16933-16933/? D/Lifecycle: MainActivity onCreate 创建 执行
12-02 22:23:42.052 16933-16933/? D/Lifecycle: MainActivity onStart 可见 执行
12-02 22:23:42.052 16933-16933/? D/Lifecycle: MainActivity onResume 获取焦点 执行
4.2、打开一个Activity,接着按下Back键
执行:onCreate → onStart → onResume → onPause → onStop → onDestroy
12-02 22:29:50.100 21748-21748/? D/Lifecycle: MainActivity onCreate 创建 执行
12-02 22:29:50.100 21748-21748/? D/Lifecycle: MainActivity onStart 可见 执行
12-02 22:29:50.100 21748-21748/? D/Lifecycle: MainActivity onResume 获取焦点 执行
12-02 22:29:51.304 21748-21748/com.amqr.activitylifecycle D/Lifecycle: MainActivity onPause 失去焦点 执行
12-02 22:29:51.808 21748-21748/com.amqr.activitylifecycle D/Lifecycle: MainActivity onStop 不可见 执行
12-02 22:29:51.808 21748-21748/com.amqr.activitylifecycle D/Lifecycle: MainActivity onDestroy 销毁 执行
4.3、打开一个Activity,然后按下Home键
打开一个新的Activity:
执行:onCreate → onStart → onResume
按下Home键:
执行:onPause → onStop
12-04 21:41:35.407 9001-9001/com.amqr.activitylifecycle D/Lifecycle: MainActivity onCreate 创建 执行
12-04 21:41:35.407 9001-9001/com.amqr.activitylifecycle D/Lifecycle: MainActivity onStart 可见 执行
12-04 21:41:35.407 9001-9001/com.amqr.activitylifecycle D/Lifecycle: MainActivity onResume 获取焦点 执行

12-04 21:41:36.919 9001-9001/com.amqr.activitylifecycle D/Lifecycle: MainActivity onPause 失去焦点 执行
12-04 21:41:37.415 9001-9001/com.amqr.activitylifecycle D/Lifecycle: MainActivity onSaveInstanceState 保存数据
12-04 21:41:37.415 9001-9001/com.amqr.activitylifecycle D/Lifecycle: MainActivity onStop 不可见 执行
4.4、打开程序A,(启动默认的启动页MainActivity),按下任务列表,重新选择程序A
打开程序A:
执行:onCreate → onStart → onResume
按下任务列表:
执行:onPause → onStop
重新选择程序A:
执行:app:onRestart → onStart → onResume

12-04 21:30:43.979 4670-4670/? D/Lifecycle: MainActivity onCreate 创建 执行
12-04 21:30:43.979 4670-4670/? D/Lifecycle: MainActivity onStart 可见 执行
12-04 21:30:43.979 4670-4670/? D/Lifecycle: MainActivity onResume 获取焦点 执行
// 按下任务列表
12-04 21:30:47.319 4670-4670/com.amqr.activitylifecycle D/Lifecycle: MainActivity onPause 失去焦点 执行
12-04 21:30:47.979 4670-4670/com.amqr.activitylifecycle D/Lifecycle: MainActivity onSaveInstanceState 保存数据
12-04 21:30:47.979 4670-4670/com.amqr.activitylifecycle D/Lifecycle: MainActivity onStop 不可见 执行
// 选择打开app
12-04 21:30:50.811 4670-4670/com.amqr.activitylifecycle D/Lifecycle: MainActivity onRestart 重新打开Activity
12-04 21:30:50.811 4670-4670/com.amqr.activitylifecycle D/Lifecycle: MainActivity onStart 可见 执行
12-04 21:30:50.811 4670-4670/com.amqr.activitylifecycle D/Lifecycle: MainActivity onResume 获取焦点 执行

4.5、打开甲Activity,然后打开乙Activity,接着按下Back键 (注意onPause和onStop之间)
打开甲Activity:
执行:甲onCreate → 甲onStart → 甲onResume
接着打开乙Acitivity:
执行:甲onPause
   → 乙onCreate
   → 乙onStart
   → 乙onResume
→ 甲onStop
(此时界面停留在乙)
接着按下Back键:
执行:乙onPause
   →甲onRestart
   →甲onstart
   →甲onResume
乙onStop
乙Destroy
(此时界面停留在甲)
  在上面的流程中,我们发现,涉及到其他的Activity的时候,其他的Activity的生命周期流程是在上一个Activity的onPause和onStop之间完成的。(注意:不是按部就班等到上一个Activity先执行onPause接着执行onStop之后再执行另外一个Activity的生命周期)
  源码其实也证明了这一点,也就是:旧的Activity必先Pause,接着新的Activity才可以创建。如下所示,MainActivity代表甲,SecondActivity代表乙。
12-04 21:53:10.751 12020-12020/? D/Lifecycle: MainActivity onCreate 创建 执行
12-04 21:53:10.751 12020-12020/? D/Lifecycle: MainActivity onStart 可见 执行
12-04 21:53:10.751 12020-12020/? D/Lifecycle: MainActivity onResume 获取焦点 执行
打开B
12-04 21:53:12.919 12020-12020/com.amqr.activitylifecycle D/Lifecycle: MainActivity onPause 失去焦点 执行
12-04 21:53:12.923 12020-12020/com.amqr.activitylifecycle D/Lifecycle: SecondActivity onCreate 创建 执行
12-04 21:53:12.923 12020-12020/com.amqr.activitylifecycle D/Lifecycle: SecondActivity onStart 可见 执行
12-04 21:53:12.923 12020-12020/com.amqr.activitylifecycle D/Lifecycle: SecondActivity onResume 获取焦点 执行
12-04 21:53:13.315 12020-12020/com.amqr.activitylifecycle D/Lifecycle: MainActivity onSaveInstanceState 保存数据
12-04 21:53:13.315 12020-12020/com.amqr.activitylifecycle D/Lifecycle: MainActivity onStop 不可见 执行
(别看执行是MainActivity的onStop,但是现在停留的界面是B)
// Back
12-04 21:53:22.255 12020-12020/com.amqr.activitylifecycle D/Lifecycle: SecondActivity onPause 失去焦点 执行
12-04 21:53:22.255 12020-12020/com.amqr.activitylifecycle D/Lifecycle: MainActivity onRestart 重新打开Activity
12-04 21:53:22.255 12020-12020/com.amqr.activitylifecycle D/Lifecycle: MainActivity onStart 可见 执行
12-04 21:53:22.255 12020-12020/com.amqr.activitylifecycle D/Lifecycle: MainActivity onResume 获取焦点 执行
12-04 21:53:22.619 12020-12020/com.amqr.activitylifecycle D/Lifecycle: SecondActivity onStop 不可见 执行
12-04 21:53:22.619 12020-12020/com.amqr.activitylifecycle D/Lifecycle: SecondActivity onDestroy 销毁 执行
4.6、打开一个新的Activity,锁屏,解锁屏幕,
打开新的Activity:
执行:onCreate → onStart → onResume
锁屏:
执行:onPause → onStop
解锁:
执行:onRestart → onStart → onResume
12-04 22:02:42.191 15855-15855/com.amqr.activitylifecycle D/Lifecycle: MainActivity onCreate 创建 执行
12-04 22:02:42.191 15855-15855/com.amqr.activitylifecycle D/Lifecycle: MainActivity onStart 可见 执行
12-04 22:02:42.191 15855-15855/com.amqr.activitylifecycle D/Lifecycle: MainActivity onResume 获取焦点 执行
// 锁屏
12-04 22:02:46.951 15855-15855/com.amqr.activitylifecycle D/Lifecycle: MainActivity onPause 失去焦点 执行
12-04 22:02:46.951 15855-15855/com.amqr.activitylifecycle D/Lifecycle: MainActivity onSaveInstanceState 保存数据
12-04 22:02:46.951 15855-15855/com.amqr.activitylifecycle D/Lifecycle: MainActivity onStop 不可见 执行
// 解锁
12-04 22:02:49.291 15855-15855/com.amqr.activitylifecycle D/Lifecycle: MainActivity onRestart 重新打开Activity
12-04 22:02:49.291 15855-15855/com.amqr.activitylifecycle D/Lifecycle: MainActivity onStart 可见 执行
12-04 22:02:49.315 15855-15855/com.amqr.activitylifecycle D/Lifecycle: MainActivity onResume 获取焦点 执行
. 常见的几种操作和生命周期以上都有列举,注意研读生命周期图,掌握Activity生命周期转换的基本逻辑,然后结合案例记忆即可。
特别提示一下:谷歌的文档建议我们不要在onPause做过多的工作,现在通过上面的两个Activity的切换过程我们也是可以理解的。旧的Activity必须先Pause,新的才能onCreate,onStart和onResume,既然这样,为了让新的界面能够快速的显示出来给用户看,那么onPause肯定不能有太多的重量级操作。即:onPause里面不能放耗时操作,否则影响界面切换速度。
五、Activity的正常销毁和异常销毁
1、正常销毁
一个Activity我们通过按下Home键,Back键,或者某一个屏幕的空间我们finish掉都是正常销毁。
2、异常销毁
正常销毁自然是最好的,但是Activity也会有异常销毁的情况,比如下面这两种情况:
• 1、手机横竖屏的切换,Activity被强制撤销重建,那么就算是异常销毁了。
• 2、当前程序为后台进程时,因为系统内存不足给gc回收了。
3、手机横竖屏的Activity异常销毁与SaveInstanceState保存数据
  我们手机横竖屏会导致重走生命周期这点我们肯定已经是知道的了。
  当我们在竖屏的时候往EditText里面填写一些数据,然后在切换到横屏,这时候我们发现重建完的Activity还保留我们在EditText的文本。但是在这个过程中我们开发人员并没有做什么保存数据的操作。那这些为什么数据是怎么保存下来的呢?
其实这就是onSaveInstanceState帮我们做的。说之前我们先来看一下我们熟悉的onCreate的参数。我们在编码的时候复写onCreate是经常的事,每次参数里都有一个bundle,平时有人也许没有多大注意它,其实它干的事情就是在我们的Activity异常销毁的时候帮我们保存数据用的。
代码依然采用上面的提供的生命周期示例演示的MainActivity和SecondActivity的代码。
12-03 02:17:25.388 6883-6883/? D/Lifecycle: MainActivity onCreate 创建 执行
12-03 02:17:25.388 6883-6883/? D/Lifecycle: MainActivity onStart 可见 执行
12-03 02:17:25.388 6883-6883/? D/Lifecycle: MainActivity onResume 获取焦点 执行

12-03 02:17:28.908 6883-6883/com.amqr.activitylifecycle D/Lifecycle: MainActivity onPause 失去焦点 执行
12-03 02:17:28.908 6883-6883/com.amqr.activitylifecycle D/Lifecycle: MainActivity onSaveInstanceState 保存数据
12-03 02:17:28.908 6883-6883/com.amqr.activitylifecycle D/Lifecycle: MainActivity onStop 不可见 执行
12-03 02:17:28.908 6883-6883/com.amqr.activitylifecycle D/Lifecycle: MainActivity onDestroy 销毁 执行

12-03 02:17:28.932 6883-6883/com.amqr.activitylifecycle D/Lifecycle: MainActivity onCreate 创建 执行
12-03 02:17:28.932 6883-6883/com.amqr.activitylifecycle D/Lifecycle: MainActivity onStart 可见 执行
12-03 02:17:28.932 6883-6883/com.amqr.activitylifecycle D/Lifecycle: MainActivity onRestoreInstanceState 恢复数据
12-03 02:17:28.932 6883-6883/com.amqr.activitylifecycle D/Lifecycle: MainActivity onResume 获取焦点 执行
从上面的日志打印中我们知道,由于Activity异常销毁,那么这个时候的onSaveInstanceState和onRestoreInstanceState方法都被执行了。
就是利用这两个方法我们才得以实现数据的保存和恢复的。当我们的程序Activity异常销毁时,那么onSaveInstanceState就会调用,将保存着数据的Bundle对象传递给onRestoreInstanceState和onCreate()方法。利用他们两者一个保存数据一个恢复数据的特点,其实我们可以做很多事,只需要在对应的复写的里面加上对应的逻辑就行。比如我们的存数据在安卓的Application,可能因为程序异常销毁而导致数据丢失,那么这个时候应可以利用这对方法来进行完善了。
onSaveInstanceState和onRestoreInstanceState方法一般都是配对使用的。onSaveInstanceState的作用:当程序的组件被异常销毁时,做一定的数据保存的工作。onRestoreInstanceState的作用:恢复程序被异常的终止时的数据。
3.1、onRestoreInstanceState方法和onCreate的savedInstanceState参数.
onCreate的savedInstanceState参数
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, “SecondActivity onCreate 创建 执行”);
}
onRestoreInstanceState方法
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d(TAG, “MainActivity onRestoreInstanceState 恢复数据”);
}
当Activity被异常销毁时,bundle类型的参数savaInstanceState会保存的数据这个我们已经知道了。
保存没什么可说,恢复却出现了不同。就算我们不复写onRestoreInstanceState方法,也可以利用生命周期的onCreate方法的参数 Bundle savaInstanceState来进行数据恢复。当然如果我们复写onRestoreInstanceState方法,一样可进行数据恢复。两者有什么区别呢?
• 针对onCreate的参数Bundle savedInstanceState有可能为空:
  如果之前Activity的onSaveInstanceState方法没有执行过,那么onCreate的参数Bundle savedInstanceState有可能为空,这样就导致了onCreate的参数Bundle savedInstanceState有可能为空,所以在利用onCreate的参数Bundle savedInstanceState进行数据恢复的时候需要进行参数的非空判断,这个参数不一定是有值的。
• 针对onRestoreInstanceState(推荐):
  如果之前Activity的onSaveInstanceState方法没有执行过,那么onRestoreInstanceState肯定不会执行。也就是说,只要onRestoreInstanceState方法执行,那么之前肯定执行过onSaveInstanceState方法。所以,在onRestoreInstanceState方法进行恢复数据的时候,不需要进行什么非空判断,直接用。
所以:推荐在 onRestoreInstanceState 方法进行数据恢复。(Google也是推荐我们这么做的)
3.2、onSaveInstanceState和onRestoreInstanceState何时执行
 onSaveInstanceState何时执行:
1.当用户按下HOME键时;
  这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道acitvity A是否会被销毁所以系统会调用onSaveInstanceState,让用户有机会保存某些非永久性数据,以下几种分析都遵循该原则。
2.打开任务列表(长按HOME键/长按选项键,因机型而异),按下就执行保存数据;
  因为你按下任务列表,你完全有可能选择其他程序然后玩很久,当前这个程序就被冷落好久了,既然被冷落了,就有可能被gc回收,所以保存数据很正常。
3.从甲Activity 中启动一个新的activity时;
4.屏幕横竖屏切换;
5.锁屏(锁屏会执行onSaveInstanceState,解锁不会执行)
以上说的几种情况全经测试。
 onRestoreInstanceState何时执行:
1.Activity被异常销毁后打开Activity;
2.横竖屏切换后打开Activity;
3.被gc回收后打开Activity。
3.3、题外话android:configChanges切屏后不重走生命周期
可否让程序切换横竖屏时不重走生命周期?
可以的,在Activity的manifest里面的配置加上这么一句:
android:configChanges=”orientation|screenSize”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值