Android GrrenDao的简单使用

我相信,在平时的开发过程中,大家一定会或多或少地接触到 SQLite。然而在使用它时,我们往往需要做许多额外的工作,像编写 SQL 语句与解析查询结果等。所以,适用于 Android 的ORM 框架也就孕育而生,现在市面上主流的框架有 OrmLite、SugarORM、Active Android、Realm 与 GreenDAO。

greenDAO是一种Android数据库ORM(object/relational mapping)框架,与OrmLite、ActiveOrm、LitePal等数据库相比,单位时间内可以插入、更新和查询更多的数据,而且提供了大量的灵活通用接口。


下面直接代码:
package com.Entity;

import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Index;
import org.greenrobot.greendao.annotation.Keep;
import org.greenrobot.greendao.annotation.NotNull;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Property;

/**
 * Created by Administrator on 2018/1/2.
 */
@Entity(generateConstructors = false)
public class Student {
    @Id
    private Long id;
    private String name;
    private int age;
    private String num;
    private String school;
    private String money;
    private Integer mney;

    public int getMney() {
        return mney;
    }

    public void setMney(int mney) {
        this.mney = mney;
    }

    public String getNum() {
        return num;
    }

    public void setNum(String num) {
        this.num = num;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", num='" + num + '\'' +
                ", school='" + school + '\'' +
                ", money='" + money + '\'' +
                '}';
    }

    public Student() {
    }


    @Keep
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }


    public Student(Long id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;

    }

    public Student(Long id, String name, int age, String num) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.num = num;
    }

    public Student(Long id, String name, int age, String num,String school) {
        this.school = school;
        this.name = name;
        this.age = age;
        this.num = num;
        this.id = id;
    }

    public Student(Long id, String name, int age, String num, String school, String money) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.num = num;
        this.school = school;
        this.money = money;
    }

    public Student(Long id, String name, int age, String num, String school, String money, int mney) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.num = num;
        this.school = school;
        this.money = money;
        this.mney = mney;
    }

    @Keep
    public Long getId() {
        return id;
    }

    @Keep
    public void setId(Long id) {
        this.id = id;
    }

    @Keep
    public String getName() {
        return name;
    }


    @Keep
    public void setName(String name) {
        this.name = name;
    }

    @Keep
    public int getAge() {
        return age;
    }

    @Keep
    public void setAge(int age) {
        this.age = age;
    }

    public String getSchool() {
        return this.school;
    }

    public void setSchool(String school) {
        this.school = school;
    }

    public String getMoney() {
        return this.money;
    }

    public void setMoney(String money) {
        this.money = money;
    }

    public void setMney(Integer mney) {
        this.mney = mney;
    }
}
先弄好实体类 当你弄好实体类以后 点击 android studio 上面的Build的MaKe projeck 就会自动生成三个类(这里三个我就不写了 都是自动生成的   下面直接写方法)
package com.MyGreenDao;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;

import com.anye.greendao.gen.DaoMaster;
import com.anye.greendao.gen.DaoSession;


public class DbManager {

    // 是否加密
    public static final boolean ENCRYPTED = true;

    private static final String DB_NAME = "test.db";
    private static DbManager mDbManager;
    private static DaoMaster.DevOpenHelper mDevOpenHelper;
    private static DaoMaster mDaoMaster;
    private static DaoSession mDaoSession;

    private Context mContext;

    private DbManager(Context context) {
        this.mContext = context;
        // 初始化数据库信息
        mDevOpenHelper = new DaoMaster.DevOpenHelper(context, DB_NAME);
        getDaoMaster(context);
        getDaoSession(context);
    }

    public static DbManager getInstance(Context context) {
        if (null == mDbManager) {
            synchronized (DbManager.class) {
                if (null == mDbManager) {
                    mDbManager = new DbManager(context);
                }
            }
        }
        return mDbManager;
    }

    /**
     * 获取可读数据库
     *
     * @param context
     * @return
     */
    public static SQLiteDatabase getReadableDatabase(Context context) {
        if (null == mDevOpenHelper) {
            getInstance(context);
        }
        return mDevOpenHelper.getReadableDatabase();
    }

    /**
     * 获取可写数据库
     *
     * @param context
     * @return
     */
    public static SQLiteDatabase getWritableDatabase(Context context) {
        if (null == mDevOpenHelper) {
            getInstance(context);
        }
        return mDevOpenHelper.getWritableDatabase();
    }

    /**
     * 获取DaoMaster
     *
     * 判断是否存在数据库,如果没有则创建数据库
     * @param context
     * @return
     */
    public static DaoMaster getDaoMaster(Context context) {
        if (null == mDaoMaster) {
            synchronized (DbManager.class) {
                if (null == mDaoMaster) {
                    MyOpenHelper helper = new MyOpenHelper(context,DB_NAME,null);
                    mDaoMaster = new DaoMaster(helper.getWritableDatabase());
                }
            }
        }
        return mDaoMaster;
    }

    /**
     * 获取DaoSession
     *
     * @param context
     * @return
     */
    public static DaoSession getDaoSession(Context context) {
        if (null == mDaoSession) {
            synchronized (DbManager.class) {
                mDaoSession = getDaoMaster(context).newSession();
            }
        }

        return mDaoSession;
    }
}
package com.MyGreenDao;

import android.database.Cursor;
import android.text.TextUtils;
import android.util.Log;

import com.anye.greendao.gen.DaoMaster;

import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.internal.DaoConfig;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;



public class MigrationHelper {

    private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION = "MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS";
    private static MigrationHelper instance;

    public static MigrationHelper getInstance() {
        if (instance == null) {
            instance = new MigrationHelper();
        }
        return instance;
    }

    public void migrate(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {

        generateTempTables(db, daoClasses);
        DaoMaster.dropAllTables(db, true);
        DaoMaster.createAllTables(db,false);
//        createAllTables(db, daoClasses);
        restoreData(db, daoClasses);
    }

    public void createAllTables(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses){
        //创建新表
    }

    /**
     * 生成临时列表
     *
     * @param db
     * @param daoClasses
     */
    private void generateTempTables(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        for (int i = 0; i < daoClasses.length; i++) {
            DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);

            String divider = "";
            String tableName = daoConfig.tablename;
            String tempTableName = daoConfig.tablename.concat("_TEMP");
            ArrayList<String> properties = new ArrayList<>();

            StringBuilder createTableStringBuilder = new StringBuilder();

            createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" (");

            for (int j = 0; j < daoConfig.properties.length; j++) {
                String columnName = daoConfig.properties[j].columnName;

                if (getColumns(db, tableName).contains(columnName)) {
                    properties.add(columnName);

                    String type = null;

                    try {
                        type = getTypeByClass(daoConfig.properties[j].type);
                    } catch (Exception exception) {
                        exception.printStackTrace();
                    }

                    createTableStringBuilder.append(divider).append(columnName).append(" ").append(type);

                    if (daoConfig.properties[j].primaryKey) {
                        createTableStringBuilder.append(" PRIMARY KEY");
                    }

                    divider = ",";
                }
            }
            createTableStringBuilder.append(");");

            db.execSQL(createTableStringBuilder.toString());

            StringBuilder insertTableStringBuilder = new StringBuilder();

            insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" (");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(") SELECT ");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(" FROM ").append(tableName).append(";");

            db.execSQL(insertTableStringBuilder.toString());

        }
    }

    /**
     * 存储新的数据库表 以及数据
     *
     * @param db
     * @param daoClasses
     */
    private void restoreData(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        for (int i = 0; i < daoClasses.length; i++) {
            DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
            String tableName = daoConfig.tablename;
            String tempTableName = daoConfig.tablename.concat("_TEMP");
            ArrayList<String> properties = new ArrayList();
            ArrayList<String> all = new ArrayList();

            for (int j = 0; j < daoConfig.properties.length; j++) {
                String columnName = daoConfig.properties[j].columnName;

                if (getColumns(db, tempTableName).contains(columnName)) {
                    properties.add(columnName);
                }
                all.add(columnName);
            }

            StringBuilder insertTableStringBuilder = new StringBuilder();



            insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" (");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(") SELECT ");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";");

            StringBuilder dropTableStringBuilder = new StringBuilder();
            dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);
            String sql = insertTableStringBuilder.toString();
            Log.w("dddddd",sql);
            db.execSQL(insertTableStringBuilder.toString());
            db.execSQL(dropTableStringBuilder.toString());
        }
    }

    private String getTypeByClass(Class<?> type) throws Exception {
        if (type.equals(String.class)) {
            return "TEXT";
        }
        if (type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) {
            return "INTEGER";
        }
        if (type.equals(Boolean.class)) {
            return "BOOLEAN";
        }

        Exception exception = new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString()));
        exception.printStackTrace();
        throw exception;
    }

    private List<String> getColumns(Database db, String tableName) {
        List<String> columns = new ArrayList<>();
        Cursor cursor = null;
        try {
            cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null);
            if (cursor != null) {
                columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames()));
            }
        } catch (Exception e) {
            Log.v(tableName, e.getMessage(), e);
            e.printStackTrace();
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return columns;
    }
}
package com.MyGreenDao;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.anye.greendao.gen.DaoMaster;
import com.anye.greendao.gen.StudentDao;

import org.greenrobot.greendao.database.Database;


public class MyOpenHelper extends DaoMaster.OpenHelper {

    public MyOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);
    }

    /**
     * 数据库升级
     * @param db
     * @param oldVersion
     * @param newVersion
     */
    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {
        //操作数据库的更新 有几个表升级都可以传入到下面
        MigrationHelper.getInstance().migrate(db,StudentDao.class);
    }

}
package com.MyGreenDao;

import android.content.Context;

import com.Entity.Student;
import com.anye.greendao.gen.StudentDao;

import org.greenrobot.greendao.query.QueryBuilder;

import java.util.List;


public class StudentDaoOpe {

    /**
     * 添加数据至数据库
     *
     * @param context
     * @param stu
     */
    public static void insertData(Context context, Student stu) {

        DbManager.getDaoSession(context).getStudentDao().insert(stu);
    }


    /**
     * 将数据实体通过事务添加至数据库
     *
     * @param context
     * @param list
     */
    public static void insertData(Context context, List<Student> list) {
        if (null == list || list.size() <= 0) {
            return;
        }
        DbManager.getDaoSession(context).getStudentDao().insertInTx(list);
    }

    /**
     * 添加数据至数据库,如果存在,将原来的数据覆盖
     * 内部代码判断了如果存在就update(entity);不存在就insert(entity)     *
     * @param context
     * @param student
     */
    public static void saveData(Context context, Student student) {
        DbManager.getDaoSession(context).getStudentDao().save(student);
    }

    /**
     * 删除数据至数据库
     *
     * @param context
     * @param student 删除具体内容
     */
    public static void deleteData(Context context, Student student) {
        DbManager.getDaoSession(context).getStudentDao().delete(student);
    }

    /**
     * 根据id删除数据至数据库
     *
     * @param context
     * @param id      删除具体内容
     */
    public static void deleteByKeyData(Context context, long id) {
        DbManager.getDaoSession(context).getStudentDao().deleteByKey(id);
    }

    /**
     * 删除全部数据
     *
     * @param context
     */
    public static void deleteAllData(Context context) {
        DbManager.getDaoSession(context).getStudentDao().deleteAll();
    }

    /**
     * 更新数据库
     *
     * @param context
     * @param student
     */
    public static void updateData(Context context, Student student) {
        DbManager.getDaoSession(context).getStudentDao().update(student);
    }

    /**
     * 查询所有数据
     *
     * @param context
     * @return
     */
    public static List<Student> queryAll(Context context) {
        QueryBuilder<Student> builder = DbManager.getDaoSession(context).getStudentDao().queryBuilder();

        return builder.build().list();
    }

    /**
     * 根据id,其他的字段类似
     *
     * @param context
     * @param id
     * @return
     */
    public static List<Student> queryForId(Context context, long id) {
        QueryBuilder<Student> builder = DbManager.getDaoSession(context).getStudentDao().queryBuilder();
        /**
         * 返回当前id的数据集合,当然where(这里面可以有多组,做为条件);
         * 这里build.list();与where(StudentDao.Properties.Id.eq(id)).list()结果是一样的;
         * QueryBuilder类中list()方法return build().list();
         *
         */
        // Query<Student> build = builder.where(StudentDao.Properties.Id.eq(id)).build();
        // List<Student> list = build.list();
        return builder.where(StudentDao.Properties.Id.eq(id)).list();
    }

    /**
     * 多条件查询
     * @param context
     * @param school
     * @param age
     * @param name
     * @return
     */
    public static List<Student> queryForDob(Context context
            , String school
            ,Integer age
            ,String name) {
        QueryBuilder<Student> builder = DbManager.getDaoSession(context).getStudentDao().queryBuilder();

        return builder.whereOr(
                StudentDao.Properties.Name.eq(name),
                StudentDao.Properties.School.eq(school),
                StudentDao.Properties.Age.eq(age)).list();
    }

    /**
     * 排序
     * @param context
     * @param name
     * @return
     */
    public static List<Student> querySort(Context context,String name) {
        QueryBuilder<Student> builder = DbManager.getDaoSession(context).getStudentDao().queryBuilder();
        return builder.where(StudentDao.Properties.Name.eq(name))
                .orderDesc(StudentDao.Properties.Age).orderDesc(StudentDao.Properties.Mney).list();
    }
}

 
 
package com.MyGreenDao;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.Entity.Student;
import com.myapplication.R;

import java.util.ArrayList;
import java.util.List;

import butterknife.ButterKnife;

public class GreeDaoActivity extends AppCompatActivity implements View.OnClickListener{
    Button insertsingle ;//单个插入
    Button multinsert ;//批量插入数据
    Button update ;//更改某条数据
    Button deletesingle ;//删除某条数据
    Button deleteMult ;//批量删除所有
    Button checksingle ;//查询某条数据
    Button checkmult ;//查询数据集合
    Button checkSchool ;//查询数据集合
    Button querySort ;//排序.
    EditText ed_textView ;//显示数据
    EditText ed_school ;//显示数据
    EditText ed_name ;//显示数据
    StudentDaoOpe myGreeDaoUtils;
    private static final String TAG = "SUN";
    String strUrl =  "http://7xi8d6.com1.z0.glb.clouddn.com/2017-05-05-18251898_1013302395468665_8734429858911748096_n.jpg";
    List<Student> meiziList;
    Long number;
    Integer number1;
    String school;
    String name;
    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        ButterKnife.bind(this);
        setContentView(R.layout.activity_gree_dao);
        insertsingle = (Button) findViewById(R.id.insertsingle);
        multinsert = (Button) findViewById(R.id.multinsert);
        update = (Button) findViewById(R.id.update);
        deletesingle = (Button) findViewById(R.id.deletesingle);
        deleteMult = (Button) findViewById(R.id.deleteMult);
        checksingle = (Button) findViewById(R.id.checksingle);
        checkmult = (Button) findViewById(R.id.checkmult);
        checkSchool = (Button) findViewById(R.id.checkSchool);
        querySort = (Button) findViewById(R.id.querySort);
        ed_textView = (EditText) findViewById(R.id.ed_textView);
        ed_school = (EditText) findViewById(R.id.ed_school);
        ed_name = (EditText) findViewById(R.id.ed_name);


        myGreeDaoUtils = new StudentDaoOpe();
        insertsingle.setOnClickListener(this);
        multinsert.setOnClickListener(this);
        update.setOnClickListener(this);
        deletesingle.setOnClickListener(this);
        deleteMult.setOnClickListener(this);
        checksingle.setOnClickListener(this);
        checkmult.setOnClickListener(this);
        checkSchool.setOnClickListener(this);
        querySort.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.insertsingle:
                myGreeDaoUtils.insertData(this, new Student(null, "Sun", 20, strUrl, "一中", "9000", 20));
                Log.i(TAG, "插入单个数据");
                break;
            case R.id.multinsert:
                meiziList = new ArrayList<>();
                meiziList.add(new Student(null, "Sun", 18,
                        "http://7xi8d648096_n.jpg", "二中", "2800", 50));
                meiziList.add(new Student(null, "Sun", 60,
                        "http://7xi8d648096_n.jpg", "三中", "3200", 30));
                meiziList.add(new Student(null, "Sun", 45,
                        "http://7xi8d648096_n.jpg", "四中", "2500", 10));
                myGreeDaoUtils.insertData(this, meiziList);
                Log.i(TAG, "批量插入数据");
                break;
            case R.id.update:
                Student meizi = new Student();
                meizi.setId(number);
                meizi.setNum("http://baidu.jpg");
                myGreeDaoUtils.updateData(this, meizi);
                Log.i(TAG, "更改某条数据" + number);
                break;
            case R.id.deletesingle:
                myGreeDaoUtils.deleteByKeyData(this, number);
                Log.i(TAG, "删除某条数据" + number);
                break;
            case R.id.deleteMult:
                myGreeDaoUtils.deleteAllData(this);
                Log.i(TAG, "删除所有数据");
                break;
            case R.id.checksingle:
                if (ed_textView != null) {
                    String str = ed_textView.getText().toString();
                    if (str != null && str.length() > 0) {
                        number = Long.valueOf(str);
                    }
                }
                Log.i(TAG, myGreeDaoUtils.queryForId(this, number).toString());
                break;
            case R.id.checkmult:
                List<Student> meiziList1 = myGreeDaoUtils.queryAll(this);
                for (Student meizi2 : meiziList1) {
                    Log.i(TAG, meizi2.toString());
                }
                break;
            case R.id.checkSchool:
                if (ed_textView != null) {
                    String str = ed_textView.getText().toString();
                    if (str != null && str.length() > 0) {
                        number1 = Integer.valueOf(str);
                    }
                    Log.i(TAG, myGreeDaoUtils.queryForDob(this, "二中", number1, "Sun").toString());
                    break;
                }
            case R.id.querySort:
                Log.i(TAG, myGreeDaoUtils.querySort(this,"Sun").toString());
                break;
        }
    }
}
以上就是全部代码  顺便我把XML也贴上:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_gree_dao"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.MyGreenDao.GreeDaoActivity">
    <EditText
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:id="@+id/ed_textView" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:id="@+id/ed_name" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:id="@+id/ed_school" />

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="100dp">

        <Button
            android:id="@+id/insertsingle"
            android:layout_width="0dp"
            android:gravity="center"
            android:layout_height="wrap_content"
            android:text="插入单个数据"
            android:layout_marginTop="5dp"
            android:layout_weight="1"
            android:textSize="20sp"
            />

        <Button
            android:id="@+id/multinsert"

            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:gravity="center"
            android:layout_marginTop="5dp"
            android:text="批量插入数据"/>

    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="100dp">
        <Button
            android:id="@+id/update"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:gravity="center"
            android:layout_height="match_parent"
            android:textSize="20sp"
            android:text="更改某条数据"/>

        <Button
            android:id="@+id/deletesingle"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:gravity="center"
            android:textSize="20sp"
            android:layout_height="match_parent"
            android:text="删除某条数据"/>

        <Button
            android:id="@+id/deleteMult"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:gravity="center"
            android:textSize="20sp"
            android:layout_height="match_parent"
            android:text="批量删除所有"/>
    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="100dp">


        <Button
            android:id="@+id/checksingle"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:gravity="center"
            android:textSize="20sp"
            android:layout_height="match_parent"
            android:text="查询某条数据"/>

        <Button
            android:id="@+id/checkmult"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:gravity="center"
            android:textSize="20sp"
            android:layout_height="match_parent"
            android:text="查询数据集合"/>
        <Button
            android:id="@+id/checkSchool"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:gravity="center"
            android:textSize="20sp"
            android:layout_height="match_parent"
            android:text="多条件查询"/>
    </LinearLayout>
    <Button
        android:id="@+id/querySort"
        android:layout_width="match_parent"
        android:gravity="center"
        android:textSize="20sp"
        android:layout_height="match_parent"
        android:text="排序查询"/>

</LinearLayout>
在升级数据库的时候有个问题: 如果你添加的字段是int类型的 请使用Integer包装类 就不会升级数据库失败 也可以在升级数据的那段代码中写判断 我觉得用Integer就行 这样就不用写过多的代码 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值