xUtils框架

一.xUtils框架简介

xUtils 最初源于Afinal框架,进行了大量重构,使得xUtils支持大文件上传,更全面的http请求协议支持(10种谓词),拥有更加灵活的ORM,更多的事件注解支持且不受混淆影响…

xUtils最低兼容android 2.2 (api level 8)。

当前xUtils主要有四大模块:
1.DbUtils模块
2.ViewUtils模块
3.HttpUtils模块
4.BitmapUtils模块

二.DbUtils模块

简介

  • android中的orm框架,一行代码就可以进行增删改查。
  • 支持事务,默认关闭。
  • 可通过注释自定义表名,列名,外键,唯一约束,NOT NULL约束,CHECK约束等(需要混淆的时候请注解表名和列名)。
  • 支持绑定外键,保存实体时外键关联实体自动保存或更新。
  • 自动加载外键关联实体,支持延时加载。
  • 支持链式表达查询,更直观的查询语义。

实例

权限所需

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.xiaofei.app.xutils.MainActivity">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!"
    android:id="@+id/textView" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="添加数据"
    android:id="@+id/button_save"
    android:onClick="saveClick"
    android:layout_below="@+id/textView"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="查询所有"
    android:id="@+id/button_findAll"
    android:onClick="findAllClick"
    android:layout_below="@+id/button_save"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignRight="@+id/button_save"
    android:layout_alignEnd="@+id/button_save" />

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="查找单个"
    android:id="@+id/button"
    android:onClick="selectByClick"
    android:layout_below="@+id/button_findAll"

    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="更新"
    android:onClick="updateClick"
    android:id="@+id/button2"
    android:layout_below="@+id/button"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="删除"
    android:onClick="deleteClick"
    android:id="@+id/button3"
    android:layout_below="@+id/button2"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />
</RelativeLayout>

MainActivity.java

	import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
   	import android.widget.Toast;
    
    import com.lidroid.xutils.DbUtils;
    import com.lidroid.xutils.db.sqlite.Selector;
    import com.lidroid.xutils.db.sqlite.WhereBuilder;
    import com.lidroid.xutils.exception.DbException;

 import java.util.List;

public class MainActivity extends AppCompatActivity {
    DbUtils db;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
     db = DbUtils.create(this,"mydb");
    }

    public void saveClick(View view)
    {
        User user=new User("123456@qq.com","xiaohong");
        try {
            db.save(user);
            Toast.makeText(MainActivity.this,"save success",Toast.LENGTH_LONG).show();
        } catch (DbException e) {
            e.printStackTrace();
        }
    }
    public void findAllClick(View view)
    {
        try {
            List<User> list=db.findAll(User.class);
            for (User u:list)
            {
                System.out.println(u);
            }
        } catch (DbException e) {
            e.printStackTrace();
        }
    }

    public void selectByClick(View view)
    {
        try {
            User user = db.findFirst(Selector.from(User.class).where("name","=","xiaohong"));
        Toast.makeText(this,user.toString(),Toast.LENGTH_LONG).show();
        } catch (DbException e) {
            e.printStackTrace();
        }
    }
  public void updateClick(View view)
  {
      User user=new User();
      user.setId(1);
      user.setEmail("*********@qq.com");
      user.setName("xiaoming");
      try {
          db.update(user,"email","name");
          Toast.makeText(this,"更新成功",Toast.LENGTH_LONG).show();
      } catch (DbException e) {
          e.printStackTrace();
      }

  }

    public void deleteClick(View view)
    {
        try {
            db.delete(User.class, WhereBuilder.b("id","=","1"));
            Toast.makeText(this,"删除成功",Toast.LENGTH_LONG).show();
        } catch (DbException e) {
            e.printStackTrace();
        }
    }

}

User.java

public class User {
    private int id;
    private String name;
    private String email;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public User(String email, String name) {
        this.email = email;
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }

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

    public User() {
    }


    @Override
    public String toString() {
        return "User{" +
                "email='" + email + '\'' +
                ", id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

在这里插入图片描述

三.ViewUtils模块

简介

  • 完全注解方式就可以进行UI绑定和事件绑定。
  • 无需findViewById和setClickListener等。

实例

// xUtils的view注解要求必须提供id,以使代码混淆不受影响。
@ViewInject(R.id.textView)
TextView textView;

//@ViewInject(vale=R.id.textView, parentId=R.id.parentView)
//TextView textView;

@ResInject(id = R.string.label, type = ResType.String)
private String label;

// 取消了之前使用方法名绑定事件的方式,使用id绑定不受混淆影响
// 支持绑定多个id @OnClick({R.id.id1, R.id.id2, R.id.id3})
// or @OnClick(value={R.id.id1, R.id.id2, R.id.id3}, parentId={R.id.pid1, R.id.pid2, R.id.pid3})
// 更多事件支持参见ViewCommonEventListener类和包com.lidroid.xutils.view.annotation.event。
@OnClick(R.id.test_button)
public void testButtonClick(View v) { // 方法签名必须和接口中的要求一致
    ...
}
...
//在Activity中注入:
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    ViewUtils.inject(this); //注入view和事件
    ...
    textView.setText("some text...");
    ...
}
//在Fragment中注入:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.bitmap_fragment, container, false); // 加载fragment布局
    ViewUtils.inject(this, view); //注入view和事件
    ...
}
//在PreferenceFragment中注入:
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    ViewUtils.inject(this, getPreferenceScreen()); //注入view和事件
    ...
}
// 其他重载
// inject(View view);
// inject(Activity activity)
// inject(PreferenceActivity preferenceActivity)
// inject(Object handler, View view)
// inject(Object handler, Activity activity)
// inject(Object handler, PreferenceGroup preferenceGroup)
// inject(Object handler, PreferenceActivity preferenceActivity)

四.HttpUtils模块

简介

  • 支持同步,异步方式的请求
  • 支持大文件上传,上传大文件不会oom;
  • 支持GET,POST,MOVE,COPY,DELETE,HEAD,OPTIONS,TRACE,CONNECT请求;
  • 下载支持301/302重定向,支持设置是否根据Content-Disposition重命名下载的文件;
  • 返回文本内容的请求(默认只启用GET请求)支持缓存,可设置默认过期时间和针对当前请求的过期时间。

实例

所需jar包
在这里插入图片描述
权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

JsonObject.java

import java.util.ArrayList;

public class JsonObject {
    private String login;
    private ArrayList<User> user=new ArrayList<User>();

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public ArrayList<User> getUser() {
        return user;
    }

    public void setUser(ArrayList<User> user) {
        this.user = user;
    }

    @Override
    public String toString() {
        return "JsonObject{" +
                "login='" + login + '\'' +
                ", user=" + user +
                '}';
    }
}

User.java

public class User {
    private int id;
    private String username;
    private String password;
    private String role;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }

    public User(int id,String username, String password, String role) {
       this.id=id;
        this.username = username;
        this.password = password;
        this.role = role;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", role='" + role + '\'' +
                '}';
    }
    public User()
    {

    }
}

MainActivity2.java

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.google.gson.Gson;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.RequestParams;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest;

import java.util.ArrayList;

public class MainActivity2 extends Activity {
 private EditText editText_username;
 private EditText editText_password;
    private Button button_login;
    private TextView textView_info;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        editText_username= (EditText) findViewById(R.id.editText_username);
        editText_password= (EditText) findViewById(R.id.editText_password);
        button_login= (Button) findViewById(R.id.button_login);
        textView_info=(TextView)findViewById(R.id.info);
        button_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String username=editText_username.getText().toString();
                String password=editText_password.getText().toString();
                HttpUtils httpUtils=new HttpUtils();
                String url="http://192.168.1.101:8080/user/LoginServlet";
                RequestParams params=new RequestParams();
          params.addQueryStringParameter("username",username);
          params.addBodyParameter("password",password);
                httpUtils.send(HttpRequest.HttpMethod.POST, url, params, new RequestCallBack<String>() {

                    @Override
                    public void onStart() {
                        super.onStart();
                        textView_info.setText("conn...");
                    }

                    @Override
                    public void onLoading(long total, long current, boolean isUploading) {
                        super.onLoading(total, current, isUploading);
                        if (isUploading) {
                            textView_info.setText("upload: " + current + "/" + total);
                        } else {
                            textView_info.setText("reply: " + current + "/" + total);
                        }
                    }

                    @Override
                    public void onSuccess(ResponseInfo<String> responseInfo) {
                      String result=responseInfo.result;
                        System.out.println(result);
                        Gson gson = new Gson();
                        JsonObject object = gson.fromJson(result, JsonObject.class);
                        ArrayList<User> list=object.getUser();
                        int count=list.size();
                        String username="";
                        for (int i=0;i<count;i++)
                        {

                           username=username+list.get(i).getUsername();
                        }
                        textView_info.setText(username);
                    }

                    @Override
                    public void onFailure(HttpException error, String msg) {
                        textView_info.setText(error.getExceptionCode() + ":" + msg);
                    }
                });
            }
        });
    }


    //用来解析JSON为对象
    public void jsonToObject(String json) {
        Gson gson = new Gson();
        JsonObject object = gson.fromJson(json, JsonObject.class);
       // info.setText(object.toString());
        System.out.println(object.toString());
        textView_info.setText(object.toString());
    }

}

activity_main2.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.xiaofei.app.xutils.MainActivity2">

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/editText_username"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:hint="input username"
        android:layout_alignParentEnd="true" />

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/editText_password"
        android:layout_below="@+id/editText_username"
        android:layout_alignParentLeft="true"
        android:hint="inout password"
        android:layout_alignParentStart="true"
        android:layout_alignRight="@+id/editText_username"
        android:layout_alignEnd="@+id/editText_username" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="登录"
        android:id="@+id/button_login"
        android:layout_below="@+id/editText_password"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignRight="@+id/editText_password"
        android:layout_alignEnd="@+id/editText_password" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="New Text"
        android:id="@+id/info"
        android:layout_below="@+id/button_login"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />
</RelativeLayout>

五.BitmapUtils模块

简介

  • 加载bitmap的时候无需考虑bitmap加载过程中出现的oom和android容器快速滑动时候出现的图片错位等现象;
  • 支持加载网络图片和本地图片;
  • 内存管理使用lru算法,更好的管理bitmap内存;
  • 可配置线程加载线程数量,缓存大小,缓存路径,加载显示动画等…

实例

在这里插入图片描述
在这里插入图片描述
所需jar包
在这里插入图片描述
需要Bmob云服务中存有数据

product.java

import cn.bmob.v3.BmobObject;
import cn.bmob.v3.datatype.BmobFile;

public class product extends BmobObject{
    private String name;
    private BmobFile pic;
    private double price;
    private double discount;
    public product()
    {

    }

    public product(String name, BmobFile pic, double price, double discount) {
        this.name = name;
        this.pic = pic;
        this.price = price;
        this.discount = discount;
    }

    public double getDiscount() {
        return discount;
    }

    public void setDiscount(double discount) {
        this.discount = discount;
    }

    public String getName() {
        return name;
    }

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

    public BmobFile getPic() {
        return pic;
    }

    public void setPic(BmobFile pic) {
        this.pic = pic;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}

ProductListAdapter.java

import android.content.Context;
import android.os.Environment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.lidroid.xutils.BitmapUtils;

import java.util.List;

public class ProductListAdapter extends BaseAdapter {
    private Context context;
    private List<product> products;

    public ProductListAdapter(Context context, List<product> products) {
        this.context = context;
        this.products = products;

    }

    public List<product> getProducts() {
        return products;
    }

    public void setProducts(List<product> products) {
        this.products = products;
    }

    @Override
    public int getCount() {
        return products.size();
    }

    @Override
    public Object getItem(int position) {
        return products.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder vh;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.product_list_item, null);
            vh = new ViewHolder();
            vh.textView_name = (TextView) convertView.findViewById(R.id.textView_name);
            vh.textView_price = (TextView) convertView.findViewById(R.id.textView_price);
            vh.textView_discount = (TextView) convertView.findViewById(R.id.textView_discount);
            vh.imageView_product_image = (ImageView) convertView.findViewById(R.id.imageView_product_image);
            convertView.setTag(vh);
        }
        vh = (ViewHolder) convertView.getTag();
        product p = products.get(position);
        vh.textView_name.setText(p.getName());
        vh.textView_price.setText("¥" + Math.round((p.getPrice() * (p.getDiscount() / 10) * 100.00)) / 100.00);
        vh.textView_discount.setText(String.valueOf(p.getDiscount()) + "折");
       //用于缓存图片文件 Lru算法
        //用于缓存图片文件 Lru算法
        String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/x-utils";
        BitmapUtils bitmapUtils = new BitmapUtils(context, path);
        bitmapUtils.configDefaultBitmapMaxSize(100, 100);
        bitmapUtils.display(vh.imageView_product_image, p.getPic().getFileUrl(context));
        return convertView;
    }

    static class ViewHolder {

        TextView textView_name;
        TextView textView_price;
        TextView textView_discount;
        ImageView imageView_product_image;

    }
}

ProductListActivity.java

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ListView;

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

import cn.bmob.v3.Bmob;
import cn.bmob.v3.BmobQuery;
import cn.bmob.v3.listener.FindListener;

public class ProductListActivity extends AppCompatActivity {

    private ListView productListView;
    private ProductListAdapter pla;
    private List<product> products=new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_product_list);
        // 初始化 Bmob SDK
        // 使用时请将第二个参数Application ID替换成你在Bmob服务器端创建的Application ID
        Bmob.initialize(this, "Application ID");
        productListView=(ListView)findViewById(R.id.product_list_view);
        pla=new ProductListAdapter(ProductListActivity.this,products);
        loadData();
    }
    private void loadData()
    {
        final View loadView=getLayoutInflater().inflate(R.layout.load_data,null);
        productListView.addHeaderView(loadView);
        productListView.setAdapter(pla);
        BmobQuery<product> query=new BmobQuery<>();
        query.findObjects(ProductListActivity.this, new FindListener<product>() {
            @Override
            public void onSuccess(List<product> list) {
                System.out.println(list.size());
                products=list;
                productListView.removeHeaderView(loadView);
                pla.setProducts(products);
                pla.notifyDataSetChanged();
            }

            @Override
            public void onError(int i, String s) {

            }
        });

    }
}

button_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:drawable="@color/colorAccent"
         android:state_pressed="true">
     </item>
    <item android:drawable="@color/colorPrimary"></item>
</selector>

load_data.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleSmall"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="正在玩命加载中..."
        android:id="@+id/textView"/>
</LinearLayout>

product_list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:id="@+id/imageView_product_image"
        android:src="@mipmap/ic_launcher"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignBottom="@+id/button" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="产品标题部分内容"
        android:id="@+id/textView_name"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/imageView_product_image"
        android:layout_toEndOf="@+id/imageView_product_image" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="去购买"
        android:background="@drawable/button_bg"
        android:id="@+id/button"
        android:layout_below="@+id/textView_name"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="¥97.00"
        android:id="@+id/textView_price"
        android:layout_alignBottom="@+id/imageView_product_image"
        android:layout_toRightOf="@+id/imageView_product_image"
        android:layout_toEndOf="@+id/imageView_product_image" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="折扣"
        android:id="@+id/textView_discount"
        android:layout_alignBaseline="@+id/button"
        android:layout_alignBottom="@+id/button"
        android:layout_toRightOf="@+id/textView_name"
        android:layout_toEndOf="@+id/textView_name" />
</RelativeLayout>

activity_product_list.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".ProductListActivity">


    <ListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/product_list_view"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />
</RelativeLayout>
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值