Dagger2 +ButterKnife 框架集成和运用

Android MVP项目搭建(MVP+Dagger2+Butterknife) Android MVP项目的搭建Demo(MVP+Dagger2+Butterknife) 立即下载

Dagger2 是一个注入框架 :简单说就是 对象注入 以前要new 的东西,现在通过Dagger2 直接提供 实现了一定程度的解耦合

一 环境配置 

  dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'

        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
全文如下不细说,注意Butterknife 的原始自动生成代码用的  不是Apt  所以会发生冲突 将他的改成这样就都可以用了
apply plugin: 'com.android.application'
apply plugin: 'com.jakewharton.butterknife'
apply plugin: 'com.neenbedankt.android-apt'
android {
    compileSdkVersion 26
    buildToolsVersion "26.0.1"
    defaultConfig {
        applicationId "com.example.cuizehui.estore"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    //dagger2和butterknife冲突
    packagingOptions{
        exclude 'META-INF/services/javax.annotation.processing.Processor'
    }

}

dependencies {
    apply plugin: 'com.neenbedankt.android-apt'


    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })


   /* apt 'com.google.dagger:dagger-compiler:2.10-rc4'
*/
    //dagger2
    apt 'com.google.dagger:dagger-compiler:2.0'
    compile 'com.google.dagger:dagger:2.0'


    compile 'com.android.support:appcompat-v7:26.+'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'com.android.support:design:26.+'
    compile 'com.android.support:support-v4:26.+'

    //butterknife
    compile 'com.jakewharton:butterknife:8.8.1'
    /*annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
*/
    //只需要改这一句
    apt 'com.jakewharton:butterknife-compiler:+'

    // circleimagerview
    compile 'de.hdodenhof:circleimageview:2.1.0'

    testCompile 'junit:junit:4.12'
    provided 'org.glassfish:javax.annotation:10.0-b28'
}

二 根据框架结构分三层

 Application  -->Activity --> view/fragment  大多数情况下都是这三层
参考文章:
http://www.jianshu.com/p/f4180ad30317

1

Application:  (因为ApplictionComponent 是Activity 的依赖项所以 在生成其他Component 时 需要依赖项的对象)

APPComponet的创建:
public class MyApplication extends Application
{
   
    //全局单例 注入器 并给其他注入器提供依赖
    private ApplicationComponent appComponent;

        @Override
        public void onCreate() {
            super.onCreate();
            initAppComponent();

        }


    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;

    }


    public  void  initAppComponent(){

        appComponent= DaggerApplicationComponent
                .builder()
                .applicationModule(new ApplicationModule(this))
                .build();
    }
    public static MyApplication getInstance(Context context){
        return (MyApplication)context.getApplicationContext();
    }


    public ApplicationComponent getAppComponent(){
            return  appComponent;
    }


}
AppComponent 文件(是一个接口文件 加注释 因为这里使用了单例模式所以依赖项后面要加作用范围 也就是作用域@注解):
package com.example.cuizehui.estore.interfaces;

import android.app.Application;

import com.example.cuizehui.estore.MainActivity;
import com.example.cuizehui.estore.module.ApplicationModule;


import javax.inject.Singleton;

import dagger.Component;

/**
 * Created by cuizehui on 17-9-13.
 * * 注入器
 */
@Singleton
@Component (modules = ApplicationModule.class)
public interface ApplicationComponent {

    Application getApplication();

}

AppModule:文件 只是简单的提供了一个APP对象
package com.example.cuizehui.estore.module;

import android.app.Application;

import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;

@Module
public class ApplicationModule {


    private Application application;

    public ApplicationModule(Application application){
        this.application=application;
    }

    @Provides
    @Singleton
    public Application provideApplication(){
        return application;
    }

}

2

MainActivity:



MainActivityComponet(由于前面的单例依赖项后面要加作用范围 也就是作用域@PreActivity):
package com.example.cuizehui.estore.interfaces;

import com.example.cuizehui.estore.MainActivity;

import com.example.cuizehui.estore.PreActivity;
import com.example.cuizehui.estore.module.MainActivityModule;

import dagger.Component;

/**
 * Created by cuizehui on 17-9-14.
 *
 */
@PreActivity
@Component (modules = MainActivityModule.class,dependencies = ApplicationComponent.class)
public interface MainActivityComponent {
    void inject(MainActivity mainActivity);
}

PreActivity():
package com.example.cuizehui.estore;

import javax.inject.Scope;

@Scope
public @interface PreActivity {
}



MainActivityModule:(这里实现了对一个listview adapter对象的创建和提供)
package com.example.cuizehui.estore.module;

import android.util.Log;

import java.util.ArrayList;

import dagger.Module;
import dagger.Provides;


@Module

public class MainActivityModule {

    //mainActivity 引用的获取  ,方便fragment  获取
    private   MainActivity mainActivity;

    public MainActivityModule(MainActivity mainActivity) {

        this.mainActivity=mainActivity;

    }

    @Provides
    @PreActivity

    MainActivity provideMainActivity() {
        return mainActivity;
    }

    @PreActivity
    @Provides
    public ArrayList<BasePagerView> providePagerViews(){

        ArrayList<BasePagerView>   pagerViews=new ArrayList<>();
        pagerViews.add(new HomepagerView(mainActivity));
        pagerViews.add(new ShopPagerView(mainActivity));
        pagerViews.add(new OrderPagerView(mainActivity));
        pagerViews.add(new MinePagerView(mainActivity));

        return  pagerViews;
    }

    //通过参数的方法 也能进入到上面的代码 获取到对象 ,另外这段代码可以省略和直接在在MainViewPagerAdapter的构造函数中添加注解的效果一至
    @PreActivity
    @Provides
    public MainViewPagerAdapter providemainViewPagerAdapter(ArrayList<BasePagerView> pagerViewslist){
        MainViewPagerAdapter mainViewPagerAdapter=new MainViewPagerAdapter(pagerViewslist);
        return  mainViewPagerAdapter;
    }



}

MainActivityComponet的注入(在MainAcitivity中完成):
   MainActivityComponent  mainActivityComponent= DaggerMainActivityComponent
                .builder()
                .applicationComponent(appComponent)
                .mainActivityModule(new MainActivityModule(this))
                .build();
        mainActivityComponent.inject(this);

这样的注入也可以在BaseActivity 中写好了接口方便 继承BaseActivity的Activity 进行注入,像这样:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base);
        setupActivityComponent(MyApplication.getInstance(this).getAppComponent());
    }



    protected abstract  void setupActivityComponent(ApplicationComponent appComponent);

3

view (普通类)注入

viewModule:
package com.example.cuizehui.estore.module;

import android.content.Context;
import android.util.Log;

import java.util.ArrayList;

import dagger.Module;
import dagger.Provides;

/**
 * Created by cuizehui on 17-9-19.
 */
@Module

public class HomepagerViewModule {
    public MainActivity mainActivity;
    public HomepagerViewModule(MainActivity mainActivity) {
        this.mainActivity=mainActivity;
    }



    @Provides
    public ArrayList<ShopDaTa> provideShopDaTa(){
        ArrayList<ShopDaTa> arrayList=new ArrayList<>();
        //请求拉取数据放到 arraylist中
        //模拟数据
        ShopDaTa shopDaTa1=new ShopDaTa();
        shopDaTa1.setProductName("dfsfd");

        ShopDaTa shopDaTa2=new ShopDaTa();
        shopDaTa1.setProductName("df43fd");
        arrayList.add(shopDaTa1);
        arrayList.add(shopDaTa2);



        return  arrayList ;
    }

    @Provides

    public HomeViewpagerLVAdapter provideLVadpter(ArrayList<ShopDaTa> arrayList){
        Log.d("list.size:",arrayList.size()+"");
        HomeViewpagerLVAdapter homeViewpagerLVAdapter=new HomeViewpagerLVAdapter(arrayList,mainActivity);

        return  homeViewpagerLVAdapter;
    }
}

viewComponet:
package com.example.cuizehui.estore.interfaces;

import dagger.Component;

@Component(modules = HomepagerViewModule.class)
public interface HomePagerViewComponent {
    //注入方法
    void inject(HomepagerView homepagerView);

}

viewComponet 在view中注入:
        HomePagerViewComponent homePagerViewComponent= DaggerHomePagerViewComponent
                .builder()
                .homepagerViewModule(new HomepagerViewModule(mainActivity))
                .build();
        homePagerViewComponent.inject(this);

特别要注意注入一定要在使用之前,还需要注意所传的上下文之间的引用!!

参考文章:
Dagger2 入门:
http://www.jianshu.com/p/1d84ba23f4d2

http://www.jianshu.com/p/cd2c1c9f68d4

Dagger2 封装:

http://blog.youkuaiyun.com/u012702547/article/details/52200927

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0519/2892.html

三 ButterKnife在viewHolder下的bind

.........


 @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ShopDaTa shopDaTa= shopDATAsarrayList.get(i);


        LayoutInflater layoutInflater=LayoutInflater.from(context);
        ViewHolder holder;

        if (view != null) {
            holder = (ViewHolder) view.getTag();
        }
        else {

            view =layoutInflater.inflate(R.layout.shop_data_layout,null);
            holder = new ViewHolder(view);

         //   holder.textView =view.findViewById(R.id.productName_tV);

            view.setTag(holder);
        }

        holder.textView.setText(shopDaTa.getProductName().toString());

        return view;

    }
    //在holder中绑定
    static class ViewHolder {
         @BindView(R.id.productName_tV)
         TextView textView;
        public ViewHolder(View view) {
           ButterKnife.bind(this, view);
        }
    }

参考文章:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0519/2892.html


Nornir自动化简单介绍-网络设备信息收集 作为网工,学会通过执行脚本,可以自动化的完成日常一些设备相关配置或信息收集等工作,可以说是事半功倍。 Nornir就是这样一个自动化网络运维工具。按照官网上的说明: Nornir是用python编写的自动化框架,可与python一起使用。Nornir旨在通过提供一个纯Python框架来解决这些问题。 详细参考: Github GitHub - nornir-automation/nornir: Pluggable multi-threaded framework with inventory . 阅读详情

相关推荐

【数字IC设计】Centos 7桌面版 安装Synopsys EDA Tools

简称DC,是Synopsys公司用于做电路综合的核心工具,可以将HDL描述的电路转换为基于工艺库的门级网表。

qiumingT的博客 9793

解决Dagger2与ButterKnife冲突

发现问题 使用ButterKnife引入Dagger2后发现点击以及控件的查找均失效,主要是butterknife和dagger2都用到了annotation; 解决方法 关于注解的问题[点击跳转](“http://blog.youkuaiyun.com/xx326664162/article/details/68490059“) 按照官方正常配置App的build dependencies {

wei_ai_n的博客 2022

从ISCXTor2016到CICIDS2017:手把手教你下载和使用UNB的网络安全数据集

本文详细介绍了UNB大学发布的ISCXTor2016和CICIDS2017等网络安全数据集的下载与使用方法,特别适合加密流量识别和网络行为分析研究。文章提供了多种高效获取路径、文件结构解析及实战分析示例,帮助研究者快速上手这些真实场景捕获的精细标注数据集。

weixin_42524945的博客 630

依赖注入框架解析

依赖注入使用ButterKnife 在setContentView(..);之后加入ButterKnife.bind(this), @BindView(R.id.testFre)SimpleDraweeView testFre; @BindView(R.id.test)TextView test;Dagger2:场景:想在一个类中使用新建另外一个类,但是又觉得显示创建耦

u011072613的专栏 1024

音视频从入门到精通——指数哥伦布码原理

在计算机中,一般数字的编码都为二进制,但是由于以相等长度来记录不同数字,因此会出现很多的。

mirana的专栏 1381

STM32 LwIP协议栈优化:从TCP延迟10ms降至1ms的内存配置手册

摘要: 本文针对STM32嵌入式开发中LwIP TCP通信的高延迟问题(默认配置下延迟达10~20ms),提出纯软件优化方案,通过调整内存配置与TCP参数将延迟降至1ms。核心问题包括内存池不足、pbuf分配低效及Nagle算法拖累,优化步骤包括: 内存池扩容:增大MEMP_NUM_TCP_PCB至10、PBUF_POOL_SIZE至32,避免资源竞争; pbuf静态池分配:采用2048字节大块缓冲区匹配DMA传输,减少分块与拷贝; 关闭Nagle算法:设置TCP_NODELAY=1,禁用延迟确认以加速小包

weixin_42212753的博客 1707

ButterKnife及Dagger2的使用

ButterKnife ButterKnife的优势 强大的View绑定事件和资源文件的绑定 使用的便捷性上,剔除了原始绑定时候的复杂性 由于大多数的注解都是在编译期,所以不会影响程序运行的效率 代码清晰,可读性相对来说要强很多 ButterKnife的使用 导入依赖:(项目的build.gradle 中) classpath 'com.jakewharton:butterknife-gra...

学海无涯的博客 323

STM32实现任意角度移相全桥PWM

STM32实现任意角度移相全桥PWM,最小分辨率0.5度,频率占空比课任意调节 本文重点在于如何产生任意角度的移相, 两个定时器工作于主从模式,从模式为Gate mode,用第一个定时器触发第二个来实现延时移相

Wind blog 3万+

android 组件化dagger2,Android模块化之ButterKnife和Dagger2的使用

通常来说,我们引入一个第三方库,只需要在OpenSourceLibrary中的gradle文件中添加一个依赖即可,这样任何一个业务module都可以使用该库的功能。但是,有一种库例外,这种库会利用用apt或annotationProcessor生成代码。这种库使用大量使用注解,然后在编译期间生成代码,能够为开发者省很多功夫,比如大名鼎鼎的ButterKnife和Dagger2,涉及到这种库时,在用...

weixin_42491664的博客 350

汇川Easy系列PLC系统PID指令编程应用(增量型)

增量式PIDS7-1200/1500增量式PID(输出归一化、支持PWM输出)_西门子1200pid算法公式-优快云博客文章浏览阅读1k次。本文介绍了S7-1200/1500 PLC中增量式PID算法的应用,包括输出归一化和PWM输出。通过详细解析,阐述了PID输出如何限制在0.0-1.0之间,并且如何将PID输出与PWM占空比关联,适用于温度等控制场景。

RXXW_Dor的博客 1422

手把手教你学Simulink--基于新能源与储能系统的场景实例:压缩空气储能(CAES)系统热力学建模

本文介绍了使用Simulink进行压缩空气储能(CAES)系统热力学建模的详细步骤。系统模型包含压缩机、储气装置、膨胀机、热交换器和控制器等核心模块,通过MATLAB函数计算各部件参数,并设置仿真条件。文章详细说明了从模型创建到性能评估的完整流程,包括压缩/膨胀过程的能量转换、温度压力变化等关键指标分析。该建模方法可验证设计方案的有效性,并为系统优化提供参考,适用于新能源与储能领域的研究与应用。

MHD0815的博客 9173

ButterKnife和dagger2

ButterKnife 注于Android系统的View注入框架,当一个布局十分复杂时,需要引入执行大量的findViewById代码来找到View的对象,有了ButterKnife可以很轻松的省去这些步骤。是大神JakeWharton的力作,目前使用很广。最重要的一点,使用ButterKnife对性能基本没有损失,因为ButterKnife用到的注解并不是在运行时反射的,而是在编译的时候生成新的...

TimPika的博客 526

深入Scrapy ItemLoader:打造优雅高效的Python爬虫数据清洗流水线

ItemLoader是 Scrapy 提供的声明式数据加载工具。它的核心理念是:将数据提取(从response中取原始值)和数据清洗/验证(处理空值、格式转换、默认值等)分离开。你可以把它想象成一个工厂流水线:原始零件(selector提取的文本)进入,经过一道道工序(输入处理器),组装成最终产品(Item字段)。首先在items.py中定义清晰的数据结构。使用搭配类型注释(虽然Scrapy自身不强制,但对人和IDE友好)。

2201_76125261的博客 68

android依赖注入框架Dagger和Butterknife实战

依赖注入(DependencyInjection):在类A中要用到一个B的对象(依赖),需要通过新建B的实例或其他一些主动的方式来获取对象,然后才能调用。而通过外部的方式自动将B的对象分配给A(注入),实现相对被动的获取对象,这个过程称为依赖注入。   控制反转:对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。 依赖注入:

浩大仙的专栏 5371

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

day35mvp架构,dagger2,butterknife的使用

butterKnife框架简介 ButterKnife是一个专注于Android系统的View注入框架,以前总是要写很多findViewById来找到View对象,有了ButterKnife可以很轻松的省去这些步骤。 ButterKnife->针对UI注解类框架 ->设置监听器查找控件 ->省略findviewbyid,setOnclicklistener 1.导入依赖 2.声明...

weixin_44419661的博客 526

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

mvp架构,dagger2,butterknife的使用

mvp架构,dagger2,butterknife的使用butterKnife框架简介ButterKnife的优势ButterKnife的使用dagger2Dagger2是什么?框架说明Dagger2与butterknife区别依赖注入Dagger2注解说明Dagger2基本使用:Dagger2复杂使用:小结 butterKnife框架简介 注于Android系统的View注入框架,当一个布局十分...

SingleTigerkin的博客 581

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

注解与依赖注入框架(ButterKnife 和 Dagger2)

文章目录一、注解分类1.1、标准注解1.2、元注解二、定义注解2.1、基本定义2.2、定义成员变量2.3、定义运行时注解2.4、定义编译时注解2.5、定义源码级注解三、注解处理器 一、注解分类 1.1、标准注解 @Override:对覆盖超类中的方法进行标记,如果被标记的方法并没有实际覆盖超类中的方法,则编译器会发出错误警告。 @Deprecated:对不鼓励使用或者已过时的方法添加注解,当编程人员使用这些方法时,将会在编译时显示提示信息。 @SuppressWarnings:选择性的取消特定代码段中的警

csdn1225987336的专栏 437

Android 依赖注入框架(ButterKnife和Dagger2)

在Android开发中,依赖注入是一种重要的设计模式,它有助于更好地管理和组织应用程序的组件,并提高了代码的可测试性和可维护性。两个常见的Android依赖注入框架是ButterKnife和Dagger 2。

weixin_45568421的博客 546

关于Android依赖注入框架ButterKnife和Dagger的简单比较

最近调研了Android平台可以使用的依赖注入框架。发现现在常用的有四种。Dagger、Butter Knife、RoboGuice、Android Annotations。经过一系列的比较,最后我们的选择 的范围缩小到Dagger、Butter Knife这2个框架上。其实在国内外使用的比较多的应该是Dagger。但是我觉得还是有点复杂了,再看jakewharton的blog时,他也提到了da

极客公园 1万+

Android注解框架Dagger ,Butterknife 和AndroidAnnotations以及RoboGuice的比较

http://stackoverflow.com/questions/24351817/dagger-and-butter-knife-vs-android-annotations 这片文章的答案,简单的介绍了三种注解框架(Dagger,Butterknife以及AA)的异同以及简单的比较。RoboGuice是Google官方的注解框架,不过每个类都需要继承RoboActivity。下面进行客观的

Mrljdx的专栏 2020

Android依赖注入框架终极指南:Dagger vs ButterKnife深度对比

在Android开发中,依赖注入框架是提升开发效率的关键工具。本文将深入对比两大主流框架Dagger与ButterKnife的核心功能、使用场景及性能表现,帮助开发者选择最适合项目需求的解决方案。 ## 📌 什么是依赖注入? 依赖注入(Dependency Injection)是一种设计模式,通过外部注入对象依赖而非内部创建,降低代码耦合度并提升可测试性。在Android开发中,Dagger

gitblog_00019的博客 908

问题:Dagger2和ButterKnife冲突

问题:Dagger2和ButterKnife冲突 他人的解决方案(http://www.cnblogs.com/yizuochengchi2012/p/5659362.html) 我的解决方案: 就是修改Dagger2为: compile ‘com.google.dagger:dagger:2.5’ //apt ‘com.goo

qq_24657021的博客 1609

butterknife、dagger

文章目录ButterKnife1.app-配置2.Module配置3.详细代码Dagger ButterKnife 1.app-配置 1.androidx implementation 'com.jakewharton:butterknife:10.1.0' annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0' 2.其它版本 /** * ButterKnife依赖 */ implementati

amynn的博客 212

Day3:MVP+ButterKnife+Dagger2的使用

Day3:MVP+ButterKnife+Dagger2的使用一.MVP框架1.框架发展过程:2.MVP框架介绍:3.使用MVP的好处:4.结构图:5.目录结构二. lib_core核心库封装1.model层:2.view层:3.presenter层:三. app模块中请求大虾四.ButterKnife的使用1.介绍2.使用(1)依赖:(2)android studio 插件安装:(3)activity中使用(4)fragment中使用:五.Dagger2使用 一.MVP框架 1.框架发展过程: mvc -

qq_34178710的博客 3225

注解(浅谈Dagger,ButterKnife,Roboguide)

花了将近一个星期的时间,把这三个框架都试着用了一下,至于是否实用,我觉得这是仁者见仁,智者见智的事,如果你的技术不够牛掰,那么我建议你用一下ButterKinife就可以了,至于其他两个,用起来确实有些麻烦,并且,可能都不知道它到底怎么运行的. 我们再来谈一下,为什么要用注解?仅仅是为了少些几行代码么?我相信没有程序员不用快捷键的,多几个findViewById应该也不费事吧?很多人说,是

Love_Beauty的博客 1947
上一篇: APP登陆设计 User的全局设置
下一篇: 事件回调 和通知方式的总结(EventBus框架的使用)
Nela
博客等级 码龄11年 9粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值