Full Code of ngu2008/wanandroid for AI

master a42574101ad1 cached
86 files
234.2 KB
62.8k tokens
408 symbols
1 requests
Download .txt
Showing preview only (262K chars total). Download the full file or copy to clipboard to get everything.
Repository: ngu2008/wanandroid
Branch: master
Commit: a42574101ad1
Files: 86
Total size: 234.2 KB

Directory structure:
gitextract_ft2s6f_c/

├── .gitignore
├── .metadata
├── README.md
├── android/
│   ├── app/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── ngu/
│   │           │           └── wanandroidngu/
│   │           │               └── MainActivity.java
│   │           └── res/
│   │               ├── drawable/
│   │               │   └── launch_background.xml
│   │               └── values/
│   │                   └── styles.xml
│   ├── build.gradle
│   ├── gradle/
│   │   └── wrapper/
│   │       └── gradle-wrapper.properties
│   ├── gradle.properties
│   ├── key.properties
│   ├── settings.gradle
│   └── wandroid_ngu.jks
├── interview.md
├── ios/
│   ├── Flutter/
│   │   ├── AppFrameworkInfo.plist
│   │   ├── Debug.xcconfig
│   │   └── Release.xcconfig
│   ├── Runner/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Assets.xcassets/
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   └── LaunchImage.imageset/
│   │   │       ├── Contents.json
│   │   │       └── README.md
│   │   ├── Base.lproj/
│   │   │   ├── LaunchScreen.storyboard
│   │   │   └── Main.storyboard
│   │   ├── Info.plist
│   │   └── main.m
│   ├── Runner.xcodeproj/
│   │   ├── project.pbxproj
│   │   ├── project.xcworkspace/
│   │   │   └── contents.xcworkspacedata
│   │   └── xcshareddata/
│   │       └── xcschemes/
│   │           └── Runner.xcscheme
│   └── Runner.xcworkspace/
│       └── contents.xcworkspacedata
├── lib/
│   ├── app.dart
│   ├── base/
│   │   └── _base_widget.dart
│   ├── common/
│   │   ├── application.dart
│   │   └── user.dart
│   ├── db/
│   │   └── db_helper.dart
│   ├── event/
│   │   ├── change_theme_event.dart
│   │   └── login_event.dart
│   ├── http/
│   │   ├── api.dart
│   │   ├── api_service.dart
│   │   └── dio_manager.dart
│   ├── loading.dart
│   ├── main.dart
│   ├── model/
│   │   ├── article_model.dart
│   │   ├── banner_model.dart
│   │   ├── base_model.dart
│   │   ├── collection_model.dart
│   │   ├── common_websit_model.dart
│   │   ├── common_website_model.dart
│   │   ├── hotword_model.dart
│   │   ├── hotword_result_model.dart
│   │   ├── navi_model.dart
│   │   ├── pretty_model.dart
│   │   ├── project_tree_model.dart
│   │   ├── projectlist_model.dart
│   │   ├── system_tree_content_model.dart
│   │   ├── system_tree_model.dart
│   │   ├── todo_item.dart
│   │   ├── todolist_model.dart
│   │   ├── user_model.dart
│   │   ├── website_collection_model.dart
│   │   ├── wx_article_content_model.dart
│   │   └── wx_article_title_model.dart
│   ├── splash_screen.dart
│   ├── ui/
│   │   ├── drawer/
│   │   │   ├── about.dart
│   │   │   ├── collctions.dart
│   │   │   ├── common_website.dart
│   │   │   ├── drawer.dart
│   │   │   └── pretty.dart
│   │   ├── home/
│   │   │   ├── banner.dart
│   │   │   └── home_page.dart
│   │   ├── knowledge/
│   │   │   ├── knowledge.dart
│   │   │   └── knowledge_content.dart
│   │   ├── login/
│   │   │   └── login_page.dart
│   │   ├── navigation/
│   │   │   └── navigation.dart
│   │   ├── project/
│   │   │   └── project.dart
│   │   ├── public_ui/
│   │   │   └── webview_page.dart
│   │   ├── publicc/
│   │   │   └── publicc.dart
│   │   └── search/
│   │       ├── hot_search_result.dart
│   │       └── search.dart
│   └── util/
│       ├── bubble_indication_painter.dart
│       ├── style_util.dart
│       ├── theme_util.dart
│       └── utils.dart
├── pubspec.yaml
└── test/
    └── widget_test.dart

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Miscellaneous
*.class
*.lock
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# Visual Studio Code related
.vscode/

# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.packages
.pub-cache/
.pub/
build/

# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java

# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*

# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages


================================================
FILE: .metadata
================================================
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
  revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b
  channel: stable

project_type: app


================================================
FILE: README.md
================================================
## Flutter学习资源汇总持续更新中......

- [Flutter官方网站](https://flutter.dev/)
- [Flutter中文网](https://flutterchina.club/)
- wendux的[Flutter实战](https://book.flutterchina.club/)
- Flutter官方example[flutter_gallery](https://github.com/flutter/flutter/tree/master/examples/flutter_gallery)
- [阿里巴巴咸鱼团队系列文章](https://www.yuque.com/xytech/flutter)
- [阿里巴巴flutter-go](https://github.com/alibaba/flutter-go),flutter 开发者帮助 APP,包含 flutter 常用 140+ 组件的demo 演示与中文文档
- [awesome-flutter](https://github.com/Solido/awesome-flutter)包含居多优秀的Flutter库,工具,教程,文章等
- [玩Android跨平台项目](https://www.wanandroid.com/project/list/1?cid=402)
- 非常有用的[Json转Model插件](https://github.com/neverwoodsS/idea_dart_json_format)
- [Flutter-Notebook](https://github.com/OpenFlutter/Flutter-Notebook),提供了很多优秀样例和Demo
- [Flutter-plugins](https://github.com/flutter/plugins),flutter官方插件,提供了众多优秀插件
- 掘金作者[恋猫de小郭系列文章](https://juejin.im/user/582aca2ba22b9d006b59ae68/posts)
## 前言

- 这是一款使用Flutter写的WanAndroid客户端应用,在Android和IOS都完美运行
- ~~可以用来入门Flutter,简单明了,适合初学者~~  
- [项目完全开源](https://github.com/ngu2008/wanandroid_ngu),如果本项目确实能够帮助到你学习Flutter,谢谢start一下,有问题请提交Issues,我会及时回复

## 环境搭建

- 根据[Flutter中文网](https://flutterchina.club/get-started/install)搭建开发环境,使用Android Studio安装Flutter插件,点击pubspec.yaml的package get,然后运行

##  APP下载

- Android[点击下载](https://www.pgyer.com/haFL),或者扫描下方二维码下载

  ![](screenshot/a7.png)
  
- 暂不支持IOS版本下载,请自行clone项目代码运行。

## App目录结构
>- |--lib
>    - |-- main (入口类)
>    - |-- loading (启动页)
>    - |-- splash_screen (引导页)
>    - |-- util (工具类)
>    - |-- base (基类,封装基类BaseWidget和BaseWidgetState)
>    - |-- http (网络请求相关类)
>    - |-- common (常用类)
>    - |-- event (事件类)
>    - |-- model (实体类)
>    - |-- ui (界面相关)
>    - |-- util (工具类)

## 功能介绍

#### V1.5版本

- 常用网站增加数据库[sqflite](https://pub.flutter-io.cn/packages/sqflite)功能
- 修复注册登录按钮颜色与主题色不一致的问题

#### V1.4版本

- 增加切换主题
- 封装基类BaseWidget和BaseWidgetState
- 显示隐藏AppBar
- 增加状态页切换(数据加载中,数据加载失败,空数据)

#### V1.3版本

- 新增搜索和搜索结果列表
- 新增页面正在加载...
- 整个界面UI风格修改

#### V1.2版本

- 新增福利,妹子图,使用[photo_view](https://pub.flutter-io.cn/packages/photo_view),你懂得
- 新增分享[share](https://pub.flutter-io.cn/packages/share)
- 新增常用网站
- 新增关于作者,退出登录

#### V1.1版本

- 新增引导页[flutter-intro-slider](https://github.com/duytq94/flutter-intro-slider)
- 列表页悬浮FloatingActionButton,点击迅速回到顶部
- 新增注册、登录、我的收藏,增加侧滑抽屉,详见截图

#### V1.0版本
- 项目首页、知识体系、公众号、导航、项目、各个页面,和详情页面
- 主要的UI包括首页轮播图和列表,体系流式布局,公众号导航TabBar,以及下拉刷新和加载更多
- 轮播图使用的是开源库[flutter_swiper](https://github.com/best-flutter/flutter_swiper)
- 网络请求使用的是开源库[dio](https://github.com/flutterchina/dio)

## 我的主页
 - [掘金](https://juejin.im/user/5b319afee51d455e2c32fb5b/posts)
 - [CSDN](https://blog.csdn.net/zw2008224044)

## 应用截图

| <img src="/screenshot/b6.jpg" width="280" alt="福利,妹子图"/> | <img src="/screenshot/b2.jpg" width="280" alt="导航页"/> | <img src="/screenshot/b1.jpg" width="280" alt="导航页"/> |
| :--: | :--: | :--: |
| 福利,妹子图 | 导航页 | 导航页 |

| <img src="/screenshot/a0.png" width="280" height="498" alt="登录"/> | <img src="/screenshot/a01.png" width="280" height="498" alt="注册"/> | <img src="/screenshot/b4.jpg" width="280" height="498" alt="分享"/> |
| :--: | :--: | :--: |
| 登录 | 注册 | 分享 |

| <img src="/screenshot/b5.jpg" width="280" height="498" alt="关于作者"/> | <img src="/screenshot/b3.png" width="280" height="498" alt="常用网站"/> | <img src="/screenshot/a02.jpg" width="280" height="498" alt="侧滑抽屉"/> |
| :--: | :--: | :--: |
| 关于作者 | 常用网站 | 侧滑抽屉 |

| <img src="/screenshot/a1.jpg" width="280" height="498" alt="首页"/> | <img src="/screenshot/a2.jpg" width="280" height="498" alt="体系"/> |  <img src="/screenshot/a3.jpg" width="280" height="498" alt="公众号"/> |
| :--: | :--: | :--: |
| 首页 | 体系 | 公众号 |

| <img src="/screenshot/a4.jpg" width="280" height="498" alt="导航"/> | <img src="/screenshot/a5.jpg" width="280" height="498" alt="项目"/> | <img src="/screenshot/a6.jpg" width="280" height="498" alt="基础知识"/> |
| :--: | :--: | :--: |
| 导航 | 项目 | 基础知识 |

| <img src="/screenshot/a8.jpg" width="280" height="498" alt="我的收藏"/> | <img src="/screenshot/a9.jpg" width="280" height="498" alt="详情页"/> |<img src="/screenshot/a10.jpg" width="280" height="498" alt="详情页"/> |
| :--: | :--: |:--: |
| 我的收藏 | 详情页 | 热门搜索 |

| <img src="/screenshot/a11.jpg" width="280" height="498" alt="搜索列表"/> | <img src="/screenshot/b7.png" width="280" height="498" alt="正在加载"/>| <img src="/screenshot/b8.png" width="280" height="498" alt="加载错误"/>|
| :--: | :--: |:--: |
| 搜索列表 | 正在加载 |加载错误 |

| <img src="/screenshot/b9.png" width="280" height="498" alt="正在加载"/>| <img src="/screenshot/b10.png" width="280" height="498" alt="正在加载"/> | |
| :--: | :--: |:--: |
| 数据为空 | 切换主题 |  |

##  感谢

1. 特别感谢github开源作者[shijiacheng](https://github.com/shijiacheng/wanandroid_flutter)
2. 感谢鸿洋大神及[玩Android官网](http://www.wanandroid.com/)提供的[开放API](http://www.wanandroid.com/blog/show/2)
3. 感谢[干货集中营 API](http://gank.io/api)

## 使用开源库

- [shared_preferences](https://pub.dartlang.org/packages/shared_preferences)
- [fluttertoast](https://pub.dartlang.org/packages/fluttertoast)
- [share](https://pub.flutter-io.cn/packages/share)
- [flutter_swiper](https://pub.flutter-io.cn/packages/flutter_swiper)
- [cupertino_icons](https://pub.flutter-io.cn/packages/cupertino_icons)
- [flutter_webview_plugin](https://pub.flutter-io.cn/packages/flutter_webview_plugin)
- [dio](https://pub.flutter-io.cn/packages/dio)
- [flutter-intro-slider](https://github.com/duytq94/flutter-intro-slider)
- [photo_view](https://pub.flutter-io.cn/packages/photo_view)
- [sqflite](https://pub.flutter-io.cn/packages/sqflite)
- [path_provider ](https://pub.flutter-io.cn/packages/path_provider#-installing-tab-)

## 欢迎关注我的微信公众号

  ![](screenshot/wechat.jpg)

================================================
FILE: android/app/build.gradle
================================================
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') { reader ->
        localProperties.load(reader)
    }
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
    flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
    flutterVersionName = '1.0'
}


apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

def keystorePropertiesFile = rootProject.file("key.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))

android {
    compileSdkVersion 28

    lintOptions {
        disable 'InvalidPackage'
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.ngu.wanandroidngu"
        minSdkVersion 16
        targetSdkVersion 28
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
    }

    signingConfigs {
        release {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile file(keystoreProperties['storeFile'])
            storePassword keystoreProperties['storePassword']
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}


flutter {
    source '../..'
}

dependencies {
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
}


================================================
FILE: android/app/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ngu.wanandroidngu">

    <!-- The INTERNET permission is required for development. Specifically,
         flutter needs it to communicate with the running application
         to allow setting breakpoints, to provide hot reload, etc.
    -->
    <uses-permission android:name="android.permission.INTERNET"/>

    <!-- io.flutter.app.FlutterApplication is an android.app.Application that
         calls FlutterMain.startInitialization(this); in its onCreate method.
         In most cases you can leave this as-is, but you if you want to provide
         additional functionality it is fine to subclass or reimplement
         FlutterApplication and put your custom class here. -->
    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="玩安卓ngu"
        android:icon="@mipmap/sun">
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- This keeps the window background of the activity showing
                 until Flutter renders its first frame. It can be removed if
                 there is no splash screen (such as the default splash screen
                 defined in @style/LaunchTheme). -->
            <meta-data
                android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
                android:value="true" />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>


================================================
FILE: android/app/src/main/java/com/ngu/wanandroidngu/MainActivity.java
================================================
package com.ngu.wanandroidngu;

import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GeneratedPluginRegistrant.registerWith(this);
  }
}


================================================
FILE: android/app/src/main/res/drawable/launch_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@android:color/white" />

    <!-- You can insert your own image assets here -->
    <!-- <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/launch_image" />
    </item> -->
</layer-list>


================================================
FILE: android/app/src/main/res/values/styles.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
        <!-- Show a splash screen on the activity. Automatically removed when
             Flutter draws its first frame -->
        <item name="android:windowBackground">@drawable/launch_background</item>
    </style>
</resources>


================================================
FILE: android/build.gradle
================================================
buildscript {
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

rootProject.buildDir = '../build'
subprojects {
    project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
    project.evaluationDependsOn(':app')
}

task clean(type: Delete) {
    delete rootProject.buildDir
}


================================================
FILE: android/gradle/wrapper/gradle-wrapper.properties
================================================
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip


================================================
FILE: android/gradle.properties
================================================
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536M


================================================
FILE: android/key.properties
================================================
storePassword=wandroid_ngu
keyPassword=wandroid_ngu
keyAlias=wandroid_ngu
storeFile=../wandroid_ngu.jks

================================================
FILE: android/settings.gradle
================================================
include ':app'

def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()

def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}

plugins.each { name, path ->
    def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
    include ":$name"
    project(":$name").projectDir = pluginDirectory
}


================================================
FILE: interview.md
================================================
# 一道面试题

> 分享一道面试题,结果有点出乎意料

代码如下:输出结果是什么?

    public class Test {

    public static void main(String[] args) {
        Set<Short> stack = new HashSet<>();
        for (Short i = 0; i < 100; i++) {
            stack.add(i);
            stack.remove(i - 1);
        }
        System.out.println(stack.size());
    }

- 答案是100,i-1这里用到了隐式类型转换i-1会转成int型的减法,所以在remove时,根本没有那个对象,所以无论怎么调stack.remove(i-1)都不会有元素移出,所以答案是100.

================================================
FILE: ios/Flutter/AppFrameworkInfo.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>CFBundleDevelopmentRegion</key>
  <string>en</string>
  <key>CFBundleExecutable</key>
  <string>App</string>
  <key>CFBundleIdentifier</key>
  <string>io.flutter.flutter.app</string>
  <key>CFBundleInfoDictionaryVersion</key>
  <string>6.0</string>
  <key>CFBundleName</key>
  <string>App</string>
  <key>CFBundlePackageType</key>
  <string>FMWK</string>
  <key>CFBundleShortVersionString</key>
  <string>1.0</string>
  <key>CFBundleSignature</key>
  <string>????</string>
  <key>CFBundleVersion</key>
  <string>1.0</string>
  <key>MinimumOSVersion</key>
  <string>8.0</string>
</dict>
</plist>


================================================
FILE: ios/Flutter/Debug.xcconfig
================================================
#include "Generated.xcconfig"


================================================
FILE: ios/Flutter/Release.xcconfig
================================================
#include "Generated.xcconfig"


================================================
FILE: ios/Runner/AppDelegate.h
================================================
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>

@interface AppDelegate : FlutterAppDelegate

@end


================================================
FILE: ios/Runner/AppDelegate.m
================================================
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];
  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end


================================================
FILE: ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "size" : "20x20",
      "idiom" : "iphone",
      "filename" : "Icon-App-20x20@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "20x20",
      "idiom" : "iphone",
      "filename" : "Icon-App-20x20@3x.png",
      "scale" : "3x"
    },
    {
      "size" : "29x29",
      "idiom" : "iphone",
      "filename" : "Icon-App-29x29@1x.png",
      "scale" : "1x"
    },
    {
      "size" : "29x29",
      "idiom" : "iphone",
      "filename" : "Icon-App-29x29@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "29x29",
      "idiom" : "iphone",
      "filename" : "Icon-App-29x29@3x.png",
      "scale" : "3x"
    },
    {
      "size" : "40x40",
      "idiom" : "iphone",
      "filename" : "Icon-App-40x40@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "40x40",
      "idiom" : "iphone",
      "filename" : "Icon-App-40x40@3x.png",
      "scale" : "3x"
    },
    {
      "size" : "60x60",
      "idiom" : "iphone",
      "filename" : "Icon-App-60x60@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "60x60",
      "idiom" : "iphone",
      "filename" : "Icon-App-60x60@3x.png",
      "scale" : "3x"
    },
    {
      "size" : "20x20",
      "idiom" : "ipad",
      "filename" : "Icon-App-20x20@1x.png",
      "scale" : "1x"
    },
    {
      "size" : "20x20",
      "idiom" : "ipad",
      "filename" : "Icon-App-20x20@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "29x29",
      "idiom" : "ipad",
      "filename" : "Icon-App-29x29@1x.png",
      "scale" : "1x"
    },
    {
      "size" : "29x29",
      "idiom" : "ipad",
      "filename" : "Icon-App-29x29@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "40x40",
      "idiom" : "ipad",
      "filename" : "Icon-App-40x40@1x.png",
      "scale" : "1x"
    },
    {
      "size" : "40x40",
      "idiom" : "ipad",
      "filename" : "Icon-App-40x40@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "76x76",
      "idiom" : "ipad",
      "filename" : "Icon-App-76x76@1x.png",
      "scale" : "1x"
    },
    {
      "size" : "76x76",
      "idiom" : "ipad",
      "filename" : "Icon-App-76x76@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "83.5x83.5",
      "idiom" : "ipad",
      "filename" : "Icon-App-83.5x83.5@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "1024x1024",
      "idiom" : "ios-marketing",
      "filename" : "Icon-App-1024x1024@1x.png",
      "scale" : "1x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}


================================================
FILE: ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "universal",
      "filename" : "LaunchImage.png",
      "scale" : "1x"
    },
    {
      "idiom" : "universal",
      "filename" : "LaunchImage@2x.png",
      "scale" : "2x"
    },
    {
      "idiom" : "universal",
      "filename" : "LaunchImage@3x.png",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}


================================================
FILE: ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
================================================
# Launch Screen Assets

You can customize the launch screen with your own desired assets by replacing the image files in this directory.

You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.

================================================
FILE: ios/Runner/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="EHf-IW-A2E">
            <objects>
                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
                        <viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
                            </imageView>
                        </subviews>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <constraints>
                            <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
                            <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
                        </constraints>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="53" y="375"/>
        </scene>
    </scenes>
    <resources>
        <image name="LaunchImage" width="168" height="185"/>
    </resources>
</document>


================================================
FILE: ios/Runner/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
    </dependencies>
    <scenes>
        <!--Flutter View Controller-->
        <scene sceneID="tne-QT-ifu">
            <objects>
                <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
        </scene>
    </scenes>
</document>


================================================
FILE: ios/Runner/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>wanandroid_ngu</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>$(FLUTTER_BUILD_NAME)</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>$(FLUTTER_BUILD_NUMBER)</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UIViewControllerBasedStatusBarAppearance</key>
	<false/>
</dict>
</plist>


================================================
FILE: ios/Runner/main.m
================================================
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char* argv[]) {
  @autoreleasepool {
    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
  }
}


================================================
FILE: ios/Runner.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXBuildFile section */
		1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
		2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; };
		3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
		3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
		3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
		9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
		9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
		9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
		978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
		97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
		97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
		97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
		97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
		9705A1C41CF9048500538489 /* Embed Frameworks */ = {
			isa = PBXCopyFilesBuildPhase;
			buildActionMask = 2147483647;
			dstPath = "";
			dstSubfolderSpec = 10;
			files = (
				3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
				9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
			);
			name = "Embed Frameworks";
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
		1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
		1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
		2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };
		3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
		3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
		7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
		7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
		7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
		9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
		9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
		9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
		97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
		97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
		97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
		97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
		97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
		97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		97C146EB1CF9000F007C117D /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
				3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		9740EEB11CF90186004384FC /* Flutter */ = {
			isa = PBXGroup;
			children = (
				2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
				3B80C3931E831B6300D905FE /* App.framework */,
				3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
				9740EEBA1CF902C7004384FC /* Flutter.framework */,
				9740EEB21CF90195004384FC /* Debug.xcconfig */,
				7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
				9740EEB31CF90195004384FC /* Generated.xcconfig */,
			);
			name = Flutter;
			sourceTree = "<group>";
		};
		97C146E51CF9000F007C117D = {
			isa = PBXGroup;
			children = (
				9740EEB11CF90186004384FC /* Flutter */,
				97C146F01CF9000F007C117D /* Runner */,
				97C146EF1CF9000F007C117D /* Products */,
				CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
			);
			sourceTree = "<group>";
		};
		97C146EF1CF9000F007C117D /* Products */ = {
			isa = PBXGroup;
			children = (
				97C146EE1CF9000F007C117D /* Runner.app */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		97C146F01CF9000F007C117D /* Runner */ = {
			isa = PBXGroup;
			children = (
				7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
				7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
				97C146FA1CF9000F007C117D /* Main.storyboard */,
				97C146FD1CF9000F007C117D /* Assets.xcassets */,
				97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
				97C147021CF9000F007C117D /* Info.plist */,
				97C146F11CF9000F007C117D /* Supporting Files */,
				1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
				1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
			);
			path = Runner;
			sourceTree = "<group>";
		};
		97C146F11CF9000F007C117D /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				97C146F21CF9000F007C117D /* main.m */,
			);
			name = "Supporting Files";
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		97C146ED1CF9000F007C117D /* Runner */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
			buildPhases = (
				9740EEB61CF901F6004384FC /* Run Script */,
				97C146EA1CF9000F007C117D /* Sources */,
				97C146EB1CF9000F007C117D /* Frameworks */,
				97C146EC1CF9000F007C117D /* Resources */,
				9705A1C41CF9048500538489 /* Embed Frameworks */,
				3B06AD1E1E4923F5004D2608 /* Thin Binary */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = Runner;
			productName = Runner;
			productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
			productType = "com.apple.product-type.application";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		97C146E61CF9000F007C117D /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastUpgradeCheck = 0910;
				ORGANIZATIONNAME = "The Chromium Authors";
				TargetAttributes = {
					97C146ED1CF9000F007C117D = {
						CreatedOnToolsVersion = 7.3.1;
					};
				};
			};
			buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
			compatibilityVersion = "Xcode 3.2";
			developmentRegion = English;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
				Base,
			);
			mainGroup = 97C146E51CF9000F007C117D;
			productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				97C146ED1CF9000F007C117D /* Runner */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		97C146EC1CF9000F007C117D /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
				3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
				9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
				97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
				2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
				97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
		3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "Thin Binary";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
		};
		9740EEB61CF901F6004384FC /* Run Script */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "Run Script";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
		};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		97C146EA1CF9000F007C117D /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
				97C146F31CF9000F007C117D /* main.m in Sources */,
				1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXVariantGroup section */
		97C146FA1CF9000F007C117D /* Main.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				97C146FB1CF9000F007C117D /* Base */,
			);
			name = Main.storyboard;
			sourceTree = "<group>";
		};
		97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				97C147001CF9000F007C117D /* Base */,
			);
			name = LaunchScreen.storyboard;
			sourceTree = "<group>";
		};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
		249021D3217E4FDB00AE95B9 /* Profile */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				MTL_ENABLE_DEBUG_INFO = NO;
				SDKROOT = iphoneos;
				TARGETED_DEVICE_FAMILY = "1,2";
				VALIDATE_PRODUCT = YES;
			};
			name = Profile;
		};
		249021D4217E4FDB00AE95B9 /* Profile */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
				DEVELOPMENT_TEAM = S8QB4VV633;
				ENABLE_BITCODE = NO;
				FRAMEWORK_SEARCH_PATHS = (
					"$(inherited)",
					"$(PROJECT_DIR)/Flutter",
				);
				INFOPLIST_FILE = Runner/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				LIBRARY_SEARCH_PATHS = (
					"$(inherited)",
					"$(PROJECT_DIR)/Flutter",
				);
				PRODUCT_BUNDLE_IDENTIFIER = com.ngu.wanandroidNgu;
				PRODUCT_NAME = "$(TARGET_NAME)";
				VERSIONING_SYSTEM = "apple-generic";
			};
			name = Profile;
		};
		97C147031CF9000F007C117D /* Debug */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = dwarf;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_TESTABILITY = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				MTL_ENABLE_DEBUG_INFO = YES;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = iphoneos;
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Debug;
		};
		97C147041CF9000F007C117D /* Release */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_COMMA = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
				CLANG_WARN_STRICT_PROTOTYPES = YES;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				MTL_ENABLE_DEBUG_INFO = NO;
				SDKROOT = iphoneos;
				TARGETED_DEVICE_FAMILY = "1,2";
				VALIDATE_PRODUCT = YES;
			};
			name = Release;
		};
		97C147061CF9000F007C117D /* Debug */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
				ENABLE_BITCODE = NO;
				FRAMEWORK_SEARCH_PATHS = (
					"$(inherited)",
					"$(PROJECT_DIR)/Flutter",
				);
				INFOPLIST_FILE = Runner/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				LIBRARY_SEARCH_PATHS = (
					"$(inherited)",
					"$(PROJECT_DIR)/Flutter",
				);
				PRODUCT_BUNDLE_IDENTIFIER = com.ngu.wanandroidNgu;
				PRODUCT_NAME = "$(TARGET_NAME)";
				VERSIONING_SYSTEM = "apple-generic";
			};
			name = Debug;
		};
		97C147071CF9000F007C117D /* Release */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
			buildSettings = {
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
				ENABLE_BITCODE = NO;
				FRAMEWORK_SEARCH_PATHS = (
					"$(inherited)",
					"$(PROJECT_DIR)/Flutter",
				);
				INFOPLIST_FILE = Runner/Info.plist;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				LIBRARY_SEARCH_PATHS = (
					"$(inherited)",
					"$(PROJECT_DIR)/Flutter",
				);
				PRODUCT_BUNDLE_IDENTIFIER = com.ngu.wanandroidNgu;
				PRODUCT_NAME = "$(TARGET_NAME)";
				VERSIONING_SYSTEM = "apple-generic";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				97C147031CF9000F007C117D /* Debug */,
				97C147041CF9000F007C117D /* Release */,
				249021D3217E4FDB00AE95B9 /* Profile */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				97C147061CF9000F007C117D /* Debug */,
				97C147071CF9000F007C117D /* Release */,
				249021D4217E4FDB00AE95B9 /* Profile */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = 97C146E61CF9000F007C117D /* Project object */;
}


================================================
FILE: ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "group:Runner.xcodeproj">
   </FileRef>
</Workspace>


================================================
FILE: ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "0910"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "97C146ED1CF9000F007C117D"
               BuildableName = "Runner.app"
               BlueprintName = "Runner"
               ReferencedContainer = "container:Runner.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      language = ""
      shouldUseLaunchSchemeArgsEnv = "YES">
      <Testables>
      </Testables>
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
            BuildableName = "Runner.app"
            BlueprintName = "Runner"
            ReferencedContainer = "container:Runner.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
      <AdditionalOptions>
      </AdditionalOptions>
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      language = ""
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
            BuildableName = "Runner.app"
            BlueprintName = "Runner"
            ReferencedContainer = "container:Runner.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
      <AdditionalOptions>
      </AdditionalOptions>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Profile"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "97C146ED1CF9000F007C117D"
            BuildableName = "Runner.app"
            BlueprintName = "Runner"
            ReferencedContainer = "container:Runner.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>


================================================
FILE: ios/Runner.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "group:Runner.xcodeproj">
   </FileRef>
</Workspace>


================================================
FILE: lib/app.dart
================================================
import 'package:flutter/material.dart';
import 'package:wanandroid_ngu/ui/drawer/drawer.dart';
import 'package:wanandroid_ngu/ui/home/home_page.dart';
import 'package:wanandroid_ngu/ui/knowledge/knowledge.dart';
import 'package:wanandroid_ngu/ui/navigation/navigation.dart';
import 'package:wanandroid_ngu/ui/project/project.dart';
import 'package:wanandroid_ngu/ui/publicc/publicc.dart';
import 'package:wanandroid_ngu/ui/search/search.dart';

//应用页面使用有状态Widget
class App extends StatefulWidget {
  App({Key key}) : super(key: key);

  @override
  AppState createState() => AppState();
}

//应用页面状态实现类
class AppState extends State<App> {
  int _selectedIndex = 0; //当前选中项的索引

  final appBarTitles = ['玩Android', '体系', '公众号', '导航', "项目"];
  int elevation = 4;

  var pages = <Widget>[
    HomePage(),
    KnowledgePage(),
    PubliccPage(),
    NavigationPage(),
    ProjectPage()
  ];

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: _onWillPop,
      child: Scaffold(
        drawer: DrawerPage(),
        appBar: AppBar(
          title: new Text(appBarTitles[_selectedIndex]),
          bottom: null,
          elevation: 0,
          actions: <Widget>[
            IconButton(
                icon: Icon(Icons.search),
                onPressed: () {
                  Navigator.of(context)
                      .push(new MaterialPageRoute(builder: (context) {
                    return new SearchPage();
                  }));
                })
          ],
        ),
        body: new IndexedStack(children: pages, index: _selectedIndex),
        //底部导航按钮 包含图标及文本
        bottomNavigationBar: BottomNavigationBar(
          items: <BottomNavigationBarItem>[
            BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('首页')),
            BottomNavigationBarItem(
                icon: Icon(Icons.assignment), title: Text('体系')),
            BottomNavigationBarItem(icon: Icon(Icons.chat), title: Text('公众号')),
            BottomNavigationBarItem(
                icon: Icon(Icons.navigation), title: Text('导航')),
            BottomNavigationBarItem(icon: Icon(Icons.book), title: Text('项目'))
          ],
          type: BottomNavigationBarType.fixed, //设置显示的模式
          currentIndex: _selectedIndex, //当前选中项的索引
          onTap: _onItemTapped, //选择按下处理
        ),
      ),
    );
  }

  //选择按下处理 设置当前索引为index值
  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
      if (index == 2 || index == 4) {
        elevation = 0;
      } else {
        elevation = 4;
      }
    });
  }

  Future<bool> _onWillPop() {
    return showDialog(
          context: context,
          builder: (context) => new AlertDialog(
                title: new Text('提示'),
                content: new Text('确定退出应用吗?'),
                actions: <Widget>[
                  new FlatButton(
                    onPressed: () => Navigator.of(context).pop(false),
                    child: new Text('再看一会'),
                  ),
                  new FlatButton(
                    onPressed: () => Navigator.of(context).pop(true),
                    child: new Text('退出'),
                  ),
                ],
              ),
        ) ??
        false;
  }
}


================================================
FILE: lib/base/_base_widget.dart
================================================
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

abstract class BaseWidget extends StatefulWidget {

  BaseWidgetState baseWidgetState;

  @override
  BaseWidgetState createState() {
    baseWidgetState = getState();
    return baseWidgetState;
  }

  BaseWidgetState getState();
}

abstract class BaseWidgetState<T extends BaseWidget> extends State<T> {
  bool _isAppBarShow = true; //导航栏是否显示

  bool _isErrorWidgetShow = false; //错误信息是否显示
  String _errorContentMesage = "网络请求失败,请检查您的网络";
  String _errImgPath = "images/ic_error.png";

  bool _isLoadingWidgetShow = false;

  bool _isEmptyWidgetShow = false;
  String _emptyWidgetContent = "暂无数据~";
  String _emptyImgPath = "images/ic_empty.png"; //自己根据需求变更

  FontWeight _fontWidget = FontWeight.w600; //错误页面和空页面的字体粗度

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: _getBaseAppBar(),
        body: Container(
          color: Colors.white, //背景颜色,可自己变更
          child: Stack(
            children: <Widget>[
              getContentWidget(context),
              _getBaseErrorWidget(),
              _getBaseEmptyWidget(),
              _getBassLoadingWidget(),
            ],
          ),
        ));
  }

  @override
  void dispose() {
    super.dispose();
  }

  Widget getContentWidget(BuildContext context);

  ///暴露的错误页面方法,可以自己重写定制
  Widget getErrorWidget() {
    return Container(
      //错误页面中心可以自己调整
      padding: EdgeInsets.fromLTRB(0, 0, 0, 80),
      color: Colors.white,
      width: double.infinity,
      height: double.infinity,
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Image(
              image: AssetImage(_errImgPath),
              width: 120,
              height: 120,
            ),
            Container(
              margin: EdgeInsets.fromLTRB(0, 20, 0, 0),
              child: Text(_errorContentMesage,
                  style: TextStyle(
                    color: Colors.grey,
                    fontWeight: _fontWidget,
                  )),
            ),
            Container(
                margin: EdgeInsets.fromLTRB(0, 20, 0, 0),
                child: OutlineButton(
                  child: Text("重新加载",
                      style: TextStyle(
                        color: Colors.grey,
                        fontWeight: _fontWidget,
                      )),
                  onPressed: () => {onClickErrorWidget()},
                ))
          ],
        ),
      ),
    );
  }

  Widget getLoadingWidget() {
    return Center(
        child: CupertinoActivityIndicator(
      radius: 15.0, //值越大加载的图形越大
    ));
  }

  Widget getEmptyWidget() {
    return Container(
      padding: EdgeInsets.fromLTRB(0, 0, 0, 100),
      color: Colors.white,
      width: double.infinity,
      height: double.infinity,
      child: Center(
        child: Container(
          alignment: Alignment.center,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Image(
                color: Colors.black12,
                image: AssetImage(_emptyImgPath),
                width: 150,
                height: 150,
              ),
              Container(
                margin: EdgeInsets.fromLTRB(0, 10, 0, 0),
                child: Text(_emptyWidgetContent,
                    style: TextStyle(
                      color: Colors.grey,
                      fontWeight: _fontWidget,
                    )),
              )
            ],
          ),
        ),
      ),
    );
  }

  PreferredSizeWidget _getBaseAppBar() {
    return PreferredSize(
        child: Offstage(
          offstage: !_isAppBarShow,
          child: getAppBar(),
        ),
        preferredSize: Size.fromHeight(50));
  }

  ///导航栏 appBar
  AppBar getAppBar();

  Widget _getBaseErrorWidget() {
    return Offstage(
      offstage: !_isErrorWidgetShow,
      child: getErrorWidget(),
    );
  }

  Widget _getBassLoadingWidget() {
    return Offstage(
      offstage: !_isLoadingWidgetShow,
      child: getLoadingWidget(),
    );
  }

  Widget _getBaseEmptyWidget() {
    return Offstage(
      offstage: !_isEmptyWidgetShow,
      child: getEmptyWidget(),
    );
  }

  ///点击错误页面后展示内容
  void onClickErrorWidget();

  ///设置错误提示信息
  void setErrorContent(String content) {
    if (content != null) {
      setState(() {
        _errorContentMesage = content;
      });
    }
  }

  ///设置导航栏隐藏或者显示
  void setAppBarVisible(bool isVisible) {
    setState(() {
      _isAppBarShow = isVisible;
    });
  }

  void showContent() {
    setState(() {
      _isEmptyWidgetShow = false;
      _isLoadingWidgetShow = false;
      _isErrorWidgetShow = false;
    });
  }

  void showloading() {
    setState(() {
      _isEmptyWidgetShow = false;
      _isLoadingWidgetShow = true;
      _isErrorWidgetShow = false;
    });
  }

  void showEmpty() {
    setState(() {
      _isEmptyWidgetShow = true;
      _isLoadingWidgetShow = false;
      _isErrorWidgetShow = false;
    });
  }

  void showError() {
    setState(() {
      _isEmptyWidgetShow = false;
      _isLoadingWidgetShow = false;
      _isErrorWidgetShow = true;
    });
  }

  ///设置空页面内容
  void setEmptyWidgetContent(String content) {
    if (content != null) {
      setState(() {
        _emptyWidgetContent = content;
      });
    }
  }

  ///设置错误页面图片
  void setErrorImage(String imagePath) {
    if (imagePath != null) {
      setState(() {
        _errImgPath = imagePath;
      });
    }
  }

  ///设置空页面图片
  void setEmptyImage(String imagePath) {
    if (imagePath != null) {
      setState(() {
        _emptyImgPath = imagePath;
      });
    }
  }
}


================================================
FILE: lib/common/application.dart
================================================
import 'package:event_bus/event_bus.dart';

class Application{
  static EventBus eventBus=new EventBus();
}


================================================
FILE: lib/common/user.dart
================================================
import '../model/user_model.dart';
import 'package:dio/dio.dart';
import 'package:shared_preferences/shared_preferences.dart';

class User {

  static final User singleton = User._internal();

  factory User() {
    return singleton;
  }

  User._internal();

  List<String> cookie;
  String userName;

  void saveUserInfo(UserModel _userModel,Response response){
        List<String> cookies = response.headers["set-cookie"];
        cookie = cookies;
        userName = _userModel.data.username;
        saveInfo();
  }

  Future<Null> getUserInfo() async {
  SharedPreferences sp = await SharedPreferences.getInstance();
  List<String> cookies = sp.getStringList("cookies");
  if (cookies != null) {
    cookie = cookies;
  }

  String username = sp.getString("username");
  if(username!=null){
    userName = username;
  }
}

  saveInfo() async {
    SharedPreferences sp = await SharedPreferences.getInstance();
    sp.setStringList("cookies", cookie);
    sp.setString("username", userName);
  }

  void clearUserInfor(){
    cookie = null;
    userName = null;
    clearInfo();

  }
  
  clearInfo() async {
    SharedPreferences sp = await SharedPreferences.getInstance();
    sp.setStringList("cookies", null);
    sp.setString("username", null);
  }
}


================================================
FILE: lib/db/db_helper.dart
================================================
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'dart:async';
import 'package:path/path.dart';
import 'package:wanandroid_ngu/model/common_websit_model.dart';

class DatabaseHelper {

  static final DatabaseHelper _instance = DatabaseHelper.internal();
  factory DatabaseHelper() => _instance;

  final String tableName = "table_common_web";

  final String columnId = "id";
  final String columnName = "name";
  final String columnlink = "link";
  final String columnIcon = "icon";
  final String columnOrder = "web_order";
  final String columnVisible = "visible";

  static Database _db;

  Future<Database> get db async {
    if (_db != null) {
      return _db;
    }
    _db = await initDb();
    return _db;
  }

  DatabaseHelper.internal();

  initDb() async {
    Directory documentDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentDirectory.path, "wanandroid.db");
    var ourDb = await openDatabase(path, version: 1, onCreate: _onCreate);
    return ourDb;
  }

  //创建数据库表
  void _onCreate(Database db, int version) async {
    await db.execute(
        "create table $tableName($columnId integer primary key,$columnIcon text not null, $columnlink text not null,$columnName text not null , $columnVisible integer not null , $columnOrder integer not null)");
    print("Table is created");
  }

//插入
  Future<int> saveItem(DataListBean item) async {
    var dbClient = await db;
    int res = await dbClient.insert("$tableName", item.toMap());
    print(res.toString());
    return res;
  }

  //查询
  Future<List> getTotalList() async {
    var dbClient = await db;
    var result = await dbClient.rawQuery("SELECT * FROM $tableName ");
    return result.toList();
  }

  //查询总数
  Future<int> getCount() async {
    var dbClient = await db;
    return Sqflite.firstIntValue(await dbClient.rawQuery(
        "SELECT COUNT(*) FROM $tableName"
    ));
  }

//按照id查询
  Future<DataListBean> getItem(int id) async {
    var dbClient = await db;
    var result = await dbClient.rawQuery("SELECT * FROM $tableName WHERE id = $id");
    if (result.length == 0) return null;
    return DataListBean.fromMap(result.first);
  }


  //清空数据
  Future<int> clear() async {
    var dbClient = await db;
    return await dbClient.delete(tableName);
  }


  //根据id删除
  Future<int> deleteItem(int id) async {
    var dbClient = await db;
    return await dbClient.delete(tableName,
        where: "$columnId = ?", whereArgs: [id]);
  }

  //修改
  Future<int> updateItem(DataListBean item) async {
    var dbClient = await db;
    return await dbClient.update("$tableName", item.toMap(),
        where: "$columnId = ?", whereArgs: [item.id]);
  }

  //清空数据库


  //关闭
  Future close() async {
    var dbClient = await db;
    return dbClient.close();
  }
}


================================================
FILE: lib/event/change_theme_event.dart
================================================
import 'package:flutter/material.dart';

class ChangeThemeEvent {

  Color color;

  ChangeThemeEvent(Color c) {
    color = c;
  }
}

================================================
FILE: lib/event/login_event.dart
================================================
class LoginEvent{

}

================================================
FILE: lib/http/api.dart
================================================

class Api{
  static const String HOME_BANNER = "https://www.wanandroid.com/banner/json";

  static const String HOME_ARTICLE_LIST = "https://www.wanandroid.com/article/list/";
  /// 知识体系
  static const String SYSTEM_TREE = "https://www.wanandroid.com/tree/json";
  // 知识体系详情
  static const String SYSTEM_TREE_CONTENT = "https://www.wanandroid.com/article/list/";
  // 公众号名称
  static const String WX_LIST = "https://wanandroid.com/wxarticle/chapters/json";
  // 公众号文章
  static const String WX_ARTICLE_LIST = "https://wanandroid.com/wxarticle/list/";
  // 导航列表数据
  static const String NAVI_LIST = "https://www.wanandroid.com/navi/json";
  // 项目分类
  static const String PROJECT_TREE = "https://www.wanandroid.com/project/tree/json";
  // 项目列表
  static const String PROJECT_LIST = "https://www.wanandroid.com/project/list/";
  // 搜索热词
  static const String SEARCH_HOT_WORD = "https://www.wanandroid.com//hotkey/json";
  // 搜索结果
  static const String SEARCH_RESULT = "https://www.wanandroid.com/article/query/";
  // 用户登录
  static const String USER_LOGIN = "https://www.wanandroid.com/user/login";
  // 用户注册
  static const String USER_REGISTER = "https://www.wanandroid.com/user/register";
  // 收藏列表
  static const String COLLECTION_LIST = "https://www.wanandroid.com/lg/collect/list/";
  //常用网站
  static const String COMMON_WEBSITE = "https://www.wanandroid.com/friend/json";


  // 我的收藏-取消收藏
  static const String CANCEL_COLLECTION = "https://www.wanandroid.com/lg/uncollect/";
  
  // 我的收藏-新增收藏
  static const String ADD_COLLECTION = "https://www.wanandroid.com/lg/collect/add/json";
  // 网站收藏
  static const String WEBSITE_COLLECTION_LIST = "https://www.wanandroid.com/lg/collect/usertools/json";
  // 取消网站收藏
  static const String CANCEL_WEBSITE_COLLECTION = "https://www.wanandroid.com/lg/collect/deletetool/json";
  // 新增网站收藏
  static const String ADD_WEBSITE_COLLECTION = "https://www.wanandroid.com/lg/collect/addtool/json";
  // 编辑网站收藏
  static const String EDIT_WEBSITE_COLLECTION = "https://www.wanandroid.com/lg/collect/updatetool/json";

  // todo列表数据
  static const String TODO_LIST = "https://wanandroid.com/lg/todo/list/";
  // 新增todo数据
  static const String ADD_TODO = "https://www.wanandroid.com/lg/todo/add/json";
  // 更新todo数据
  static const String UPDATE_TODO = "https://www.wanandroid.com/lg/todo/update/";
  // 删除todo数据
  static const String DELETE_TODO = "https://www.wanandroid.com/lg/todo/delete/";
  // 仅更新todo完成状态
  static const String DONE_TODO = "https://www.wanandroid.com/lg/todo/done/";
  
}

================================================
FILE: lib/http/api_service.dart
================================================
import 'package:dio/dio.dart';
import 'package:wanandroid_ngu/common/user.dart';
import 'package:wanandroid_ngu/http/dio_manager.dart';
import 'package:wanandroid_ngu/model/article_model.dart';
import 'package:wanandroid_ngu/model/banner_model.dart';
import 'package:wanandroid_ngu/model/base_model.dart';
import 'package:wanandroid_ngu/model/collection_model.dart';
import 'package:wanandroid_ngu/model/common_websit_model.dart';
import 'package:wanandroid_ngu/model/hotword_result_model.dart';
import 'package:wanandroid_ngu/model/navi_model.dart';
import 'package:wanandroid_ngu/model/pretty_model.dart';
import 'package:wanandroid_ngu/model/projectlist_model.dart';
import 'package:wanandroid_ngu/model/project_tree_model.dart';
import 'package:wanandroid_ngu/model/system_tree_content_model.dart';
import 'package:wanandroid_ngu/model/system_tree_model.dart';
import 'package:wanandroid_ngu/model/todolist_model.dart';
import 'package:wanandroid_ngu/model/user_model.dart';
import 'package:wanandroid_ngu/model/website_collection_model.dart';
import 'package:wanandroid_ngu/model/wx_article_content_model.dart';
import 'package:wanandroid_ngu/model/wx_article_title_model.dart';
import 'package:wanandroid_ngu/model/hotword_model.dart';

import 'api.dart';

class ApiService {
  void getBanner(Function callback) async {
    DioManager.singleton.dio
        .get(Api.HOME_BANNER, options: _getOptions())
        .then((response) {
      callback(BannerModel(response.data));
    });
  }

  void getArticleList(Function callback, Function errorback, int _page) async {
    DioManager.singleton.dio
        .get(Api.HOME_ARTICLE_LIST + "$_page/json", options: _getOptions())
        .then((response) {
      callback(ArticleModel(response.data));
    }).catchError((e) {
      errorback(e);
    });
  }


  /// 获取知识体系列表
  void getSystemTree(Function callback, Function errorback) async {
    DioManager.singleton.dio
        .get(Api.SYSTEM_TREE, options: _getOptions())
        .then((response) {
      callback(SystemTreeModel(response.data));
      }).catchError((e) {
      errorback(e);
    });
  }

  /// 获取知识体系列表详情
  void getSystemTreeContent(Function callback, Function errorback,int _page, int _id) async {
    DioManager.singleton.dio
        .get(Api.SYSTEM_TREE_CONTENT + "$_page/json?cid=$_id",
            options: _getOptions())
        .then((response) {
      callback(SystemTreeContentModel(response.data));
    }).catchError((e) {
      errorback(e);
    });
  }

  /// 获取公众号名称
  void getWxList(Function callback, Function errorback) async {
    DioManager.singleton.dio
        .get(Api.WX_LIST, options: _getOptions())
        .then((response) {
      callback(WxArticleTitleModel(response.data));
      }).catchError((e) {
      errorback(e);
    });
  }

  /// 获取公众号文章
  void getWxArticleList(Function callback, int _id, int _page) async {
    DioManager.singleton.dio
        .get(Api.WX_ARTICLE_LIST + "$_id/$_page/json", options: _getOptions())
        .then((response) {
      callback(WxArticleContentModel(response.data));
    });
  }

  /// 获取导航列表数据
  void getNaviList(Function callback, Function errorback) async {
    DioManager.singleton.dio
        .get(Api.NAVI_LIST, options: _getOptions())
        .then((response) {
      callback(NaviModel(response.data));
    }).catchError((e) {
      errorback(e);
    });
  }

  /// 获取项目分类
  void getProjectTree(Function callback,Function errorback) async {
    DioManager.singleton.dio
        .get(Api.PROJECT_TREE, options: _getOptions())
        .then((response) {
      callback(ProjectTreeModel(response.data));
    }).catchError((e) {
      errorback(e);
    });
  }

  /// 获取项目列表
  void getProjectList(Function callback, int _page, int _id) async {
    DioManager.singleton.dio
        .get(Api.PROJECT_LIST + "$_page/json?cid=$_id", options: _getOptions())
        .then((response) {
      callback(ProjectTreeListModel(response.data));
    });
  }

  /// 获取搜索热词
  void getSearchHotWord(Function callback) async {
    DioManager.singleton.dio
        .get(Api.SEARCH_HOT_WORD, options: _getOptions())
        .then((response) {
      callback(HotwordModel.fromMap(response.data));
    });
  }

  /// 获取搜索结果
  void getSearchResult(Function callback, Function errorback, int _page, String _keyword) async {
    FormData formData = new FormData.from({
      "k": _keyword,
    });
    DioManager.singleton.dio
        .post(Api.SEARCH_RESULT + "$_page/json",
            data: formData, options: _getOptions())
        .then((response) {
      callback(HotwordResultModel.fromMap(response.data));
    }).catchError((e) {
      errorback(e);
    });
  }

  /// 登录
  void login(Function callback, String _username, String _password) async {
    FormData formData =
        new FormData.from({"username": _username, "password": _password});
    DioManager.singleton.dio
        .post(Api.USER_LOGIN, data: formData, options: _getOptions())
        .then((response) {
      callback(UserModel(response.data), response);
    });
  }

  /// 注册
  void register(Function callback, String _username, String _password) async {
    FormData formData = new FormData.from({
      "username": _username,
      "password": _password,
      "repassword": _password
    });
    DioManager.singleton.dio
        .post(Api.USER_REGISTER, data: formData, options: null)
        .then((response) {
      print(response.toString());
      callback(UserModel(response.data));
    });
  }

  /// 获取收藏列表
  void getCollectionList(
      Function callback, Function errorback, int _page) async {
    DioManager.singleton.dio
        .get(Api.COLLECTION_LIST + "$_page/json", options: _getOptions())
        .then((response) {
      callback(CollectionModel(response.data));
    }).catchError((e) {
      errorback(e);
    });
  }

  /// 我的收藏-取消收藏
  void cancelCollection(
      Function callback, Function errorback, int _id, int _originId) async {
    FormData formData = new FormData.from({"originId": _originId});
    DioManager.singleton.dio
        .post(Api.CANCEL_COLLECTION + "$_id/json",
            data: formData, options: _getOptions())
        .then((response) {
      callback(BaseModel(response.data));
    }).catchError((e) {
      errorback(e);
    });
  }




  ///常用网站
  void getCommonWebsite(Function callback, Function errorback) async {
    DioManager.singleton.dio
        .get(Api.COMMON_WEBSITE, options: _getOptions())
        .then((response) {
      callback(CommonWebsitModel.fromMap(response.data));
    }).catchError((e) {
      errorback(e);
    });
  }

  void getPrettyGirl(Function callback, int _page) async {
    DioManager.singleton.dio
        .get("http://gank.io/api/data/福利/10/" + "$_page")
        .then((response) {
      callback(PrettyModel.fromMap(response.data));
    });
  }

  /// 取消网站收藏
  void cancelWebsiteCollectionList(Function callback, int _id) async {
    FormData formData = new FormData.from({
      "id": _id,
    });
    DioManager.singleton.dio
        .post(Api.CANCEL_WEBSITE_COLLECTION,
            data: formData, options: _getOptions())
        .then((response) {
      callback(BaseModel(response.data));
    });
  }


  Options _getOptions() {
    Map<String, String> map = new Map();
    List<String> cookies = User().cookie;
    map["Cookie"] = cookies.toString();
    return Options(headers: map);
  }
}


================================================
FILE: lib/http/dio_manager.dart
================================================
import 'dart:io';

import 'package:dio/dio.dart';

class DioManager {
  Dio _dio;

  DioManager._internal() {
    _dio = new Dio();
    (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
        (client) {
      client.badCertificateCallback =
          (X509Certificate cert, String host, int port) {
        return true;
      };
    };
  }

  static DioManager singleton = DioManager._internal();

  factory DioManager() => singleton;

  get dio {
    return _dio;
  }
}


================================================
FILE: lib/loading.dart
================================================
import 'package:flutter/material.dart';
import 'dart:async';

import 'package:shared_preferences/shared_preferences.dart';
import 'package:wanandroid_ngu/app.dart';

//加载页面
class LoadingPage extends StatefulWidget {
  @override
  _LoadingState createState() => new _LoadingState();
}

class _LoadingState extends State<LoadingPage> {

  @override
  void initState(){
    super.initState();
    //在加载页面停顿2秒
    new Future.delayed(Duration(seconds: 2),(){
      _getHasSkip();
    });
  }

  void _getHasSkip ()async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    bool hasSkip = prefs.getBool("hasSkip");
    if(hasSkip==null||!hasSkip){
      Navigator.of(context).pushReplacementNamed("splash");
    }else {
      Navigator.of(context).pushAndRemoveUntil(
          new MaterialPageRoute(
              builder: (context) => App()),
              (route) => route == null);
    }
  }

  @override
  Widget build(BuildContext context) {
    return new Center(
      child: Stack(
        children: <Widget>[
          //加载页面居中背景图 使用cover模式
          Image.asset("images/loading.png",fit: BoxFit.cover,),
        ],
      ),
    );
  }
}

================================================
FILE: lib/main.dart
================================================
import 'package:flutter/material.dart';
import 'package:wanandroid_ngu/common/application.dart';
import 'package:wanandroid_ngu/common/user.dart';
import 'package:wanandroid_ngu/event/change_theme_event.dart';
import 'package:wanandroid_ngu/splash_screen.dart';
import 'package:wanandroid_ngu/util/theme_util.dart';
import 'package:wanandroid_ngu/util/utils.dart';
import './app.dart';
import './loading.dart';
import 'dart:io';
import 'package:flutter/services.dart';

void main() {
  getLoginInfo();
  runApp(MyApp());
  if (Platform.isAndroid) {
// 以下两行 设置android状态栏为透明的沉浸。写在组件渲染之后,是为了在渲染后进行set赋值,覆盖状态栏,写在渲染之前MaterialApp组件会覆盖掉这个值。
    SystemUiOverlayStyle systemUiOverlayStyle =
        SystemUiOverlayStyle(statusBarColor: Colors.transparent);
    SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
  }
}

Future<Null> getLoginInfo() async {
  User.singleton.getUserInfo();
}

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return MyAppState();
  }
}

class MyAppState extends State<MyApp> {

  Color themeColor = ThemeUtils.currentColorTheme;
  @override
  void initState() {
    super.initState();
    Utils.getColorThemeIndex().then((index) {
      print('color theme index = $index');
      if (index != null) {
        ThemeUtils.currentColorTheme = ThemeUtils.supportColors[index];
        Application.eventBus
            .fire(new ChangeThemeEvent(ThemeUtils.supportColors[index]));
      }
    });

    Application.eventBus.on<ChangeThemeEvent>().listen((event) {
      setState(() {
        themeColor = event.color;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "玩Android",
      debugShowCheckedModeBanner: false,
      theme:
          new ThemeData(primaryColor: themeColor, brightness: Brightness.light),
      routes: <String, WidgetBuilder>{
        "app": (BuildContext context) => new App(),
        "splash": (BuildContext context) => new SplashScreen(),
      },
      home: new LoadingPage(),
    );
  }
}


================================================
FILE: lib/model/article_model.dart
================================================
import 'dart:convert' show json;

class ArticleModel {

  int errorCode;
  String errorMsg;
  Data data;

  ArticleModel.fromParams({this.errorCode, this.errorMsg, this.data});

  factory ArticleModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new ArticleModel.fromJson(json.decode(jsonStr)) : new ArticleModel.fromJson(jsonStr);

  ArticleModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
    data = jsonRes['data'] == null ? null : new Data.fromJson(jsonRes['data']);
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  }
}

class Data {

  int curPage;
  int offset;
  int pageCount;
  int size;
  int total;
  bool over;
  List<Article> datas;

  Data.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});

  Data.fromJson(jsonRes) {
    curPage = jsonRes['curPage'];
    offset = jsonRes['offset'];
    pageCount = jsonRes['pageCount'];
    size = jsonRes['size'];
    total = jsonRes['total'];
    over = jsonRes['over'];
    datas = jsonRes['datas'] == null ? null : [];

    for (var datasItem in datas == null ? [] : jsonRes['datas']){
      datas.add(datasItem == null ? null : new Article.fromJson(datasItem));
    }
  }

  @override
  String toString() {
    return '{"curPage": $curPage,"offset": $offset,"pageCount": $pageCount,"size": $size,"total": $total,"over": $over,"datas": $datas}';
  }
}

class Article {

  int chapterId;
  int courseId;
  int id;
  int publishTime;
  int superChapterId;
  int type;
  int userId;
  int visible;
  int zan;
  bool collect;
  bool fresh;
  String apkLink;
  String author;
  String chapterName;
  String desc;
  String envelopePic;
  String link;
  String niceDate;
  String origin;
  String projectLink;
  String superChapterName;
  String title;
  List<Tag> tags;

  Article.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});

  Article.fromJson(jsonRes) {
    chapterId = jsonRes['chapterId'];
    courseId = jsonRes['courseId'];
    id = jsonRes['id'];
    publishTime = jsonRes['publishTime'];
    superChapterId = jsonRes['superChapterId'];
    type = jsonRes['type'];
    userId = jsonRes['userId'];
    visible = jsonRes['visible'];
    zan = jsonRes['zan'];
    collect = jsonRes['collect'];
    fresh = jsonRes['fresh'];
    apkLink = jsonRes['apkLink'];
    author = jsonRes['author'];
    chapterName = jsonRes['chapterName'];
    desc = jsonRes['desc'];
    envelopePic = jsonRes['envelopePic'];
    link = jsonRes['link'];
    niceDate = jsonRes['niceDate'];
    origin = jsonRes['origin'];
    projectLink = jsonRes['projectLink'];
    superChapterName = jsonRes['superChapterName'];
    title = jsonRes['title'];
    tags = jsonRes['tags'] == null ? null : [];

    for (var tagsItem in tags == null ? [] : jsonRes['tags']){
      tags.add(tagsItem == null ? null : new Tag.fromJson(tagsItem));
    }
  }

  @override
  String toString() {
    return '{"chapterId": $chapterId,"courseId": $courseId,"id": $id,"publishTime": $publishTime,"superChapterId": $superChapterId,"type": $type,"userId": $userId,"visible": $visible,"zan": $zan,"collect": $collect,"fresh": $fresh,"apkLink": ${apkLink != null?'${json.encode(apkLink)}':'null'},"author": ${author != null?'${json.encode(author)}':'null'},"chapterName": ${chapterName != null?'${json.encode(chapterName)}':'null'},"desc": ${desc != null?'${json.encode(desc)}':'null'},"envelopePic": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"niceDate": ${niceDate != null?'${json.encode(niceDate)}':'null'},"origin": ${origin != null?'${json.encode(origin)}':'null'},"projectLink": ${projectLink != null?'${json.encode(projectLink)}':'null'},"superChapterName": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"tags": $tags}';
  }
}

class Tag {

  String name;
  String url;

  Tag.fromParams({this.name, this.url});

  Tag.fromJson(jsonRes) {
    name = jsonRes['name'];
    url = jsonRes['url'];
  }

  @override
  String toString() {
    return '{"name": ${name != null?'${json.encode(name)}':'null'},"url": ${url != null?'${json.encode(url)}':'null'}}';
  }
}



================================================
FILE: lib/model/banner_model.dart
================================================
import 'dart:convert' show json;

class BannerModel {

  int errorCode;
  String errorMsg;
  List<BannerData> data;

  BannerModel.fromParams({this.errorCode, this.errorMsg, this.data});

  factory BannerModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new BannerModel.fromJson(json.decode(jsonStr)) : new BannerModel.fromJson(jsonStr);

  BannerModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
    data = jsonRes['data'] == null ? null : [];

    for (var dataItem in data == null ? [] : jsonRes['data']){
      data.add(dataItem == null ? null : new BannerData.fromJson(dataItem));
    }
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  }
}

class BannerData {

  int id;
  int isVisible;
  int order;
  int type;
  String desc;
  String imagePath;
  String title;
  String url;

  BannerData.fromParams({this.id, this.isVisible, this.order, this.type, this.desc, this.imagePath, this.title, this.url});

  BannerData.fromJson(jsonRes) {
    id = jsonRes['id'];
    isVisible = jsonRes['isVisible'];
    order = jsonRes['order'];
    type = jsonRes['type'];
    desc = jsonRes['desc'];
    imagePath = jsonRes['imagePath'];
    title = jsonRes['title'];
    url = jsonRes['url'];
  }

  @override
  String toString() {
    return '{"id": $id,"isVisible": $isVisible,"order": $order,"type": $type,"desc": ${desc != null?'${json.encode(desc)}':'null'},"imagePath": ${imagePath != null?'${json.encode(imagePath)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"url": ${url != null?'${json.encode(url)}':'null'}}';
  }
}



================================================
FILE: lib/model/base_model.dart
================================================
import 'dart:convert' show json;

class BaseModel {

  int errorCode;
  String errorMsg;

  BaseModel.fromParams({ this.errorCode, this.errorMsg});

  factory BaseModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new BaseModel.fromJson(json.decode(jsonStr)) : new BaseModel.fromJson(jsonStr);
  
  BaseModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'}}';
  }
}



================================================
FILE: lib/model/collection_model.dart
================================================
import 'dart:convert' show json;

class CollectionModel {

  int errorCode;
  String errorMsg;
  CollectionData data;

  CollectionModel.fromParams({this.errorCode, this.errorMsg, this.data});

  factory CollectionModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new CollectionModel.fromJson(json.decode(jsonStr)) : new CollectionModel.fromJson(jsonStr);
  
  CollectionModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
    data = jsonRes['data'] == null ? null : new CollectionData.fromJson(jsonRes['data']);
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  }
}

class CollectionData {

  int curPage;
  int offset;
  int pageCount;
  int size;
  int total;
  bool over;
  List<Collection> datas;

  CollectionData.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});
  
  CollectionData.fromJson(jsonRes) {
    curPage = jsonRes['curPage'];
    offset = jsonRes['offset'];
    pageCount = jsonRes['pageCount'];
    size = jsonRes['size'];
    total = jsonRes['total'];
    over = jsonRes['over'];
    datas = jsonRes['datas'] == null ? null : [];

    for (var datasItem in datas == null ? [] : jsonRes['datas']){
            datas.add(datasItem == null ? null : new Collection.fromJson(datasItem));
    }
  }

  @override
  String toString() {
    return '{"curPage": $curPage,"offset": $offset,"pageCount": $pageCount,"size": $size,"total": $total,"over": $over,"datas": $datas}';
  }
}

class Collection {

  int chapterId;
  int courseId;
  int id;
  int originId;
  int publishTime;
  int userId;
  int visible;
  int zan;
  String author;
  String chapterName;
  String desc;
  String envelopePic;
  String link;
  String niceDate;
  String origin;
  String title;

  Collection.fromParams({this.chapterId, this.courseId, this.id, this.originId, this.publishTime, this.userId, this.visible, this.zan, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.title});
  
  Collection.fromJson(jsonRes) {
    chapterId = jsonRes['chapterId'];
    courseId = jsonRes['courseId'];
    id = jsonRes['id'];
    originId = jsonRes['originId'];
    publishTime = jsonRes['publishTime'];
    userId = jsonRes['userId'];
    visible = jsonRes['visible'];
    zan = jsonRes['zan'];
    author = jsonRes['author'];
    chapterName = jsonRes['chapterName'];
    desc = jsonRes['desc'];
    envelopePic = jsonRes['envelopePic'];
    link = jsonRes['link'];
    niceDate = jsonRes['niceDate'];
    origin = jsonRes['origin'];
    title = jsonRes['title'];
  }

  @override
  String toString() {
    return '{"chapterId": $chapterId,"courseId": $courseId,"id": $id,"originId": ${origin != null?'${json.encode(origin)}':'null'}Id,"publishTime": $publishTime,"userId": $userId,"visible": $visible,"zan": $zan,"author": ${author != null?'${json.encode(author)}':'null'},"chapterName": ${chapterName != null?'${json.encode(chapterName)}':'null'},"desc": ${desc != null?'${json.encode(desc)}':'null'},"envelopePic": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"niceDate": ${niceDate != null?'${json.encode(niceDate)}':'null'},"origin": ${origin != null?'${json.encode(origin)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'}}';
  }
}



================================================
FILE: lib/model/common_websit_model.dart
================================================
class CommonWebsitModel {

  String errorMsg;
  int errorCode;
  List<DataListBean> data;

  static CommonWebsitModel fromMap(Map<String, dynamic> map) {
    CommonWebsitModel common_websit_model = new CommonWebsitModel();
    common_websit_model.errorMsg = map['errorMsg'];
    common_websit_model.errorCode = map['errorCode'];
    common_websit_model.data = DataListBean.fromMapList(map['data']);
    return common_websit_model;
  }

  static List<CommonWebsitModel> fromMapList(dynamic mapList) {
    List<CommonWebsitModel> list = new List(mapList.length);
    for (int i = 0; i < mapList.length; i++) {
      list[i] = fromMap(mapList[i]);
    }
    return list;
  }

}

class DataListBean {

  String icon;
  String link;
  String name;
  int id;
  int order;
  int visible;

  static DataListBean fromMap(Map<String, dynamic> map) {
    DataListBean dataListBean = new DataListBean();
    dataListBean.icon = map['icon'];
    dataListBean.link = map['link'];
    dataListBean.name = map['name'];
    dataListBean.id = map['id'];
    dataListBean.order = map['order'];
    dataListBean.visible = map['visible'];
    return dataListBean;
  }

  static List<DataListBean> fromMapList(dynamic mapList) {
    List<DataListBean> list = new List(mapList.length);
    for (int i = 0; i < mapList.length; i++) {
      list[i] = fromMap(mapList[i]);
    }
    return list;
  }

  Map<String, dynamic> toMap() {
    var map = Map<String, dynamic>();
    map["icon"] = icon;
    map["link"] = link;
    map["name"] = name;
    map["id"] = id;
    map["web_order"] = order;
    map["visible"] = visible;

    if (id != null) {
      map["id"] = id;
    }

    return map;
  }

}


================================================
FILE: lib/model/common_website_model.dart
================================================
import 'dart:convert' show json;

class CommonWebsiteModel {

  int errorCode;
  String errorMsg;
  List<CommonWebsiteData> data;

  CommonWebsiteModel.fromParams({this.errorCode, this.errorMsg, this.data});

  factory CommonWebsiteModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new CommonWebsiteModel.fromJson(json.decode(jsonStr)) : new CommonWebsiteModel.fromJson(jsonStr);

  CommonWebsiteModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
    data = jsonRes['data'] == null ? null : [];

    for (var dataItem in data == null ? [] : jsonRes['data']){
      data.add(dataItem == null ? null : new CommonWebsiteData.fromJson(dataItem));
    }
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  }
}

class CommonWebsiteData {

  int id;
  int order;
  int visible;
  String icon;
  String link;
  String name;

  CommonWebsiteData.fromParams({this.id, this.order, this.visible, this.icon, this.link, this.name});

  CommonWebsiteData.fromJson(jsonRes) {
    id = jsonRes['id'];
    order = jsonRes['order'];
    visible = jsonRes['visible'];
    icon = jsonRes['icon'];
    link = jsonRes['link'];
    name = jsonRes['name'];
  }

  @override
  String toString() {
    return '{"id": $id,"order": $order,"visible": $visible,"icon": ${icon != null?'${json.encode(icon)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"name": ${name != null?'${json.encode(name)}':'null'}}';
  }
}



================================================
FILE: lib/model/hotword_model.dart
================================================
class HotwordModel {

  String errorMsg;
  int errorCode;
  List<DataListBean> data;

  static HotwordModel fromMap(Map<String, dynamic> map) {
    HotwordModel hotword_model = new HotwordModel();
    hotword_model.errorMsg = map['errorMsg'];
    hotword_model.errorCode = map['errorCode'];
    hotword_model.data = DataListBean.fromMapList(map['data']);
    return hotword_model;
  }

  static List<HotwordModel> fromMapList(dynamic mapList) {
    List<HotwordModel> list = new List(mapList.length);
    for (int i = 0; i < mapList.length; i++) {
      list[i] = fromMap(mapList[i]);
    }
    return list;
  }

}

class DataListBean {

  String link;
  String name;
  int id;
  int order;
  int visible;

  static DataListBean fromMap(Map<String, dynamic> map) {
    DataListBean dataListBean = new DataListBean();
    dataListBean.link = map['link'];
    dataListBean.name = map['name'];
    dataListBean.id = map['id'];
    dataListBean.order = map['order'];
    dataListBean.visible = map['visible'];
    return dataListBean;
  }

  static List<DataListBean> fromMapList(dynamic mapList) {
    List<DataListBean> list = new List(mapList.length);
    for (int i = 0; i < mapList.length; i++) {
      list[i] = fromMap(mapList[i]);
    }
    return list;
  }
}


================================================
FILE: lib/model/hotword_result_model.dart
================================================
class HotwordResultModel {

  String errorMsg;
  int errorCode;
  DataBean data;

  static HotwordResultModel fromMap(Map<String, dynamic> map) {
    HotwordResultModel hotword_result_model = new HotwordResultModel();
    hotword_result_model.errorMsg = map['errorMsg'];
    hotword_result_model.errorCode = map['errorCode'];
    hotword_result_model.data = DataBean.fromMap(map['data']);
    return hotword_result_model;
  }

  static List<HotwordResultModel> fromMapList(dynamic mapList) {
    List<HotwordResultModel> list = new List(mapList.length);
    for (int i = 0; i < mapList.length; i++) {
      list[i] = fromMap(mapList[i]);
    }
    return list;
  }

}

class DataBean {
  bool over;
  int curPage;
  int offset;
  int pageCount;
  int size;
  int total;
  List<DatasListBean> datas;

  static DataBean fromMap(Map<String, dynamic> map) {
    DataBean dataBean = new DataBean();
    dataBean.over = map['over'];
    dataBean.curPage = map['curPage'];
    dataBean.offset = map['offset'];
    dataBean.pageCount = map['pageCount'];
    dataBean.size = map['size'];
    dataBean.total = map['total'];
    dataBean.datas = DatasListBean.fromMapList(map['datas']);
    return dataBean;
  }

  static List<DataBean> fromMapList(dynamic mapList) {
    List<DataBean> list = new List(mapList.length);
    for (int i = 0; i < mapList.length; i++) {
      list[i] = fromMap(mapList[i]);
    }
    return list;
  }
}

class DatasListBean {

  String apkLink;
  String author;
  String chapterName;
  String desc;
  String envelopePic;
  String link;
  String niceDate;
  String origin;
  String projectLink;
  String superChapterName;
  String title;
  bool collect;
  bool fresh;
  int chapterId;
  int courseId;
  int id;
  int publishTime;
  int superChapterId;
  int type;
  int userId;
  int visible;
  int zan;
  List<TagsListBean> tags;

  static DatasListBean fromMap(Map<String, dynamic> map) {
    DatasListBean datasListBean = new DatasListBean();
    datasListBean.apkLink = map['apkLink'];
    datasListBean.author = map['author'];
    datasListBean.chapterName = map['chapterName'];
    datasListBean.desc = map['desc'];
    datasListBean.envelopePic = map['envelopePic'];
    datasListBean.link = map['link'];
    datasListBean.niceDate = map['niceDate'];
    datasListBean.origin = map['origin'];
    datasListBean.projectLink = map['projectLink'];
    datasListBean.superChapterName = map['superChapterName'];
    datasListBean.title = map['title'];
    datasListBean.collect = map['collect'];
    datasListBean.fresh = map['fresh'];
    datasListBean.chapterId = map['chapterId'];
    datasListBean.courseId = map['courseId'];
    datasListBean.id = map['id'];
    datasListBean.publishTime = map['publishTime'];
    datasListBean.superChapterId = map['superChapterId'];
    datasListBean.type = map['type'];
    datasListBean.userId = map['userId'];
    datasListBean.visible = map['visible'];
    datasListBean.zan = map['zan'];
    datasListBean.tags = TagsListBean.fromMapList(map['tags']);
    return datasListBean;
  }

  static List<DatasListBean> fromMapList(dynamic mapList) {
    List<DatasListBean> list = new List(mapList.length);
    for (int i = 0; i < mapList.length; i++) {
      list[i] = fromMap(mapList[i]);
    }
    return list;
  }
}

class TagsListBean {
  String name;
  String url;

  static TagsListBean fromMap(Map<String, dynamic> map) {
    TagsListBean tagsListBean = new TagsListBean();
    tagsListBean.name = map['name'];
    tagsListBean.url = map['url'];
    return tagsListBean;
  }

  static List<TagsListBean> fromMapList(dynamic mapList) {
    List<TagsListBean> list = new List(mapList.length);
    for (int i = 0; i < mapList.length; i++) {
      list[i] = fromMap(mapList[i]);
    }
    return list;
  }
}


================================================
FILE: lib/model/navi_model.dart
================================================
import 'dart:convert' show json;

class NaviModel {

  int errorCode;
  String errorMsg;
  List<NaviData> data;

  NaviModel.fromParams({this.errorCode, this.errorMsg, this.data});

  factory NaviModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new NaviModel.fromJson(json.decode(jsonStr)) : new NaviModel.fromJson(jsonStr);

  NaviModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
    data = jsonRes['data'] == null ? null : [];

    for (var dataItem in data == null ? [] : jsonRes['data']){
      data.add(dataItem == null ? null : new NaviData.fromJson(dataItem));
    }
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  }
}

class NaviData {

  int cid;
  String name;
  List<NaviArticle> articles;

  NaviData.fromParams({this.cid, this.name, this.articles});

  NaviData.fromJson(jsonRes) {
    cid = jsonRes['cid'];
    name = jsonRes['name'];
    articles = jsonRes['articles'] == null ? null : [];

    for (var articlesItem in articles == null ? [] : jsonRes['articles']){
      articles.add(articlesItem == null ? null : new NaviArticle.fromJson(articlesItem));
    }
  }

  @override
  String toString() {
    return '{"cid": $cid,"name": ${name != null?'${json.encode(name)}':'null'},"articles": $articles}';
  }
}

class NaviArticle {

  int chapterId;
  int courseId;
  int id;
  int publishTime;
  int superChapterId;
  int type;
  int userId;
  int visible;
  int zan;
  bool collect;
  bool fresh;
  String apkLink;
  String author;
  String chapterName;
  String desc;
  String envelopePic;
  String link;
  String niceDate;
  String origin;
  String projectLink;
  String superChapterName;
  String title;
  List<dynamic> tags;

  NaviArticle.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});

  NaviArticle.fromJson(jsonRes) {
    chapterId = jsonRes['chapterId'];
    courseId = jsonRes['courseId'];
    id = jsonRes['id'];
    publishTime = jsonRes['publishTime'];
    superChapterId = jsonRes['superChapterId'];
    type = jsonRes['type'];
    userId = jsonRes['userId'];
    visible = jsonRes['visible'];
    zan = jsonRes['zan'];
    collect = jsonRes['collect'];
    fresh = jsonRes['fresh'];
    apkLink = jsonRes['apkLink'];
    author = jsonRes['author'];
    chapterName = jsonRes['chapterName'];
    desc = jsonRes['desc'];
    envelopePic = jsonRes['envelopePic'];
    link = jsonRes['link'];
    niceDate = jsonRes['niceDate'];
    origin = jsonRes['origin'];
    projectLink = jsonRes['projectLink'];
    superChapterName = jsonRes['superChapterName'];
    title = jsonRes['title'];
    tags = jsonRes['tags'] == null ? null : [];

    for (var tagsItem in tags == null ? [] : jsonRes['tags']){
      tags.add(tagsItem);
    }
  }

  @override
  String toString() {
    return '{"chapterId": $chapterId,"courseId": $courseId,"id": $id,"publishTime": $publishTime,"superChapterId": $superChapterId,"type": $type,"userId": $userId,"visible": $visible,"zan": $zan,"collect": $collect,"fresh": $fresh,"apkLink": ${apkLink != null?'${json.encode(apkLink)}':'null'},"author": ${author != null?'${json.encode(author)}':'null'},"chapterName": ${chapterName != null?'${json.encode(chapterName)}':'null'},"desc": ${desc != null?'${json.encode(desc)}':'null'},"envelopePic": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"niceDate": ${niceDate != null?'${json.encode(niceDate)}':'null'},"origin": ${origin != null?'${json.encode(origin)}':'null'},"projectLink": ${projectLink != null?'${json.encode(projectLink)}':'null'},"superChapterName": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"tags": $tags}';
  }
}



================================================
FILE: lib/model/pretty_model.dart
================================================
class PrettyModel {


  bool error;
  List<ResultsListBean> results;

  static PrettyModel fromMap(Map<String, dynamic> map) {
    PrettyModel pretty_model = new PrettyModel();
    pretty_model.error = map['error'];
    pretty_model.results = ResultsListBean.fromMapList(map['results']);
    return pretty_model;
  }

  static List<PrettyModel> fromMapList(dynamic mapList) {
    List<PrettyModel> list = new List(mapList.length);
    for (int i = 0; i < mapList.length; i++) {
      list[i] = fromMap(mapList[i]);
    }
    return list;
  }

}

class ResultsListBean {

  String _id;
  String createdAt;
  String desc;
  String publishedAt;
  String source;
  String type;
  String url;
  String who;
  bool used;

  static ResultsListBean fromMap(Map<String, dynamic> map) {
    ResultsListBean resultsListBean = new ResultsListBean();
    resultsListBean._id = map['_id'];
    resultsListBean.createdAt = map['createdAt'];
    resultsListBean.desc = map['desc'];
    resultsListBean.publishedAt = map['publishedAt'];
    resultsListBean.source = map['source'];
    resultsListBean.type = map['type'];
    resultsListBean.url = map['url'];
    resultsListBean.who = map['who'];
    resultsListBean.used = map['used'];
    return resultsListBean;
  }

  static List<ResultsListBean> fromMapList(dynamic mapList) {
    List<ResultsListBean> list = new List(mapList.length);
    for (int i = 0; i < mapList.length; i++) {
      list[i] = fromMap(mapList[i]);
    }
    return list;
  }
}


================================================
FILE: lib/model/project_tree_model.dart
================================================
import 'dart:convert' show json;

class ProjectTreeModel {

  int errorCode;
  String errorMsg;
  List<ProjectTreeData> data;

  ProjectTreeModel.fromParams({this.errorCode, this.errorMsg, this.data});

  factory ProjectTreeModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new ProjectTreeModel.fromJson(json.decode(jsonStr)) : new ProjectTreeModel.fromJson(jsonStr);

  ProjectTreeModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
    data = jsonRes['data'] == null ? null : [];

    for (var dataItem in data == null ? [] : jsonRes['data']){
      data.add(dataItem == null ? null : new ProjectTreeData.fromJson(dataItem));
    }
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  }
}

class ProjectTreeData {

  int courseId;
  int id;
  int order;
  int parentChapterId;
  int visible;
  bool userControlSetTop;
  String name;
  List<dynamic> children;

  ProjectTreeData.fromParams({this.courseId, this.id, this.order, this.parentChapterId, this.visible, this.userControlSetTop, this.name, this.children});

  ProjectTreeData.fromJson(jsonRes) {
    courseId = jsonRes['courseId'];
    id = jsonRes['id'];
    order = jsonRes['order'];
    parentChapterId = jsonRes['parentChapterId'];
    visible = jsonRes['visible'];
    userControlSetTop = jsonRes['userControlSetTop'];
    name = jsonRes['name'];
    children = jsonRes['children'] == null ? null : [];

    for (var childrenItem in children == null ? [] : jsonRes['children']){
      children.add(childrenItem);
    }
  }

  @override
  String toString() {
    return '{"courseId": $courseId,"id": $id,"order": $order,"parentChapterId": $parentChapterId,"visible": $visible,"userControlSetTop": $userControlSetTop,"name": ${name != null?'${json.encode(name)}':'null'},"children": $children}';
  }
}



================================================
FILE: lib/model/projectlist_model.dart
================================================
import 'dart:convert' show json;

class ProjectTreeListModel {

  int errorCode;
  String errorMsg;
  ProjectTreeListData data;

  ProjectTreeListModel.fromParams({this.errorCode, this.errorMsg, this.data});

  factory ProjectTreeListModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new ProjectTreeListModel.fromJson(json.decode(jsonStr)) : new ProjectTreeListModel.fromJson(jsonStr);

  ProjectTreeListModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
    data = jsonRes['data'] == null ? null : new ProjectTreeListData.fromJson(jsonRes['data']);
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  }
}

class ProjectTreeListData {

  int curPage;
  int offset;
  int pageCount;
  int size;
  int total;
  bool over;
  List<ProjectTreeListDatas> datas;

  ProjectTreeListData.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});

  ProjectTreeListData.fromJson(jsonRes) {
    curPage = jsonRes['curPage'];
    offset = jsonRes['offset'];
    pageCount = jsonRes['pageCount'];
    size = jsonRes['size'];
    total = jsonRes['total'];
    over = jsonRes['over'];
    datas = jsonRes['datas'] == null ? null : [];

    for (var datasItem in datas == null ? [] : jsonRes['datas']){
      datas.add(datasItem == null ? null : new ProjectTreeListDatas.fromJson(datasItem));
    }
  }

  @override
  String toString() {
    return '{"curPage": $curPage,"offset": $offset,"pageCount": $pageCount,"size": $size,"total": $total,"over": $over,"datas": $datas}';
  }
}

class ProjectTreeListDatas {

  int chapterId;
  int courseId;
  int id;
  int publishTime;
  int superChapterId;
  int type;
  int userId;
  int visible;
  int zan;
  bool collect;
  bool fresh;
  String apkLink;
  String author;
  String chapterName;
  String desc;
  String envelopePic;
  String link;
  String niceDate;
  String origin;
  String projectLink;
  String superChapterName;
  String title;
  List<ProjectTreeListTag> tags;

  ProjectTreeListDatas.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});

  ProjectTreeListDatas.fromJson(jsonRes) {
    chapterId = jsonRes['chapterId'];
    courseId = jsonRes['courseId'];
    id = jsonRes['id'];
    publishTime = jsonRes['publishTime'];
    superChapterId = jsonRes['superChapterId'];
    type = jsonRes['type'];
    userId = jsonRes['userId'];
    visible = jsonRes['visible'];
    zan = jsonRes['zan'];
    collect = jsonRes['collect'];
    fresh = jsonRes['fresh'];
    apkLink = jsonRes['apkLink'];
    author = jsonRes['author'];
    chapterName = jsonRes['chapterName'];
    desc = jsonRes['desc'];
    envelopePic = jsonRes['envelopePic'];
    link = jsonRes['link'];
    niceDate = jsonRes['niceDate'];
    origin = jsonRes['origin'];
    projectLink = jsonRes['projectLink'];
    superChapterName = jsonRes['superChapterName'];
    title = jsonRes['title'];
    tags = jsonRes['tags'] == null ? null : [];

    for (var tagsItem in tags == null ? [] : jsonRes['tags']){
      tags.add(tagsItem == null ? null : new ProjectTreeListTag.fromJson(tagsItem));
    }
  }

  @override
  String toString() {
    return '{"chapterId": $chapterId,"courseId": $courseId,"id": $id,"publishTime": $publishTime,"superChapterId": $superChapterId,"type": $type,"userId": $userId,"visible": $visible,"zan": $zan,"collect": $collect,"fresh": $fresh,"apkLink": ${apkLink != null?'${json.encode(apkLink)}':'null'},"author": ${author != null?'${json.encode(author)}':'null'},"chapterName": ${chapterName != null?'${json.encode(chapterName)}':'null'},"desc": ${desc != null?'${json.encode(desc)}':'null'},"envelopePic": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"niceDate": ${niceDate != null?'${json.encode(niceDate)}':'null'},"origin": ${origin != null?'${json.encode(origin)}':'null'},"projectLink": ${projectLink != null?'${json.encode(projectLink)}':'null'},"superChapterName": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"tags": $tags}';
  }
}

class ProjectTreeListTag {

  String name;
  String url;

  ProjectTreeListTag.fromParams({this.name, this.url});

  ProjectTreeListTag.fromJson(jsonRes) {
    name = jsonRes['name'];
    url = jsonRes['url'];
  }

  @override
  String toString() {
    return '{"name": ${name != null?'${json.encode(name)}':'null'},"url": ${url != null?'${json.encode(url)}':'null'}}';
  }
}



================================================
FILE: lib/model/system_tree_content_model.dart
================================================
import 'dart:convert' show json;

class SystemTreeContentModel {

  int errorCode;
  String errorMsg;
  SystemTreeContentData data;

  SystemTreeContentModel.fromParams({this.errorCode, this.errorMsg, this.data});

  factory SystemTreeContentModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new SystemTreeContentModel.fromJson(json.decode(jsonStr)) : new SystemTreeContentModel.fromJson(jsonStr);

  SystemTreeContentModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
    data = jsonRes['data'] == null ? null : new SystemTreeContentData.fromJson(jsonRes['data']);
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  }
}

class SystemTreeContentData {

  int curPage;
  int offset;
  int pageCount;
  int size;
  int total;
  bool over;
  List<SystemTreeContentChild> datas;

  SystemTreeContentData.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});

  SystemTreeContentData.fromJson(jsonRes) {
    curPage = jsonRes['curPage'];
    offset = jsonRes['offset'];
    pageCount = jsonRes['pageCount'];
    size = jsonRes['size'];
    total = jsonRes['total'];
    over = jsonRes['over'];
    datas = jsonRes['datas'] == null ? null : [];

    for (var datasItem in datas == null ? [] : jsonRes['datas']){
      datas.add(datasItem == null ? null : new SystemTreeContentChild.fromJson(datasItem));
    }
  }

  @override
  String toString() {
    return '{"curPage": $curPage,"offset": $offset,"pageCount": $pageCount,"size": $size,"total": $total,"over": $over,"datas": $datas}';
  }
}

class SystemTreeContentChild {

  int chapterId;
  int courseId;
  int id;
  int publishTime;
  int superChapterId;
  int type;
  int userId;
  int visible;
  int zan;
  bool collect;
  bool fresh;
  String apkLink;
  String author;
  String chapterName;
  String desc;
  String envelopePic;
  String link;
  String niceDate;
  String origin;
  String projectLink;
  String superChapterName;
  String title;
  List<dynamic> tags;

  SystemTreeContentChild.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});

  SystemTreeContentChild.fromJson(jsonRes) {
    chapterId = jsonRes['chapterId'];
    courseId = jsonRes['courseId'];
    id = jsonRes['id'];
    publishTime = jsonRes['publishTime'];
    superChapterId = jsonRes['superChapterId'];
    type = jsonRes['type'];
    userId = jsonRes['userId'];
    visible = jsonRes['visible'];
    zan = jsonRes['zan'];
    collect = jsonRes['collect'];
    fresh = jsonRes['fresh'];
    apkLink = jsonRes['apkLink'];
    author = jsonRes['author'];
    chapterName = jsonRes['chapterName'];
    desc = jsonRes['desc'];
    envelopePic = jsonRes['envelopePic'];
    link = jsonRes['link'];
    niceDate = jsonRes['niceDate'];
    origin = jsonRes['origin'];
    projectLink = jsonRes['projectLink'];
    superChapterName = jsonRes['superChapterName'];
    title = jsonRes['title'];
    tags = jsonRes['tags'] == null ? null : [];

    for (var tagsItem in tags == null ? [] : jsonRes['tags']){
      tags.add(tagsItem);
    }
  }

  @override
  String toString() {
    return '{"chapterId": $chapterId,"courseId": $courseId,"id": $id,"publishTime": $publishTime,"superChapterId": $superChapterId,"type": $type,"userId": $userId,"visible": $visible,"zan": $zan,"collect": $collect,"fresh": $fresh,"apkLink": ${apkLink != null?'${json.encode(apkLink)}':'null'},"author": ${author != null?'${json.encode(author)}':'null'},"chapterName": ${chapterName != null?'${json.encode(chapterName)}':'null'},"desc": ${desc != null?'${json.encode(desc)}':'null'},"envelopePic": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"niceDate": ${niceDate != null?'${json.encode(niceDate)}':'null'},"origin": ${origin != null?'${json.encode(origin)}':'null'},"projectLink": ${projectLink != null?'${json.encode(projectLink)}':'null'},"superChapterName": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"tags": $tags}';
  }
}



================================================
FILE: lib/model/system_tree_model.dart
================================================
import 'dart:convert' show json;

class SystemTreeModel {

  int errorCode;
  String errorMsg;
  List<SystemTreeData> data;

  SystemTreeModel.fromParams({this.errorCode, this.errorMsg, this.data});

  factory SystemTreeModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new SystemTreeModel.fromJson(json.decode(jsonStr)) : new SystemTreeModel.fromJson(jsonStr);

  SystemTreeModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
    data = jsonRes['data'] == null ? null : [];

    for (var dataItem in data == null ? [] : jsonRes['data']){
      data.add(dataItem == null ? null : new SystemTreeData.fromJson(dataItem));
    }
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  }
}

class SystemTreeData {

  int courseId;
  int id;
  int order;
  int parentChapterId;
  int visible;
  bool userControlSetTop;
  String name;
  List<SystemTreeChild> children;

  SystemTreeData.fromParams({this.courseId, this.id, this.order, this.parentChapterId, this.visible, this.userControlSetTop, this.name, this.children});

  SystemTreeData.fromJson(jsonRes) {
    courseId = jsonRes['courseId'];
    id = jsonRes['id'];
    order = jsonRes['order'];
    parentChapterId = jsonRes['parentChapterId'];
    visible = jsonRes['visible'];
    userControlSetTop = jsonRes['userControlSetTop'];
    name = jsonRes['name'];
    children = jsonRes['children'] == null ? null : [];

    for (var childrenItem in children == null ? [] : jsonRes['children']){
      children.add(childrenItem == null ? null : new SystemTreeChild.fromJson(childrenItem));
    }
  }

  @override
  String toString() {
    return '{"courseId": $courseId,"id": $id,"order": $order,"parentChapterId": $parentChapterId,"visible": $visible,"userControlSetTop": $userControlSetTop,"name": ${name != null?'${json.encode(name)}':'null'},"children": $children}';
  }
}

class SystemTreeChild {

  int courseId;
  int id;
  int order;
  int parentChapterId;
  int visible;
  bool userControlSetTop;
  String name;
  List<dynamic> children;

  SystemTreeChild.fromParams({this.courseId, this.id, this.order, this.parentChapterId, this.visible, this.userControlSetTop, this.name, this.children});

  SystemTreeChild.fromJson(jsonRes) {
    courseId = jsonRes['courseId'];
    id = jsonRes['id'];
    order = jsonRes['order'];
    parentChapterId = jsonRes['parentChapterId'];
    visible = jsonRes['visible'];
    userControlSetTop = jsonRes['userControlSetTop'];
    name = jsonRes['name'];
    children = jsonRes['children'] == null ? null : [];

    for (var childrenItem in children == null ? [] : jsonRes['children']){
      children.add(childrenItem);
    }
  }

  @override
  String toString() {
    return '{"courseId": $courseId,"id": $id,"order": $order,"parentChapterId": $parentChapterId,"visible": $visible,"userControlSetTop": $userControlSetTop,"name": ${name != null?'${json.encode(name)}':'null'},"children": $children}';
  }
}



================================================
FILE: lib/model/todo_item.dart
================================================
import 'package:flutter/material.dart';

class TodoItem extends StatelessWidget {
  String _itemName;
  String _dateCreated;
  int _id;

  TodoItem(this._itemName, this._dateCreated);

  TodoItem.map(dynamic obj) {
    this._itemName = obj["itemName"];
    this._dateCreated = obj["dateCreated"];
    this._id = obj["id"];
  }

  String get itemName => _itemName;
  String get dateCreated => _dateCreated;
  int get id => _id;

  Map<String, dynamic> toMap() {
    var map = Map<String, dynamic>();
    map["itemName"] = _itemName;
    map["dateCreated"] = _dateCreated;

    if (_id != null) {
      map["id"] = _id;
    }

    return map;
  }

  TodoItem.fromMap(Map<String, dynamic> map) {
    this._itemName = map["itemName"];
    this._dateCreated = map["dateCreated"];
    this._id = map["id"];
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.all(8.0),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          //solve the overflow problem
          Expanded(
            
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Text(
                  _itemName,
                  style: TextStyle(
                      color: Colors.black,
                      fontWeight: FontWeight.bold,
                      fontSize: 18.0),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
                Container(
                  margin: const EdgeInsets.only(top: 10.0),
                  child: Text(
                    "Created on: $_dateCreated",
                    style: TextStyle(
                        color: Colors.black,
                        fontSize: 12.0,
                        fontStyle: FontStyle.italic),
                  ),
                ),
              ],
            ),
          )
        ],
      ),
    );
  }
}


================================================
FILE: lib/model/todolist_model.dart
================================================
import 'dart:convert' show json;

class TodoListModel {

  int errorCode;
  String errorMsg;
  TodoListData data;

  TodoListModel.fromParams({this.errorCode, this.errorMsg, this.data});

  factory TodoListModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new TodoListModel.fromJson(json.decode(jsonStr)) : new TodoListModel.fromJson(jsonStr);
  
  TodoListModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
    data = jsonRes['data'] == null ? null : new TodoListData.fromJson(jsonRes['data']);
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  }
}

class TodoListData {

  int type;
  List<TodoListDatas> doneList;
  List<TodoListDatas> todoList;

  TodoListData.fromParams({this.type, this.doneList, this.todoList});
  
  TodoListData.fromJson(jsonRes) {
    type = jsonRes['type'];
    doneList = jsonRes['doneList'] == null ? null : [];

    for (var doneListItem in doneList == null ? [] : jsonRes['doneList']){
            doneList.add(doneListItem == null ? null : new TodoListDatas.fromJson(doneListItem));
    }

    todoList = jsonRes['todoList'] == null ? null : [];

    for (var todoListItem in todoList == null ? [] : jsonRes['todoList']){
            todoList.add(todoListItem == null ? null : new TodoListDatas.fromJson(todoListItem));
    }
  }

  @override
  String toString() {
    return '{"type": $type,"doneList": $doneList,"todoList": $todoList}';
  }
}

class TodoListDatas {

  int date;
  List<TodoData> todoList;

  TodoListDatas.fromParams({this.date, this.todoList});
  
  TodoListDatas.fromJson(jsonRes) {
    date = jsonRes['date'];
    todoList = jsonRes['todoList'] == null ? null : [];

    for (var todoListItem in todoList == null ? [] : jsonRes['todoList']){
            todoList.add(todoListItem == null ? null : new TodoData.fromJson(todoListItem));
    }
  }

  @override
  String toString() {
    return '{"date": $date,"todoList": $todoList}';
  }
}

class TodoData {

  TodoData();

  TodoData.origin(String title){
    this.title = title;
  }

  int completeDate;
  int date;
  int id;
  int priority;
  int status;
  int type;
  int userId;
  String completeDateStr;
  String content;
  String dateStr;
  String title;

  TodoData.fromParams({this.completeDate, this.date, this.id, this.priority, this.status, this.type, this.userId, this.completeDateStr, this.content, this.dateStr, this.title});
  
  TodoData.fromJson(jsonRes) {
    completeDate = jsonRes['completeDate'];
    date = jsonRes['date'];
    id = jsonRes['id'];
    priority = jsonRes['priority'];
    status = jsonRes['status'];
    type = jsonRes['type'];
    userId = jsonRes['userId'];
    completeDateStr = jsonRes['completeDateStr'];
    content = jsonRes['content'];
    dateStr = jsonRes['dateStr'];
    title = jsonRes['title'];
  }

  @override
  String toString() {
    return '{"completeDate": $completeDate,"date": $date,"id": $id,"priority": $priority,"status": $status,"type": $type,"userId": $userId,"completeDateStr": ${completeDateStr != null?'${json.encode(completeDateStr)}':'null'},"content": ${content != null?'${json.encode(content)}':'null'},"dateStr": ${dateStr != null?'${json.encode(dateStr)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'}}';
  }
}





================================================
FILE: lib/model/user_model.dart
================================================
import 'dart:convert' show json;

class UserModel {

  int errorCode;
  String errorMsg;
  UserData data;

  UserModel.fromParams({this.errorCode, this.errorMsg, this.data});

  factory UserModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new UserModel.fromJson(json.decode(jsonStr)) : new UserModel.fromJson(jsonStr);
  
  UserModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
    data = jsonRes['data'] == null ? null : new UserData.fromJson(jsonRes['data']);
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  }
}

class UserData {

  int id;
  int type;
  String email;
  String icon;
  String password;
  String token;
  String username;
  List<dynamic> chapterTops;
  List<int> collectIds;

  UserData.fromParams({this.id, this.type, this.email, this.icon, this.password, this.token, this.username, this.chapterTops, this.collectIds});
  
  UserData.fromJson(jsonRes) {
    id = jsonRes['id'];
    type = jsonRes['type'];
    email = jsonRes['email'];
    icon = jsonRes['icon'];
    password = jsonRes['password'];
    token = jsonRes['token'];
    username = jsonRes['username'];
    chapterTops = jsonRes['chapterTops'] == null ? null : [];

    for (var chapterTopsItem in chapterTops == null ? [] : jsonRes['chapterTops']){
            chapterTops.add(chapterTopsItem);
    }

    collectIds = jsonRes['collectIds'] == null ? null : [];

    for (var collectIdsItem in collectIds == null ? [] : jsonRes['collectIds']){
            collectIds.add(collectIdsItem);
    }
  }

  @override
  String toString() {
    return '{"id": $id,"type": $type,"email": ${email != null?'${json.encode(email)}':'null'},"icon": ${icon != null?'${json.encode(icon)}':'null'},"password": ${password != null?'${json.encode(password)}':'null'},"token": ${token != null?'${json.encode(token)}':'null'},"username": ${username != null?'${json.encode(username)}':'null'},"chapterTops": $chapterTops,"collectIds": $collectIds}';
  }
}



================================================
FILE: lib/model/website_collection_model.dart
================================================
import 'dart:convert' show json;

class WebsiteCollectionModel {

  int errorCode;
  String errorMsg;
  List<WebsiteCollectionData> data;

  WebsiteCollectionModel.fromParams({this.errorCode, this.errorMsg, this.data});

  factory WebsiteCollectionModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new WebsiteCollectionModel.fromJson(json.decode(jsonStr)) : new WebsiteCollectionModel.fromJson(jsonStr);
  
  WebsiteCollectionModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
    data = jsonRes['data'] == null ? null : [];

    for (var dataItem in data == null ? [] : jsonRes['data']){
            data.add(dataItem == null ? null : new WebsiteCollectionData.fromJson(dataItem));
    }
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  }
}

class WebsiteCollectionData {

  int id;
  int order;
  int userId;
  int visible;
  String desc;
  String icon;
  String link;
  String name;

  WebsiteCollectionData.fromParams({this.id, this.order, this.userId, this.visible, this.desc, this.icon, this.link, this.name});
  
  WebsiteCollectionData.fromJson(jsonRes) {
    id = jsonRes['id'];
    order = jsonRes['order'];
    userId = jsonRes['userId'];
    visible = jsonRes['visible'];
    desc = jsonRes['desc'];
    icon = jsonRes['icon'];
    link = jsonRes['link'];
    name = jsonRes['name'];
  }

  @override
  String toString() {
    return '{"id": $id,"order": $order,"userId": $userId,"visible": $visible,"desc": ${desc != null?'${json.encode(desc)}':'null'},"icon": ${icon != null?'${json.encode(icon)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"name": ${name != null?'${json.encode(name)}':'null'}}';
  }
}



================================================
FILE: lib/model/wx_article_content_model.dart
================================================
import 'dart:convert' show json;

class WxArticleContentModel {

  int errorCode;
  String errorMsg;
  WxArticleContentData data;

  WxArticleContentModel.fromParams({this.errorCode, this.errorMsg, this.data});

  factory WxArticleContentModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new WxArticleContentModel.fromJson(json.decode(jsonStr)) : new WxArticleContentModel.fromJson(jsonStr);

  WxArticleContentModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
    data = jsonRes['data'] == null ? null : new WxArticleContentData.fromJson(jsonRes['data']);
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  }
}

class WxArticleContentData {

  int curPage;
  int offset;
  int pageCount;
  int size;
  int total;
  bool over;
  List<WxArticleContentDatas> datas;

  WxArticleContentData.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});

  WxArticleContentData.fromJson(jsonRes) {
    curPage = jsonRes['curPage'];
    offset = jsonRes['offset'];
    pageCount = jsonRes['pageCount'];
    size = jsonRes['size'];
    total = jsonRes['total'];
    over = jsonRes['over'];
    datas = jsonRes['datas'] == null ? null : [];

    for (var datasItem in datas == null ? [] : jsonRes['datas']){
      datas.add(datasItem == null ? null : new WxArticleContentDatas.fromJson(datasItem));
    }
  }

  @override
  String toString() {
    return '{"curPage": $curPage,"offset": $offset,"pageCount": $pageCount,"size": $size,"total": $total,"over": $over,"datas": $datas}';
  }
}

class WxArticleContentDatas {

  int chapterId;
  int courseId;
  int id;
  int publishTime;
  int superChapterId;
  int type;
  int userId;
  int visible;
  int zan;
  bool collect;
  bool fresh;
  String apkLink;
  String author;
  String chapterName;
  String desc;
  String envelopePic;
  String link;
  String niceDate;
  String origin;
  String projectLink;
  String superChapterName;
  String title;
  List<WxArticleContentTags> tags;

  WxArticleContentDatas.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});

  WxArticleContentDatas.fromJson(jsonRes) {
    chapterId = jsonRes['chapterId'];
    courseId = jsonRes['courseId'];
    id = jsonRes['id'];
    publishTime = jsonRes['publishTime'];
    superChapterId = jsonRes['superChapterId'];
    type = jsonRes['type'];
    userId = jsonRes['userId'];
    visible = jsonRes['visible'];
    zan = jsonRes['zan'];
    collect = jsonRes['collect'];
    fresh = jsonRes['fresh'];
    apkLink = jsonRes['apkLink'];
    author = jsonRes['author'];
    chapterName = jsonRes['chapterName'];
    desc = jsonRes['desc'];
    envelopePic = jsonRes['envelopePic'];
    link = jsonRes['link'];
    niceDate = jsonRes['niceDate'];
    origin = jsonRes['origin'];
    projectLink = jsonRes['projectLink'];
    superChapterName = jsonRes['superChapterName'];
    title = jsonRes['title'];
    tags = jsonRes['tags'] == null ? null : [];

    for (var tagsItem in tags == null ? [] : jsonRes['tags']){
      tags.add(tagsItem == null ? null : new WxArticleContentTags.fromJson(tagsItem));
    }
  }

  @override
  String toString() {
    return '{"chapterId": $chapterId,"courseId": $courseId,"id": $id,"publishTime": $publishTime,"superChapterId": $superChapterId,"type": $type,"userId": $userId,"visible": $visible,"zan": $zan,"collect": $collect,"fresh": $fresh,"apkLink": ${apkLink != null?'${json.encode(apkLink)}':'null'},"author": ${author != null?'${json.encode(author)}':'null'},"chapterName": ${chapterName != null?'${json.encode(chapterName)}':'null'},"desc": ${desc != null?'${json.encode(desc)}':'null'},"envelopePic": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},"link": ${link != null?'${json.encode(link)}':'null'},"niceDate": ${niceDate != null?'${json.encode(niceDate)}':'null'},"origin": ${origin != null?'${json.encode(origin)}':'null'},"projectLink": ${projectLink != null?'${json.encode(projectLink)}':'null'},"superChapterName": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},"title": ${title != null?'${json.encode(title)}':'null'},"tags": $tags}';
  }
}

class WxArticleContentTags {

  String name;
  String url;

  WxArticleContentTags.fromParams({this.name, this.url});

  WxArticleContentTags.fromJson(jsonRes) {
    name = jsonRes['name'];
    url = jsonRes['url'];
  }

  @override
  String toString() {
    return '{"name": ${name != null?'${json.encode(name)}':'null'},"url": ${url != null?'${json.encode(url)}':'null'}}';
  }
}



================================================
FILE: lib/model/wx_article_title_model.dart
================================================
import 'dart:convert' show json;

class WxArticleTitleModel {

  int errorCode;
  String errorMsg;
  List<WxArticleTitleData> data;

  WxArticleTitleModel.fromParams({this.errorCode, this.errorMsg, this.data});

  factory WxArticleTitleModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new WxArticleTitleModel.fromJson(json.decode(jsonStr)) : new WxArticleTitleModel.fromJson(jsonStr);

  WxArticleTitleModel.fromJson(jsonRes) {
    errorCode = jsonRes['errorCode'];
    errorMsg = jsonRes['errorMsg'];
    data = jsonRes['data'] == null ? null : [];

    for (var dataItem in data == null ? [] : jsonRes['data']){
      data.add(dataItem == null ? null : new WxArticleTitleData.fromJson(dataItem));
    }
  }

  @override
  String toString() {
    return '{"errorCode": $errorCode,"errorMsg": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},"data": $data}';
  }
}

class WxArticleTitleData {

  int courseId;
  int id;
  int order;
  int parentChapterId;
  int visible;
  bool userControlSetTop;
  String name;
  List<dynamic> children;

  WxArticleTitleData.fromParams({this.courseId, this.id, this.order, this.parentChapterId, this.visible, this.userControlSetTop, this.name, this.children});

  WxArticleTitleData.fromJson(jsonRes) {
    courseId = jsonRes['courseId'];
    id = jsonRes['id'];
    order = jsonRes['order'];
    parentChapterId = jsonRes['parentChapterId'];
    visible = jsonRes['visible'];
    userControlSetTop = jsonRes['userControlSetTop'];
    name = jsonRes['name'];
    children = jsonRes['children'] == null ? null : [];

    for (var childrenItem in children == null ? [] : jsonRes['children']){
      children.add(childrenItem);
    }
  }

  @override
  String toString() {
    return '{"courseId": $courseId,"id": $id,"order": $order,"parentChapterId": $parentChapterId,"visible": $visible,"userControlSetTop": $userControlSetTop,"name": ${name != null?'${json.encode(name)}':'null'},"children": $children}';
  }
}



================================================
FILE: lib/splash_screen.dart
================================================
import 'package:flutter/material.dart';
import 'package:intro_slider/intro_slider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:wanandroid_ngu/app.dart';
class SplashScreen extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new SplashScreenState() ;
  }

}

class SplashScreenState extends State<SplashScreen> {

  List<Slide> slides = new List();

  @override
  void initState() {
    super.initState();

    slides.add(
      new Slide(
        title: "Flutter",
        description:
        "Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可以与现有的代码一起工作。在全世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的。",
        styleDescription: TextStyle(
            color: Colors.white,
            fontSize: 20.0,
            fontFamily: 'Raleway'),
        marginDescription: EdgeInsets.only(left: 20.0, right: 20.0, top: 20.0, bottom: 70.0),
        colorBegin: Color(0xffFFDAB9),
        colorEnd: Color(0xff40E0D0),
        directionColorBegin: Alignment.topLeft,
        directionColorEnd: Alignment.bottomRight,
      ),
    );

    slides.add(
      new Slide(
        title: "Wanandroid",
        description:
        "这是一款使用Flutter写的WanAndroid客户端应用,在Android和IOS都完美运行,可以用来入门Flutter,简单明了,适合初学者,项目完全开源,如果本项目确实能够帮助到你学习Flutter,谢谢start,有问题请提交Issues,我会及时回复。",
        styleDescription: TextStyle(
            color: Colors.white,
            fontSize: 20.0,
            fontFamily: 'Raleway'),
        marginDescription: EdgeInsets.only(left: 20.0, right: 20.0, top: 20.0, bottom: 70.0),
        colorBegin: Color(0xffFFFACD),
        colorEnd: Color(0xffFF6347),
        directionColorBegin: Alignment.topLeft,
        directionColorEnd: Alignment.bottomRight,
      ),
    );

    slides.add(
      new Slide(
        title: "Welcome",
        description:
        "赠人玫瑰,手有余香;\n分享技术,传递快乐。",
        styleDescription: TextStyle(
            color: Colors.white,
            fontSize: 20.0,
            fontFamily: 'Raleway'),
        marginDescription: EdgeInsets.only(left: 20.0, right: 20.0, top: 20.0, bottom: 70.0),
        colorBegin: Color(0xffFFA500),
        colorEnd: Color(0xff7FFFD4),
        directionColorBegin: Alignment.topLeft,
        directionColorEnd: Alignment.bottomRight,
      ),
    );
  }

  void onDonePress() {
    _setHasSkip();
    Navigator.of(context).pushAndRemoveUntil(
        new MaterialPageRoute(
            builder: (context) => App()),
            (route) => route == null);
  }

  void onSkipPress() {
    _setHasSkip();
    Navigator.of(context).pushAndRemoveUntil(
        new MaterialPageRoute(
            builder: (context) => App()),
            (route) => route == null);
  }

  void _setHasSkip ()async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setBool("hasSkip", true);
  }


  @override
  Widget build(BuildContext context) {
    return IntroSlider(
        slides: this.slides,
      onDonePress: this.onDonePress,
      //renderSkipBtn: this.onSkipPress,
      nameSkipBtn: "跳过",
      nameNextBtn: "下一页",
      nameDoneBtn: "进入",
    );
  }
}

================================================
FILE: lib/ui/drawer/about.dart
================================================
import 'package:flutter/material.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';

class AboutMePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return AboutMePageState();
  }
}

class AboutMePageState extends State<AboutMePage> {
  TextStyle textStyle = new TextStyle(
      color: Colors.blue,
      decoration: new TextDecoration.combine([TextDecoration.underline]));

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text("关于作者"),
        ),
        body: new Container(
          padding: EdgeInsets.fromLTRB(35, 50, 35, 15),
          child: new Column(
            children: <Widget>[

              CircleAvatar(
                minRadius: 60,
                maxRadius: 60,
                backgroundImage: AssetImage('images/head.jpg'),
              ),

              Padding(padding: EdgeInsets.only(top: 30)),

              new Text("基于Google Flutter的玩Android客户端"),

              Container(
                margin: const EdgeInsets.fromLTRB(0.0, 80.0, 0.0, 0.0),
                child: new Row(

                  children: <Widget>[
                    new Text("邮箱:"),
                    new Text(
                      "zw20082012@126.com",
                      style: TextStyle(color: Colors.blue),

                    ),
                  ],
                ),
              ),

              GestureDetector(
                child: new Container(
                  margin: const EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0),
                  child: new Row(

                    children: <Widget>[
                      new Text("CSDN:"),
                      new Text(
                        "https://blog.csdn.net/zw2008224044",
                        style: textStyle,
                      ),
                    ],
                  ),
                ),
                onTap: () {
                  Navigator.of(context)
                      .push(new MaterialPageRoute(builder: (ctx) {
                    return new WebViewPage(
                        title: "ngu2008",
                        url: "https://blog.csdn.net/zw2008224044");
                  }));
                },
              ),
              GestureDetector(
                child: new Container(
                  margin: const EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0),
                  child: new Row(

                    children: <Widget>[
                      new Text("GitHub:"),
                      new Text(
                        "https://github.com/ngu2008/wanandroid",
                        style: textStyle,
                      ),
                    ],
                  ),
                ),
                onTap: () {
                  Navigator.of(context)
                      .push(new MaterialPageRoute(builder: (ctx) {
                    return new WebViewPage(
                        title: "GitHub",
                        url: "https://github.com/ngu2008/wanandroid");
                  }));
                },
              ),
              Expanded(child: Container(), flex: 1),
              new Text(
                "本项目仅供学习使用,不得用作商业目的",
                style: new TextStyle(fontSize: 12.0),
              )
            ],
          ),
        ));
  }
}


================================================
FILE: lib/ui/drawer/collctions.dart
================================================
import 'dart:ui';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/base/_base_widget.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/base_model.dart';
import 'package:wanandroid_ngu/model/collection_model.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';

class CollectionsPage extends BaseWidget {
  @override
  BaseWidgetState<BaseWidget> getState() {
    return CollectionsPageState();
  }
}

class CollectionsPageState extends BaseWidgetState<CollectionsPage> {
  List<Collection> _datas = new List();
  ScrollController _scrollController = ScrollController(); //listview的控制器
  int _page = 0; //加载的页数

  bool showToTopBtn = false; //是否显示“返回到顶部”按钮

  Future<Null> getData() async {
    _page = 0;
    ApiService().getCollectionList((
      CollectionModel _collectionModel,
    ) {
      if (_collectionModel.errorCode==0) {//成功
        if (_collectionModel.data.datas.length > 0) {//有数据
          showContent();
          setState(() {
            _datas.clear();
            _datas.addAll(_collectionModel.data.datas);
          });
        } else {//数据为空
          showEmpty();
        }
      }else{
        Fluttertoast.showToast(msg: _collectionModel.errorMsg);
      }
    }, (DioError error) {//发生错误
      print(error.response);
      setState(() {
        showError();
      });
    }, _page);
  }

  Future<Null> _getMore() async {
    _page++;
    ApiService().getCollectionList((
      CollectionModel _collectionModel,
    ){
      if (_collectionModel.errorCode==0) {//成功
        showContent();
        if (_collectionModel.data.datas.length > 0) {//有数据
          setState(() {
            _datas.addAll(_collectionModel.data.datas);
          });
        } else {//数据为空
          Fluttertoast.showToast(msg:"没有更多数据了");
        }
      }else{
        Fluttertoast.showToast(msg: _collectionModel.errorMsg);
      }
    }, (DioError error) {
      print(error.response);
      setState(() {
        showError();
      });
    }, _page);
  }

  @override
  void initState() {
    super.initState();
    showloading();
    getData();
    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        _getMore();
      }
    });
    _scrollController.addListener(() {
      //当前位置是否超过屏幕高度
      if (_scrollController.offset < 200 && showToTopBtn) {
        setState(() {
          showToTopBtn = false;
        });
      } else if (_scrollController.offset >= 200 && showToTopBtn == false) {
        setState(() {
          showToTopBtn = true;
        });
      }
    });
  }

  @override
  Widget getContentWidget(BuildContext context) {
    return Scaffold(
      body: RefreshIndicator(
          displacement: 15,
          child: ListView.separated(
            //普通项
            itemBuilder: _renderRow,
            //插入项
            separatorBuilder: (BuildContext context, int index) {
              return Container(
                height: 0.5,
                color: Colors.black26,
              );
            },
            controller: _scrollController,
            itemCount: _datas.length + 1,
          ),
          onRefresh: getData),
      floatingActionButton: !showToTopBtn ? null : FloatingActionButton(
          child: Icon(Icons.arrow_upward),
          onPressed: () {
            //返回到顶部时执行动画
            _scrollController.animateTo(.0,
                duration: Duration(milliseconds: 200),
                curve: Curves.ease
            );
          }
      ),
    );
  }

  Future<Null> _cancelCollection(int _position, int _id, int _originId) async {
    ApiService().cancelCollection((BaseModel _baseModel) {
      if (_baseModel.errorCode == 0) {
        _datas.removeAt(_position);
      }
      Scaffold.of(context).showSnackBar(new SnackBar(
        content: Text("移除成功!"),
      ));
      setState(() {});
    }, (DioError error) {
      print(error.response);
      setState(() {
        showError();
      });
    }, _id, _originId);
  }

  Widget _renderRow(BuildContext context, int index) {
    if (index < _datas.length) {
      return _itemView(context, index);
    }
    return null;
  }

  Widget _itemView(BuildContext context, int index) {
    return InkWell(
      child: _slideRow(index, _datas[index]),
      onTap: () {
        Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
          return new WebViewPage(
              title: _datas[index].title, url: _datas[index].link);
        }));
      },
    );
  }

  Widget _slideRow(int index, Collection item) {
    return new Slidable(
      delegate: new SlidableDrawerDelegate(),
      actionExtentRatio: 0.25,
      child: _newsRow(item),
      secondaryActions: <Widget>[
        new IconSlideAction(
          caption: '取消收藏',
          color: Colors.red,
          icon: Icons.delete,
          onTap: () {
            _cancelCollection(index, item.id, item.originId);
          },
        ),
      ],
    );
  }

  Widget _newsRow(Collection item) {
    return new Column(
      children: <Widget>[
        new Container(
            padding: EdgeInsets.fromLTRB(16, 16, 16, 8),
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                Text(
                  "作者:" + item.author,
                  style: TextStyle(fontSize: 12),
                ),
                new Expanded(
                  child: new Text(
                    "收藏时间:" + item.niceDate,
                    style: TextStyle(fontSize: 12),
                    textAlign: TextAlign.right,
                  ),
                ),
              ],
            )),
        Container(
            padding: EdgeInsets.fromLTRB(16, 0, 16, 0),
            child: Row(
              children: <Widget>[
                Expanded(
                    child: Text(
                  item.title,
                  style: TextStyle(
                    fontSize: 16,
                    fontWeight: FontWeight.bold,
                    color: const Color(0xFF3D4E5F),
                  ),
                  textAlign: TextAlign.left,
                ))
              ],
            )),
        Container(
            padding: EdgeInsets.fromLTRB(16, 8, 16, 16),
            child: Row(
              children: <Widget>[
                item.chapterName.isNotEmpty
                    ? Expanded(
                        child: Text(
                          "分类:" + item.chapterName,
                          style: TextStyle(fontSize: 12),
                        ),
                      )
                    : Text("")
              ],
            )),
      ],
    );
  }

  @override
  void dispose() {
    super.dispose();
    _scrollController.dispose();
  }

  @override
  void onClickErrorWidget() {
    showloading();
    getData();
  }

  @override
  AppBar getAppBar() {
    return  AppBar(
      title: Text("我的收藏"),
      elevation: 0.4,
    );
  }
}


================================================
FILE: lib/ui/drawer/common_website.dart
================================================
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/base/_base_widget.dart';
import 'package:wanandroid_ngu/db/db_helper.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/common_websit_model.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';

class CommonWebsitePage extends BaseWidget {
  @override
  BaseWidgetState<BaseWidget> getState() {
    return CommonWebsitePageState();
  }
}

class CommonWebsitePageState extends BaseWidgetState<CommonWebsitePage> {
  List<DataListBean> _datas = new List();
  ScrollController _scrollController = ScrollController();
  var db = DatabaseHelper();

  bool showToTopBtn = false; //是否显示“返回到顶部”按钮

  Future<Null> _getData() async {
    ApiService().getCommonWebsite((CommonWebsitModel commonWebsitModel) {
      if (commonWebsitModel.errorCode == 0) {
        var datas = commonWebsitModel.data;
        if (datas != null && datas.length > 0) {
          showContent();
          setState(() {
            _datas = datas;
          });
          //清空表数据
          db.clear();
          //数据存入数据库
          for (int i = 0; i < datas.length; i++) {
            db.saveItem(datas[i]);
          }
        } else {
          showEmpty();
        }
      } else {
        Fluttertoast.showToast(msg: commonWebsitModel.errorMsg);
      }
    }, (DioError error) {
      //发生错误
      print(error.response);
//      setState(() {
//        showError();
//      });
    });
  }

  _getDataFromDb() async {
    List datas = await db.getTotalList();
    if (datas.length > 0) {
      datas.forEach((item) {
        DataListBean dataListBean = DataListBean.fromMap(item);
        _datas.add(dataListBean);
      });
      setState(() {

      });
    } else {
      showloading();
    }
  }

  @override
  void initState() {
    super.initState();
    // showloading();
    //读取数据库的数据
    _getDataFromDb();

    _getData();
    _scrollController.addListener(() {
      //当前位置是否超过屏幕高度
      if (_scrollController.offset < 200 && showToTopBtn) {
        setState(() {
          showToTopBtn = false;
        });
      } else if (_scrollController.offset >= 200 && showToTopBtn == false) {
        setState(() {
          showToTopBtn = true;
        });
      }
    });
  }

  Widget _getBodyWidget(List<DataListBean> datas) {
    return RefreshIndicator(
      displacement: 15,
      onRefresh: _getData,
      child: GridView.builder(
          padding: EdgeInsets.all(15),
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 2, //每行2列
              mainAxisSpacing: 15,
              crossAxisSpacing: 15,
              childAspectRatio: 1.333 //
          ),
          controller: _scrollController,
          itemCount: _datas.length,
          itemBuilder: _renderItem),
    );
  }

  Color _getColor(int index) {
    switch (index % 8) {
      case 0:
        return const Color(0xFFfb6e52);
      case 1:
        return const Color(0xFFa1d46f);
      case 2:
        return const Color(0xFF5cc0e2);
      case 3:
        return const Color(0xFFffbb44);
      case 4:
        return const Color(0xFFef6666);
      case 5:
        return const Color(0xFFf8d19e);
      case 6:
        return const Color(0xFF48cfae);
      case 7:
        return const Color(0xFFaa9ef8);
    }
  }

  Widget _renderItem(BuildContext context, int index) {
    return new InkWell(
      onTap: () {
        Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
          return new WebViewPage(
              title: _datas[index].name, url: _datas[index].link);
        }));
      },
      child: Container(
        padding: EdgeInsets.only(top: 25, left: 25),
        color: _getColor(index),
        child: Text(
          _datas[index].name,
          style: TextStyle(
              color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold),
        ),
      ),
    );
  }

  @override
  AppBar getAppBar() {
    return AppBar(
      title: Text("常用网站"),
      elevation: 0.4,
    );
  }

  @override
  Widget getContentWidget(BuildContext context) {
    return Scaffold(
      body: _getBodyWidget(_datas),
      floatingActionButton: !showToTopBtn
          ? null
          : FloatingActionButton(
          child: Icon(Icons.arrow_upward),
          onPressed: () {
            //返回到顶部时执行动画
            _scrollController.animateTo(.0,
                duration: Duration(milliseconds: 200), curve: Curves.ease);
          }),
    );
  }

  @override
  void onClickErrorWidget() {
    showloading();
    _getData();
  }

  @override
  void dispose() {
    super.dispose();
  }

}


================================================
FILE: lib/ui/drawer/drawer.dart
================================================
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:share/share.dart';
import 'package:wanandroid_ngu/common/application.dart';
import 'package:wanandroid_ngu/common/user.dart';
import 'package:wanandroid_ngu/event/change_theme_event.dart';
import 'package:wanandroid_ngu/event/login_event.dart';
import 'package:wanandroid_ngu/ui/drawer/about.dart';
import 'package:wanandroid_ngu/ui/drawer/collctions.dart';
import 'package:wanandroid_ngu/ui/drawer/common_website.dart';
import 'package:wanandroid_ngu/ui/drawer/pretty.dart';
import 'package:wanandroid_ngu/ui/login/login_page.dart';
import 'package:wanandroid_ngu/util/theme_util.dart';
import 'package:wanandroid_ngu/util/utils.dart';

class DrawerPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new DrawerPageState();
  }
}

class DrawerPageState extends State<DrawerPage> {
  bool isLogin = false;
  String username = "未登录";

  @override
  void initState() {
    super.initState();
    this.registerLoginEvent();
    if (null != User.singleton.userName) {
      isLogin = true;
      username = User.singleton.userName;
    }
  }

  void registerLoginEvent() {
    Application.eventBus.on<LoginEvent>().listen((event) {
      changeUI();
    });
  }

  changeUI() async {
    setState(() {
      isLogin = true;
      username = User.singleton.userName;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: ListView(
        padding: EdgeInsets.zero,
        children: <Widget>[
          UserAccountsDrawerHeader(
            accountName: InkWell(
              child: Text(username,
                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)),
              onTap: () {
                if (!isLogin) {
                  Navigator.of(context)
                      .push(new MaterialPageRoute(builder: (context) {
                    return new LoginPage();
                  }));
                }
              },
            ),
            currentAccountPicture: InkWell(
              child: CircleAvatar(
                backgroundImage: AssetImage('images/head.jpg'),
              ),
              onTap: () {
                if (!isLogin) {
                  Navigator.of(context)
                      .push(new MaterialPageRoute(builder: (context) {
                    return new LoginPage();
                  }));
                }
              },
            ),
          ),
          ListTile(
            title: Text(
              '我的收藏',
              textAlign: TextAlign.left,
            ),
            leading: Icon(Icons.collections, size: 22.0),
            onTap: () {
              if (isLogin) {
                onCollectionClick();
              } else {
                onLoginClick();
              }
            },
          ),
          ListTile(
            title: Text(
              '常用网站',
              textAlign: TextAlign.left,
            ),
            leading: Icon(Icons.web, size: 22.0),
            onTap: () {
              Navigator.of(context)
                  .push(new MaterialPageRoute(builder: (context) {
                return new CommonWebsitePage();
              }));
            },
          ),
          ListTile(
            title: Text(
              '主题',
              textAlign: TextAlign.left,
            ),
            leading: Icon(Icons.settings, size: 22.0),
            onTap: () {
              showDialog(
                context: context,
                builder: (BuildContext context) {
                  return new SimpleDialog(
                    title: Text("设置主题"),
                    children: ThemeUtils.supportColors.map((Color color) {
                      return new SimpleDialogOption(
                        child: Container(
                          padding: EdgeInsets.fromLTRB(10, 8, 10, 8),
                          height: 35,
                          color: color,
                        ),
                        onPressed: () {
                          ThemeUtils.currentColorTheme = color;
                          Utils.setColorTheme(
                              ThemeUtils.supportColors.indexOf(color));
                          changeColorTheme(color);
                          Navigator.of(context).pop();
                        },
                      );
                    }).toList(),
                  );
                },
              );
            },
          ),
          ListTile(
            title: Text(
              '分享',
              textAlign: TextAlign.left,
            ),
            leading: Icon(Icons.share, size: 22.0),
            onTap: () {
              Share.share(
                  '给你推荐一个特别好玩的应用玩安卓客户端,点击下载:https://www.pgyer.com/haFL');
            },
          ),
          ListTile(
            title: Text(
              '妹子图',
              textAlign: TextAlign.left,
            ),
            leading: Icon(Icons.directions_bike, size: 22.0),
            onTap: () {
              Navigator.of(context)
                  .push(new MaterialPageRoute(builder: (context) {
                return new PrettyPage();
              }));
            },
          ),
          ListTile(
            title: Text(
              '关于作者',
              textAlign: TextAlign.left,
            ),
            leading: Icon(Icons.info, size: 22.0),
            onTap: () {
              Navigator.of(context)
                  .push(new MaterialPageRoute(builder: (context) {
                return new AboutMePage();
              }));
            },
          ),
          logoutWidget()
        ],
      ),
    );
  }

  Widget logoutWidget() {
    if (User.singleton.userName != null) {
      return ListTile(
        title: Text(
          '退出登录',
          textAlign: TextAlign.left,
        ),
        leading: Icon(Icons.power_settings_new, size: 22.0),
        onTap: () {
          User.singleton.clearUserInfor();
          setState(() {
            isLogin = false;
            username = "未登录";
          });
        },
      );
    } else {
      return SizedBox(
        height: 0,
      );
    }
  }

  void onCollectionClick() async {
    await Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
      return new CollectionsPage();
    }));
  }

  void onLoginClick() async {
    await Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
      return new LoginPage();
    }));
  }

  changeColorTheme(Color c) {
    Application.eventBus.fire(new ChangeThemeEvent(c));
  }
}


================================================
FILE: lib/ui/drawer/pretty.dart
================================================
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view_gallery.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/pretty_model.dart';

class PrettyPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new PrettyPageState();
  }
}

class PrettyPageState extends State<PrettyPage> {

  //当前页数据
  List<ResultsListBean> _datas = new List();

  //所有的照片数据
  List<PhotoViewGalleryPageOptions> photos = new List();

  int _page = 1;

  Future<Null> _getData() async {
    ApiService().getPrettyGirl((PrettyModel prettyModel) {
      setState(() {
        _datas = prettyModel.results;
        for (int i = 0; i < _datas.length; i++) {
          PhotoViewGalleryPageOptions pageOptions = PhotoViewGalleryPageOptions(
              imageProvider: NetworkImage(_datas[i].url));
          photos.add(pageOptions);
        }
      });
    }, _page);
  }


  @override
  void initState() {
    super.initState();
    _getData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("妹子图"),
      ),
      body: Container(
          child: PhotoViewGallery(
        onPageChanged: (int index) {
          if(index==photos.length-1){//加载到最有一页
            _page++;
            _getData();
          }
        },
        pageOptions: photos,
        backgroundDecoration: BoxDecoration(color: Colors.black87),
      )),
    );
  }
}


================================================
FILE: lib/ui/home/banner.dart
================================================
import 'package:flutter/material.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/banner_model.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';

class BannerWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return BannerWidgetState();
  }
}

class BannerWidgetState extends State<BannerWidget> {

  List<BannerData> _bannerList = new List();

  @override
  void initState() {
    _bannerList.add(null);
    _getBanner();
  }

  Future<Null> _getBanner() {
    ApiService().getBanner((BannerModel _bannerModel) {
      if (_bannerModel.data.length > 0) {
        setState(() {
          _bannerList = _bannerModel.data;
        });
      }
    });

  }

  Widget buildItemImageWidget(BuildContext context, int index) {
    return new InkWell(
      onTap: () {
        Navigator.of(context).push(new MaterialPageRoute(builder: (context){
          return new WebViewPage(title: _bannerList[index].title,url: _bannerList[index].url);
        }));
      },
      child: new Container(
        child: new Image.network(
          _bannerList[index].imagePath,
          fit: BoxFit.fill,
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Swiper(
      itemBuilder: (BuildContext context, int index) {
        if (_bannerList[index] == null ||
            _bannerList[index].imagePath == null) {
          return new Container(
            color: Colors.grey[100],
          );
        } else {
          return buildItemImageWidget(context, index);
        }
      },
      itemCount: _bannerList.length,
      autoplay: true,
      pagination: new SwiperPagination(),
    );;
  }
}


================================================
FILE: lib/ui/home/home_page.dart
================================================
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/base/_base_widget.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/article_model.dart';
import 'package:wanandroid_ngu/ui/home/banner.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';

class HomePage extends BaseWidget {
  @override
  BaseWidgetState<BaseWidget> getState() {
    return HomePageState();
  }
}

class HomePageState extends BaseWidgetState<HomePage> {
  List<Article> _datas = new List();
  //listview控制器
  ScrollController _scrollController = ScrollController();
  bool showToTopBtn = false; //是否显示“返回到顶部”按钮
  int _page = 0;


  @override
  void initState() {
    super.initState();
    setAppBarVisible(false);

    getData();
    _scrollController.addListener(() {
      //滑到了底部,加载更多
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        _getMore();
      }

      //当前位置是否超过屏幕高度
      if (_scrollController.offset < 200 && showToTopBtn) {
        setState(() {
          showToTopBtn = false;
        });
      } else if (_scrollController.offset >= 200 && showToTopBtn == false) {
        setState(() {
          showToTopBtn = true;
        });
      }
    });
  }

  //获取文章列表数据
  Future<Null> getData() async {
    _page = 0;
    ApiService().getArticleList((ArticleModel _articleModel) {
      if (_articleModel.errorCode == 0) {
        //成功
        if (_articleModel.data.datas.length > 0) {
          //有数据
          showContent();
          setState(() {
            _datas.clear();
            _datas.addAll(_articleModel.data.datas);
          });
        } else {
          //数据为空
          showEmpty();
        }
      } else {
        Fluttertoast.showToast(msg: _articleModel.errorMsg);
      }
    }, (DioError error) {
      //发生错误
      print(error.response);
      setState(() {
        showError();
      });
    }, _page);
  }

  //加载更多的数据
  Future<Null> _getMore() async {
    _page++;
    ApiService().getArticleList((ArticleModel _articleModel) {
      if (_articleModel.errorCode == 0) {
        //成功
        if (_articleModel.data.datas.length > 0) {
          //有数据
          showContent();
          setState(() {
            _datas.addAll(_articleModel.data.datas);
          });
        } else {
          //数据为空
          Fluttertoast.showToast(msg: "没有更多数据了");
        }
      } else {
        Fluttertoast.showToast(msg: _articleModel.errorMsg);
      }
    }, (DioError error) {
      //发生错误
      print(error.response);
      setState(() {
        showError();
      });
    }, _page);
  }

  @override
  AppBar getAppBar() {
    return AppBar(
      title: Text("不显示"),
    );
  }

  @override
  Widget getContentWidget(BuildContext context) {
    return Scaffold(
      body: RefreshIndicator(
        displacement: 15,
        onRefresh: getData,
        child: ListView.separated(
            itemBuilder: _renderRow,
            physics: new AlwaysScrollableScrollPhysics(),
            separatorBuilder: (BuildContext context, int index) {
              return Container(
                height: 0.5,
                color: Colors.black26,
              );
            },
            controller: _scrollController,
            //包含轮播图和加载更多
            itemCount: _datas.length + 2),
      ),
      floatingActionButton: !showToTopBtn
          ? null
          : FloatingActionButton(
          child: Icon(Icons.arrow_upward),
          onPressed: () {
            //返回到顶部时执行动画
            _scrollController.animateTo(.0,
                duration: Duration(milliseconds: 200), curve: Curves.ease);
          }),
    );
  }

  Widget _renderRow(BuildContext context, int index) {
    if (index == 0) {
      return Container(
        height: 200,
        color: Colors.green,
        child: new BannerWidget(),
      );
    }

    if (index < _datas.length - 1) {
      return new InkWell(
        onTap: ()  {
           Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
            return new WebViewPage(
                title: _datas[index - 1].title, url: _datas[index - 1].link);
          }));

        },
        child: Column(
          children: <Widget>[
            Container(
              color: Colors.white,
              padding: EdgeInsets.fromLTRB(16, 16, 16, 8),
              child: Row(
                children: <Widget>[
                  Text(
                    _datas[index - 1].author,
                    style: TextStyle(fontSize: 12),
                    textAlign: TextAlign.left,
                  ),
                  Expanded(
                    child: Text(
                      _datas[index - 1].niceDate,
                      style: TextStyle(fontSize: 12),
                      textAlign: TextAlign.right,
                    ),
                  ),
                ],
              ),
            ),
            Container(
              color: Colors.white,
              padding: EdgeInsets.fromLTRB(16, 0, 16, 0),
              child: Row(
                children: <Widget>[
                  Expanded(
                    child: Text(
                      _datas[index - 1].title,
                      maxLines: 2,
                      style: TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.bold,
                        color: const Color(0xFF3D4E5F),
                      ),
                      textAlign: TextAlign.left,
                    ),
                  )
                ],
              ),
            ),
            Container(
              color: Colors.white,
              padding: EdgeInsets.fromLTRB(16, 8, 16, 16),
              child: Row(
                children: <Widget>[
                  Expanded(
                    child: Text(
                      _datas[index - 1].superChapterName,
                      style: TextStyle(fontSize: 12),
                      textAlign: TextAlign.left,
                    ),
                  )
                ],
              ),
            ),
          ],
        ),
      );
    }
    return null;
  }

  @override
  void dispose() {
    super.dispose();
    _scrollController.dispose();
  }

  @override
  bool get wantKeepAlive => true;

  @override
  void onClickErrorWidget() {
    showloading();
    getData();
  }
}

================================================
FILE: lib/ui/knowledge/knowledge.dart
================================================
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/base/_base_widget.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/system_tree_model.dart';
import 'package:wanandroid_ngu/ui/knowledge/knowledge_content.dart';
import 'package:wanandroid_ngu/util/utils.dart';

class KnowledgePage extends BaseWidget {
  @override
  BaseWidgetState<BaseWidget> getState() {
    return KnowledgePageState();
  }
}

class KnowledgePageState extends BaseWidgetState<KnowledgePage> {
  List<SystemTreeData> _datas = new List();
  //listview控制器
  ScrollController _scrollController = ScrollController();
  bool showToTopBtn = false; //是否显示“返回到顶部”按钮

  @override
  void initState() {
    super.initState();
    setAppBarVisible(false);
    _getData();

    _scrollController.addListener(() {
      //当前位置是否超过屏幕高度
      if (_scrollController.offset < 200 && showToTopBtn) {
        setState(() {
          showToTopBtn = false;
        });
      } else if (_scrollController.offset >= 200 && showToTopBtn == false) {
        setState(() {
          showToTopBtn = true;
        });
      }
    });
  }

  Future<Null> _getData() async {
    ApiService().getSystemTree((SystemTreeModel _systemTreeModel) {
      if (_systemTreeModel.errorCode == 0) {
        //成功
        if (_systemTreeModel.data.length > 0) {
          //有数据
          showContent();
          setState(() {
            _datas.clear();
            _datas.addAll(_systemTreeModel.data);
          });
        } else {
          //数据为空
          showEmpty();
        }
      } else {
        Fluttertoast.showToast(msg: _systemTreeModel.errorMsg);
      }
    },(DioError error) {
      //发生错误
      print(error.response);
      showError();
    });
  }

  Widget _renderRow(BuildContext context, int index) {
    if (index < _datas.length) {
      return InkWell(
          onTap: () {
            Navigator.of(context)
                .push(new MaterialPageRoute(builder: (context) {
              return new KnowledgeContentPage(new ValueKey(_datas[index]));
            }));
          },
          child: Container(
            color: Colors.white,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Expanded(
                    child: Container(
                  padding: EdgeInsets.all(16),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    children: <Widget>[
                      Container(
                        alignment: Alignment.centerLeft,
                        padding: EdgeInsets.only(bottom: 8),
                        child: Text(
                          _datas[index].name,
                          style: TextStyle(
                              fontSize: 16,
                              color: Color(0xFF3D4E5F),
                              fontWeight: FontWeight.bold),
                          textAlign: TextAlign.left,
                        ),
                      ),
                      Container(
                          alignment: Alignment.centerLeft,
                          child: buildChildren(_datas[index].children)),
                    ],
                  ),
                )),
                Icon(Icons.chevron_right)
              ],
            ),
          ));
    }
    return null;
  }

  Widget buildChildren(List<SystemTreeChild> children) {
    List<Widget> tiles = []; //先建一个数组用于存放循环生成的widget
    Widget content; //单独一个widget组件,用于返回需要生成的内容widget
    for (var item in children) {
      tiles.add(
        new Chip(
          materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
          backgroundColor: Utils.getChipBgColor(item.name),
          label: new Text(item.name),
//          avatar: new CircleAvatar(backgroundColor: Colors.blue,child: Text("A"),),
        ),
      );
    }

    content = Wrap(
        spacing: 12,
        runSpacing: 12,
        alignment: WrapAlignment.start,
        children: tiles);

    return content;
  }

  @override
  void dispose() {
    super.dispose();
    _scrollController.dispose();
  }

  @override
  AppBar getAppBar() {
    return AppBar(
      title: Text("不显示"),
    );
  }

  @override
  Widget getContentWidget(BuildContext context) {
    return Scaffold(
      body: RefreshIndicator(
        displacement: 15,
        onRefresh: _getData,
        child: ListView.separated(
          itemBuilder: _renderRow,
          physics: new AlwaysScrollableScrollPhysics(),
          separatorBuilder: (BuildContext context, int index) {
            return Container(
              height: 0.5,
              color: Colors.black26,
            );
          },
          itemCount: _datas.length,
          controller: _scrollController,
        ),
      ),
      floatingActionButton: !showToTopBtn ? null : FloatingActionButton(
          child: Icon(Icons.arrow_upward),
          onPressed: () {
            //返回到顶部时执行动画
            _scrollController.animateTo(.0,
                duration: Duration(milliseconds: 200),
                curve: Curves.ease
            );
          }
      ),
    );
  }

  @override
  void onClickErrorWidget() {
    showloading();
    _getData();
  }

}


================================================
FILE: lib/ui/knowledge/knowledge_content.dart
================================================
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/base/_base_widget.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/system_tree_content_model.dart';
import 'package:wanandroid_ngu/model/system_tree_model.dart';
import 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';

class KnowledgeContentPage extends StatefulWidget {
  SystemTreeData data;

  KnowledgeContentPage(ValueKey<SystemTreeData> key) : super(key: key) {
    this.data = key.value;
  }

  @override
  State<StatefulWidget> createState() {
    return KnowledgeContentPageState();
  }
}

class KnowledgeContentPageState extends State<KnowledgeContentPage>
    with TickerProviderStateMixin {
  SystemTreeData _datas;
  TabController _tabController;

  @override
  void initState() {
    super.initState();
    _datas = widget.data;
  }

  @override
  void dispose() {
    super.dispose();
    _tabController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    _tabController =
        new TabController(length: _datas.children.length, vsync: this);
    return new Scaffold(
      appBar: new AppBar(
        title: Text(_datas.name),
        bottom: new TabBar(
            indicatorColor: Colors.white,
            labelStyle:TextStyle(fontSize: 16),
            unselectedLabelStyle: TextStyle(fontSize: 16),
            controller: _tabController,
            isScrollable: true,
            tabs: _datas.children.map((SystemTreeChild item) {
              return Tab(
                text: item.name,
              );
            }).toList()),
      ),
      body: TabBarView(

        controller: _tabController,
        children: _datas.children.map((item) {
          return NewsList(
            item.id,
          );
        }).toList(),
      ),
    );
  }
}

//知识体系文章列表
class NewsList extends BaseWidget {
  final int id;
  NewsList(this.id);

  @override
  BaseWidgetState<BaseWidget> getState() {
    return _NewsListState();
  } //知识体系id
}

class _NewsListState extends BaseWidgetState<NewsList> {
  List<SystemTreeContentChild> _datas = new List();
  ScrollController _scrollController = ScrollController(); //listview的控制器
  int _page = 0;

  @override
  void initState() {
    setAppBarVisible(false);
    showloading();
    getData();
    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        _getMore();
      }
    });
  }

  Future<Null> getData() async {
    _page = 0;
    int _id = widget.id;

    ApiService().getSystemTreeContent(
        (SystemTreeContentModel _systemTreeContentModel) {

          if (_systemTreeContentModel.errorCode == 0) {
            //成功
            if (_systemTreeContentModel.data.datas.length > 0) {
              //有数据
              showContent();
              setState(() {
                _datas = _systemTreeContentModel.data.datas;
              });
            } else {
              //数据为空
              showEmpty();
            }
          } else {
            Fluttertoast.showToast(msg: _systemTreeContentModel.errorMsg);
          }
    },(DioError error) {
      //发生错误
      print(error.response);
      showError();
    }, _page, _id);
  }

  Future<Null> _getMore() async {
    _page++;
    int _id = widget.id;

    ApiService().getSystemTreeContent(
        (SystemTreeContentModel _systemTreeContentModel) {

          if (_systemTreeContentModel.errorCode == 0) {
            //成功
            if (_systemTreeContentModel.data.datas.length > 0) {
              //有数据
              showContent();
              setState(() {
                _datas.addAll(_systemTreeContentModel.data.datas);
              });
            } else {
              //数据为空
              Fluttertoast.showToast(msg: "没有更多数据了");
            }
          } else {
            Fluttertoast.showToast(msg: _systemTreeContentModel.errorMsg);
          }
    },(DioError error) {
      //发生错误
      print(error.response);
      showError();
    }, _page, _id);
  }

  Widget _renderRow(BuildContext context, int index) {
    if (index < _datas.length) {
      return InkWell(
        child: Container(
          child: _newsRow(_datas[index]),
        ),
        onTap: () {
          Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
            return new WebViewPage(
                title: _datas[index].title, url: _datas[index].link);
          }));
        },
      );
    }
    return null;
  }

  //新闻列表单个item
  Widget _newsRow(SystemTreeContentChild item) {
    return new Container(
      color: Colors.white,
      padding: EdgeInsets.all(16),
      child: Column(
        children: <Widget>[
          new Container(
              padding: EdgeInsets.fromLTRB(8, 8, 8, 8),
              child: new Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Text(
                    item.author,
                    style: TextStyle(fontSize: 12, color: Colors.grey),
                  ),
                  new Expanded(
                    child: new Text(
                      item.niceDate,
                      style: TextStyle(fontSize: 12, color: Colors.grey),
                      textAlign: TextAlign.right,
                    ),
                  ),
                ],
              )),
          Container(
              padding: EdgeInsets.fromLTRB(8, 0, 8, 8),
              child: Row(
                children: <Widget>[
                  Expanded(
                      child: Text(
                    item.title,
                    style: TextStyle(
                        fontSize: 16,
                        color: const Color(0xFF3D4E5F),
                        fontWeight: FontWeight.bold),
                    textAlign: TextAlign.left,
                  ))
                ],
              )),
          Container(
              padding: EdgeInsets.fromLTRB(8, 0, 8, 8),
              child: Row(
                children: <Widget>[
                  Text(
                    item.superChapterName,
                    style: TextStyle(fontSize: 12, color: Colors.grey),
                  ),
                  new Text(
                    "/" + item.chapterName,
                    style: TextStyle(fontSize: 12, color: Colors.grey),
                    textAlign: TextAlign.right,
                  ),
                ],
              )),
        ],
      ),
    );
  }

  @override
  AppBar getAppBar() {
    return AppBar(
      title: Text("不显示"),
    );
  }

  @override
  Widget getContentWidget(BuildContext context) {
    return RefreshIndicator(
      onRefresh: getData,
      child: ListView.separated(
        physics: new AlwaysScrollableScrollPhysics(),
        itemBuilder: _renderRow,
        itemCount: _datas.length + 1,
        controller: _scrollController,
        separatorBuilder: (BuildContext context, int index) {
          return Container(
            height: 0.5,
            color: Colors.black26,
          );
        },
      ),
    );
  }

  @override
  void onClickErrorWidget() {
    showloading();
    getData();
  }
}


================================================
FILE: lib/ui/login/login_page.dart
================================================
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:wanandroid_ngu/common/application.dart';
import 'package:wanandroid_ngu/common/user.dart';
import 'package:wanandroid_ngu/event/login_event.dart';
import 'package:wanandroid_ngu/http/api_service.dart';
import 'package:wanandroid_ngu/model/user_model.dart';
import 'package:wanandroid_ngu/util/bubble_indication_painter.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:wanandroid_ngu/util/theme_util.dart';

class LoginPage extends StatefulWidget {
  LoginPage({Key key}) : super(key: key);

  @override
  _LoginPageState createState() => new _LoginPageState();
}

class _LoginPageState extends State<LoginPage>
    with SingleTickerProviderStateMixin {

  Color themeColor = ThemeUtils.currentColorTheme;

  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

  final FocusNode myFocusNodeEmailLogin = FocusNode();
  final FocusNode myFocusNodePasswordLogin = FocusNode();

  final FocusNode myFocusNodePassword = FocusNode();
  final FocusNode myFocusNodeName = FocusNode();

  TextEditingController loginEmailController = new TextEditingController();
  TextEditingController loginPasswordController = new TextEditingController();

  bool _obscureTextLogin = true;
  bool _obscureTextSignup = true;
  bool _obscureTextSignupConfirm = true;

  TextEditingController signupNameController = new TextEditingController();
  TextEditingController signupPasswordController = new TextEditingController();
  TextEditingController signupConfirmPasswordController =
      new TextEditingController();

  PageController _pageController;

  Color left = Colors.black;
  Color right = Colors.white;

  String title = "登录";

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      key: _scaffoldKey,
      body: NotificationListener<OverscrollIndicatorNotification>(
        onNotification: (overscroll) {
          overscroll.disallowGlow();
        },
        child: SingleChildScrollView(
          child: Container(
            width: MediaQuery.of(context).size.width,
            height: MediaQuery.of(context).size.height >= 775.0
                ? MediaQuery.of(context).size.height
                : 775.0,
            decoration: new BoxDecoration(
              gradient: new LinearGradient(
                  colors: [Color(0xFFffffff), Color(0xFFffffff)],
                  begin: const FractionalOffset(0.0, 0.0),
                  end: const FractionalOffset(1.0, 1.0),
                  stops: [0.0, 1.0],
                  tileMode: TileMode.clamp),
            ),
            child: Column(
              mainAxisSize: MainAxisSize.max,
              children: <Widget>[
                Padding(
                  padding: EdgeInsets.only(top: 60.0),
                  child: _buildMenuBar(context),
                ),
                Expanded(
                  flex: 2,
                  child: PageView(
                    controller: _pageController,
                    onPageChanged: (i) {
                      if (i == 0) {
                        setState(() {
                          right = Colors.white;
                          left = Colors.black;
                          title = "登录";
                        });
                      } else if (i == 1) {
                        setState(() {
                          right = Colors.black;
                          left = Colors.white;
                          title = "注册";
                        });
                      }
                    },
                    children: <Widget>[
                      new ConstrainedBox(
                        constraints: const BoxConstraints.expand(),
                        child: _buildSignIn(context),
                      ),
                      new ConstrainedBox(
                        constraints: const BoxConstraints.expand(),
                        child: _buildSignUp(context),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    myFocusNodePassword.dispose();
    myFocusNodeName.dispose();
    _pageController?.dispose();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();

    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);

    _pageController = PageController();
  }

  void showInSnackBar(String value) {
    FocusScope.of(context).requestFocus(new FocusNode());
    _scaffoldKey.currentState?.removeCurrentSnackBar();
    _scaffoldKey.currentState.showSnackBar(new SnackBar(
      content: new Text(
        value,
        textAlign: TextAlign.center,
        style: TextStyle(
          color: Colors.white,
          fontSize: 16.0,
        ),
      ),
      backgroundColor: themeColor,
      duration: Duration(seconds: 3),
    ));
  }

  Widget _buildMenuBar(BuildContext context) {
    return Container(
      width: 300.0,
      height: 50.0,
      decoration: BoxDecoration(
        color: Color(0x552B2B2B),
        borderRadius: BorderRadius.all(Radius.circular(25.0)),
      ),
      child: CustomPaint(
        painter: TabIndicationPainter(pageController: _pageController),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            Expanded(
              child: FlatButton(
                splashColor: Colors.transparent,
                highlightColor: Colors.transparent,
                onPressed: _onSignInButtonPress,
                child: Text(
                  "登录",
                  style: TextStyle(color: left, fontSize: 16.0),
                ),
              ),
            ),
            //Container(height: 33.0, width: 1.0, color: Colors.white),
            Expanded(
              child: FlatButton(
                splashColor: Colors.transparent,
                highlightColor: Colors.transparent,
                onPressed: _onSignUpButtonPress,
                child: Text(
                  "注册",
                  style: TextStyle(
                    color: right,
                    fontSize: 16.0,
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildSignIn(BuildContext context) {
    //登录
    Future<Null> _login() async {
      String username = loginEmailController.text;
      String password = loginPasswordController.text;
      if ((null != username && username.trim().length > 0) &&
          (null != password && password.trim().length > 0)) {
        ApiService().login((UserModel _userModel, Response response) {
          if (_userModel != null) {
            User().saveUserInfo(_userModel, response);
            Application.eventBus.fire(new LoginEvent());
            if (_userModel.errorCode == 0) {
              Fluttertoast.showToast(msg: "登录成功!");
              Navigator.of(context).pop();
            } else {
              Fluttertoast.showToast(msg: _userModel.errorMsg);
            }
          }
        }, username, password);
      } else {
        Fluttertoast.showToast(
          msg: "用户名或者密码不能为空",
        );
      }
    }

    return Container(
      padding: EdgeInsets.only(top: 23.0),
      child: Column(
        children: <Widget>[
          Stack(
            alignment: Alignment.topCenter,
            overflow: Overflow.visible,
            children: <Widget>[
              Card(
                elevation: 2.0,
                color: Colors.white,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(8.0),
                ),
                child: Container(
                  width: 300.0,
                  height: 150.0,
                  child: Column(
                    children: <Widget>[
                      Padding(
                        padding: EdgeInsets.only(
                            top: 10.0, bottom: 10.0, left: 25.0, right: 25.0),
                        child: TextField(
                          focusNode: myFocusNodeEmailLogin,
                          controller: loginEmailController,
                          keyboardType: TextInputType.emailAddress,
                          style: TextStyle(fontSize: 14.0, color: Colors.black),
                          decoration: InputDecoration(
                            border: InputBorder.none,
                            icon: Icon(
                              FontAwesomeIcons.user,
                              color: Colors.black,
                              size: 18.0,
                            ),
                            hintText: "用户名",
                            hintStyle: TextStyle(fontSize: 17.0),
                          ),
                        ),
                      ),
                      Container(
                        width: 250.0,
                        height: 1.0,
                        color: Colors.grey[400],
                      ),
                      Padding(
                        padding: EdgeInsets.only(
                            top: 10.0, bottom: 10.0, left: 25.0, right: 25.0),
                        child: TextField(
                          focusNode: myFocusNodePasswordLogin,
                          controller: loginPasswordController,
                          obscureText: _obscureTextLogin,
                          style: TextStyle(fontSize: 16.0, color: Colors.black),
                          decoration: InputDecoration(
                            border: InputBorder.none,
                            icon: Icon(
                              FontAwesomeIcons.lock,
                              size: 22.0,
                              color: Colors.black,
                            ),
                            hintText: "密码",
                            hintStyle: TextStyle(fontSize: 17.0),
                            suffixIcon: GestureDetector(
                              onTap: _toggleLogin,
                              child: Icon(
                                FontAwesomeIcons.eye,
                                size: 15.0,
                                color: Colors.black,
                              ),
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
              Container(
                margin: EdgeInsets.only(top: 240.0),
                decoration: new BoxDecoration(
                  borderRadius: BorderRadius.all(Radius.circular(5.0)),
                  boxShadow: <BoxShadow>[
                    BoxShadow(
                      color: const Color(0xFFffffff),
                      offset: Offset(1.0, 6.0),
                      blurRadius: 20.0,
                    ),
                    BoxShadow(
                      color: const Color(0xFFffffff),
                      offset: Offset(1.0, 6.0),
                      blurRadius: 20.0,
Download .txt
gitextract_ft2s6f_c/

├── .gitignore
├── .metadata
├── README.md
├── android/
│   ├── app/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           ├── java/
│   │           │   └── com/
│   │           │       └── ngu/
│   │           │           └── wanandroidngu/
│   │           │               └── MainActivity.java
│   │           └── res/
│   │               ├── drawable/
│   │               │   └── launch_background.xml
│   │               └── values/
│   │                   └── styles.xml
│   ├── build.gradle
│   ├── gradle/
│   │   └── wrapper/
│   │       └── gradle-wrapper.properties
│   ├── gradle.properties
│   ├── key.properties
│   ├── settings.gradle
│   └── wandroid_ngu.jks
├── interview.md
├── ios/
│   ├── Flutter/
│   │   ├── AppFrameworkInfo.plist
│   │   ├── Debug.xcconfig
│   │   └── Release.xcconfig
│   ├── Runner/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Assets.xcassets/
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   └── LaunchImage.imageset/
│   │   │       ├── Contents.json
│   │   │       └── README.md
│   │   ├── Base.lproj/
│   │   │   ├── LaunchScreen.storyboard
│   │   │   └── Main.storyboard
│   │   ├── Info.plist
│   │   └── main.m
│   ├── Runner.xcodeproj/
│   │   ├── project.pbxproj
│   │   ├── project.xcworkspace/
│   │   │   └── contents.xcworkspacedata
│   │   └── xcshareddata/
│   │       └── xcschemes/
│   │           └── Runner.xcscheme
│   └── Runner.xcworkspace/
│       └── contents.xcworkspacedata
├── lib/
│   ├── app.dart
│   ├── base/
│   │   └── _base_widget.dart
│   ├── common/
│   │   ├── application.dart
│   │   └── user.dart
│   ├── db/
│   │   └── db_helper.dart
│   ├── event/
│   │   ├── change_theme_event.dart
│   │   └── login_event.dart
│   ├── http/
│   │   ├── api.dart
│   │   ├── api_service.dart
│   │   └── dio_manager.dart
│   ├── loading.dart
│   ├── main.dart
│   ├── model/
│   │   ├── article_model.dart
│   │   ├── banner_model.dart
│   │   ├── base_model.dart
│   │   ├── collection_model.dart
│   │   ├── common_websit_model.dart
│   │   ├── common_website_model.dart
│   │   ├── hotword_model.dart
│   │   ├── hotword_result_model.dart
│   │   ├── navi_model.dart
│   │   ├── pretty_model.dart
│   │   ├── project_tree_model.dart
│   │   ├── projectlist_model.dart
│   │   ├── system_tree_content_model.dart
│   │   ├── system_tree_model.dart
│   │   ├── todo_item.dart
│   │   ├── todolist_model.dart
│   │   ├── user_model.dart
│   │   ├── website_collection_model.dart
│   │   ├── wx_article_content_model.dart
│   │   └── wx_article_title_model.dart
│   ├── splash_screen.dart
│   ├── ui/
│   │   ├── drawer/
│   │   │   ├── about.dart
│   │   │   ├── collctions.dart
│   │   │   ├── common_website.dart
│   │   │   ├── drawer.dart
│   │   │   └── pretty.dart
│   │   ├── home/
│   │   │   ├── banner.dart
│   │   │   └── home_page.dart
│   │   ├── knowledge/
│   │   │   ├── knowledge.dart
│   │   │   └── knowledge_content.dart
│   │   ├── login/
│   │   │   └── login_page.dart
│   │   ├── navigation/
│   │   │   └── navigation.dart
│   │   ├── project/
│   │   │   └── project.dart
│   │   ├── public_ui/
│   │   │   └── webview_page.dart
│   │   ├── publicc/
│   │   │   └── publicc.dart
│   │   └── search/
│   │       ├── hot_search_result.dart
│   │       └── search.dart
│   └── util/
│       ├── bubble_indication_painter.dart
│       ├── style_util.dart
│       ├── theme_util.dart
│       └── utils.dart
├── pubspec.yaml
└── test/
    └── widget_test.dart
Download .txt
SYMBOL INDEX (408 symbols across 55 files)

FILE: android/app/src/main/java/com/ngu/wanandroidngu/MainActivity.java
  class MainActivity (line 7) | public class MainActivity extends FlutterActivity {
    method onCreate (line 8) | @Override

FILE: lib/app.dart
  class App (line 11) | class App extends StatefulWidget {
    method createState (line 15) | AppState createState()
  class AppState (line 19) | class AppState extends State<App> {
    method build (line 34) | Widget build(BuildContext context)
    method _onItemTapped (line 75) | void _onItemTapped(int index)
    method _onWillPop (line 86) | Future<bool> _onWillPop()

FILE: lib/base/_base_widget.dart
  class BaseWidget (line 5) | abstract class BaseWidget extends StatefulWidget {
    method createState (line 10) | BaseWidgetState createState()
    method getState (line 15) | BaseWidgetState getState()
  class BaseWidgetState (line 18) | abstract class BaseWidgetState<T extends BaseWidget> extends State<T> {
    method initState (line 34) | void initState()
    method build (line 39) | Widget build(BuildContext context)
    method dispose (line 56) | void dispose()
    method getContentWidget (line 60) | Widget getContentWidget(BuildContext context)
    method getErrorWidget (line 63) | Widget getErrorWidget()
    method getLoadingWidget (line 103) | Widget getLoadingWidget()
    method getEmptyWidget (line 110) | Widget getEmptyWidget()
    method _getBaseAppBar (line 143) | PreferredSizeWidget _getBaseAppBar()
    method getAppBar (line 153) | AppBar getAppBar()
    method _getBaseErrorWidget (line 155) | Widget _getBaseErrorWidget()
    method _getBassLoadingWidget (line 162) | Widget _getBassLoadingWidget()
    method _getBaseEmptyWidget (line 169) | Widget _getBaseEmptyWidget()
    method onClickErrorWidget (line 177) | void onClickErrorWidget()
    method setErrorContent (line 180) | void setErrorContent(String content)
    method setAppBarVisible (line 189) | void setAppBarVisible(bool isVisible)
    method showContent (line 195) | void showContent()
    method showloading (line 203) | void showloading()
    method showEmpty (line 211) | void showEmpty()
    method showError (line 219) | void showError()
    method setEmptyWidgetContent (line 228) | void setEmptyWidgetContent(String content)
    method setErrorImage (line 237) | void setErrorImage(String imagePath)
    method setEmptyImage (line 246) | void setEmptyImage(String imagePath)

FILE: lib/common/application.dart
  class Application (line 3) | class Application{

FILE: lib/common/user.dart
  class User (line 5) | class User {
    method saveUserInfo (line 18) | void saveUserInfo(UserModel _userModel,Response response)
    method getUserInfo (line 25) | Future<Null> getUserInfo()
    method clearUserInfor (line 44) | void clearUserInfor()

FILE: lib/db/db_helper.dart
  class DatabaseHelper (line 8) | class DatabaseHelper {
    method _onCreate (line 42) | void _onCreate(Database db, int version)
    method saveItem (line 49) | Future<int> saveItem(DataListBean item)
    method getTotalList (line 57) | Future<List> getTotalList()
    method getCount (line 64) | Future<int> getCount()
    method getItem (line 72) | Future<DataListBean> getItem(int id)
    method clear (line 81) | Future<int> clear()
    method deleteItem (line 88) | Future<int> deleteItem(int id)
    method updateItem (line 95) | Future<int> updateItem(DataListBean item)
    method close (line 105) | Future close()

FILE: lib/event/change_theme_event.dart
  class ChangeThemeEvent (line 3) | class ChangeThemeEvent {

FILE: lib/event/login_event.dart
  class LoginEvent (line 1) | class LoginEvent{

FILE: lib/http/api.dart
  class Api (line 2) | class Api{

FILE: lib/http/api_service.dart
  class ApiService (line 25) | class ApiService {
    method getBanner (line 26) | void getBanner(Function callback)
    method getArticleList (line 34) | void getArticleList(Function callback, Function errorback, int _page)
    method getSystemTree (line 46) | void getSystemTree(Function callback, Function errorback)
    method getSystemTreeContent (line 57) | void getSystemTreeContent(Function callback, Function errorback,int _p...
    method getWxList (line 69) | void getWxList(Function callback, Function errorback)
    method getWxArticleList (line 80) | void getWxArticleList(Function callback, int _id, int _page)
    method getNaviList (line 89) | void getNaviList(Function callback, Function errorback)
    method getProjectTree (line 100) | void getProjectTree(Function callback,Function errorback)
    method getProjectList (line 111) | void getProjectList(Function callback, int _page, int _id)
    method getSearchHotWord (line 120) | void getSearchHotWord(Function callback)
    method getSearchResult (line 129) | void getSearchResult(Function callback, Function errorback, int _page,...
    method login (line 144) | void login(Function callback, String _username, String _password)
    method register (line 155) | void register(Function callback, String _username, String _password)
    method getCollectionList (line 170) | void getCollectionList(
    method cancelCollection (line 182) | void cancelCollection(
    method getCommonWebsite (line 199) | void getCommonWebsite(Function callback, Function errorback)
    method getPrettyGirl (line 209) | void getPrettyGirl(Function callback, int _page)
    method cancelWebsiteCollectionList (line 218) | void cancelWebsiteCollectionList(Function callback, int _id)
    method _getOptions (line 231) | Options _getOptions()

FILE: lib/http/dio_manager.dart
  class DioManager (line 5) | class DioManager {

FILE: lib/loading.dart
  class LoadingPage (line 8) | class LoadingPage extends StatefulWidget {
    method createState (line 10) | _LoadingState createState()
  class _LoadingState (line 13) | class _LoadingState extends State<LoadingPage> {
    method initState (line 16) | void initState()
    method _getHasSkip (line 24) | void _getHasSkip ()
    method build (line 38) | Widget build(BuildContext context)

FILE: lib/main.dart
  function main (line 13) | void main()
  function getLoginInfo (line 24) | Future<Null> getLoginInfo()
  class MyApp (line 28) | class MyApp extends StatefulWidget {
    method createState (line 30) | State<StatefulWidget> createState()
  class MyAppState (line 35) | class MyAppState extends State<MyApp> {
    method initState (line 39) | void initState()
    method build (line 58) | Widget build(BuildContext context)

FILE: lib/model/article_model.dart
  class ArticleModel (line 3) | class ArticleModel {
    method toString (line 20) | String toString()
  class Data (line 25) | class Data {
    method toString (line 52) | String toString()
  class Article (line 57) | class Article {
    method toString (line 116) | String toString()
  class Tag (line 121) | class Tag {
    method toString (line 134) | String toString()

FILE: lib/model/banner_model.dart
  class BannerModel (line 3) | class BannerModel {
    method toString (line 24) | String toString()
  class BannerData (line 29) | class BannerData {
    method toString (line 54) | String toString()

FILE: lib/model/base_model.dart
  class BaseModel (line 3) | class BaseModel {
    method toString (line 18) | String toString()

FILE: lib/model/collection_model.dart
  class CollectionModel (line 3) | class CollectionModel {
    method toString (line 20) | String toString()
  class CollectionData (line 25) | class CollectionData {
    method toString (line 52) | String toString()
  class Collection (line 57) | class Collection {
    method toString (line 98) | String toString()

FILE: lib/model/common_websit_model.dart
  class CommonWebsitModel (line 1) | class CommonWebsitModel {
    method fromMap (line 7) | CommonWebsitModel fromMap(Map<String, dynamic> map)
    method fromMapList (line 15) | List<CommonWebsitModel> fromMapList(dynamic mapList)
  class DataListBean (line 25) | class DataListBean {
    method fromMap (line 34) | DataListBean fromMap(Map<String, dynamic> map)
    method fromMapList (line 45) | List<DataListBean> fromMapList(dynamic mapList)
    method toMap (line 53) | Map<String, dynamic> toMap()

FILE: lib/model/common_website_model.dart
  class CommonWebsiteModel (line 3) | class CommonWebsiteModel {
    method toString (line 24) | String toString()
  class CommonWebsiteData (line 29) | class CommonWebsiteData {
    method toString (line 50) | String toString()

FILE: lib/model/hotword_model.dart
  class HotwordModel (line 1) | class HotwordModel {
    method fromMap (line 7) | HotwordModel fromMap(Map<String, dynamic> map)
    method fromMapList (line 15) | List<HotwordModel> fromMapList(dynamic mapList)
  class DataListBean (line 25) | class DataListBean {
    method fromMap (line 33) | DataListBean fromMap(Map<String, dynamic> map)
    method fromMapList (line 43) | List<DataListBean> fromMapList(dynamic mapList)

FILE: lib/model/hotword_result_model.dart
  class HotwordResultModel (line 1) | class HotwordResultModel {
    method fromMap (line 7) | HotwordResultModel fromMap(Map<String, dynamic> map)
    method fromMapList (line 15) | List<HotwordResultModel> fromMapList(dynamic mapList)
  class DataBean (line 25) | class DataBean {
    method fromMap (line 34) | DataBean fromMap(Map<String, dynamic> map)
    method fromMapList (line 46) | List<DataBean> fromMapList(dynamic mapList)
  class DatasListBean (line 55) | class DatasListBean {
    method fromMap (line 81) | DatasListBean fromMap(Map<String, dynamic> map)
    method fromMapList (line 109) | List<DatasListBean> fromMapList(dynamic mapList)
  class TagsListBean (line 118) | class TagsListBean {
    method fromMap (line 122) | TagsListBean fromMap(Map<String, dynamic> map)
    method fromMapList (line 129) | List<TagsListBean> fromMapList(dynamic mapList)

FILE: lib/model/navi_model.dart
  class NaviModel (line 3) | class NaviModel {
    method toString (line 24) | String toString()
  class NaviData (line 29) | class NaviData {
    method toString (line 48) | String toString()
  class NaviArticle (line 53) | class NaviArticle {
    method toString (line 112) | String toString()

FILE: lib/model/pretty_model.dart
  class PrettyModel (line 1) | class PrettyModel {
    method fromMap (line 7) | PrettyModel fromMap(Map<String, dynamic> map)
    method fromMapList (line 14) | List<PrettyModel> fromMapList(dynamic mapList)
  class ResultsListBean (line 24) | class ResultsListBean {
    method fromMap (line 36) | ResultsListBean fromMap(Map<String, dynamic> map)
    method fromMapList (line 50) | List<ResultsListBean> fromMapList(dynamic mapList)

FILE: lib/model/project_tree_model.dart
  class ProjectTreeModel (line 3) | class ProjectTreeModel {
    method toString (line 24) | String toString()
  class ProjectTreeData (line 29) | class ProjectTreeData {
    method toString (line 58) | String toString()

FILE: lib/model/projectlist_model.dart
  class ProjectTreeListModel (line 3) | class ProjectTreeListModel {
    method toString (line 20) | String toString()
  class ProjectTreeListData (line 25) | class ProjectTreeListData {
    method toString (line 52) | String toString()
  class ProjectTreeListDatas (line 57) | class ProjectTreeListDatas {
    method toString (line 116) | String toString()
  class ProjectTreeListTag (line 121) | class ProjectTreeListTag {
    method toString (line 134) | String toString()

FILE: lib/model/system_tree_content_model.dart
  class SystemTreeContentModel (line 3) | class SystemTreeContentModel {
    method toString (line 20) | String toString()
  class SystemTreeContentData (line 25) | class SystemTreeContentData {
    method toString (line 52) | String toString()
  class SystemTreeContentChild (line 57) | class SystemTreeContentChild {
    method toString (line 116) | String toString()

FILE: lib/model/system_tree_model.dart
  class SystemTreeModel (line 3) | class SystemTreeModel {
    method toString (line 24) | String toString()
  class SystemTreeData (line 29) | class SystemTreeData {
    method toString (line 58) | String toString()
  class SystemTreeChild (line 63) | class SystemTreeChild {
    method toString (line 92) | String toString()

FILE: lib/model/todo_item.dart
  class TodoItem (line 3) | class TodoItem extends StatelessWidget {
    method toMap (line 20) | Map<String, dynamic> toMap()
    method build (line 39) | Widget build(BuildContext context)

FILE: lib/model/todolist_model.dart
  class TodoListModel (line 3) | class TodoListModel {
    method toString (line 20) | String toString()
  class TodoListData (line 25) | class TodoListData {
    method toString (line 49) | String toString()
  class TodoListDatas (line 54) | class TodoListDatas {
    method toString (line 71) | String toString()
  class TodoData (line 76) | class TodoData {
    method toString (line 113) | String toString()

FILE: lib/model/user_model.dart
  class UserModel (line 3) | class UserModel {
    method toString (line 20) | String toString()
  class UserData (line 25) | class UserData {
    method toString (line 61) | String toString()

FILE: lib/model/website_collection_model.dart
  class WebsiteCollectionModel (line 3) | class WebsiteCollectionModel {
    method toString (line 24) | String toString()
  class WebsiteCollectionData (line 29) | class WebsiteCollectionData {
    method toString (line 54) | String toString()

FILE: lib/model/wx_article_content_model.dart
  class WxArticleContentModel (line 3) | class WxArticleContentModel {
    method toString (line 20) | String toString()
  class WxArticleContentData (line 25) | class WxArticleContentData {
    method toString (line 52) | String toString()
  class WxArticleContentDatas (line 57) | class WxArticleContentDatas {
    method toString (line 116) | String toString()
  class WxArticleContentTags (line 121) | class WxArticleContentTags {
    method toString (line 134) | String toString()

FILE: lib/model/wx_article_title_model.dart
  class WxArticleTitleModel (line 3) | class WxArticleTitleModel {
    method toString (line 24) | String toString()
  class WxArticleTitleData (line 29) | class WxArticleTitleData {
    method toString (line 58) | String toString()

FILE: lib/splash_screen.dart
  class SplashScreen (line 5) | class SplashScreen extends StatefulWidget {
    method createState (line 7) | State<StatefulWidget> createState()
  class SplashScreenState (line 13) | class SplashScreenState extends State<SplashScreen> {
    method initState (line 18) | void initState()
    method onDonePress (line 73) | void onDonePress()
    method onSkipPress (line 81) | void onSkipPress()
    method _setHasSkip (line 89) | void _setHasSkip ()
    method build (line 96) | Widget build(BuildContext context)

FILE: lib/ui/drawer/about.dart
  class AboutMePage (line 4) | class AboutMePage extends StatefulWidget {
    method createState (line 6) | State<StatefulWidget> createState()
  class AboutMePageState (line 11) | class AboutMePageState extends State<AboutMePage> {
    method build (line 17) | Widget build(BuildContext context)

FILE: lib/ui/drawer/collctions.dart
  class CollectionsPage (line 13) | class CollectionsPage extends BaseWidget {
    method getState (line 15) | BaseWidgetState<BaseWidget> getState()
  class CollectionsPageState (line 20) | class CollectionsPageState extends BaseWidgetState<CollectionsPage> {
    method getData (line 27) | Future<Null> getData()
    method _getMore (line 53) | Future<Null> _getMore()
    method initState (line 79) | void initState()
    method getContentWidget (line 104) | Widget getContentWidget(BuildContext context)
    method _cancelCollection (line 135) | Future<Null> _cancelCollection(int _position, int _id, int _originId)
    method _renderRow (line 152) | Widget _renderRow(BuildContext context, int index)
    method _itemView (line 159) | Widget _itemView(BuildContext context, int index)
    method _slideRow (line 171) | Widget _slideRow(int index, Collection item)
    method _newsRow (line 189) | Widget _newsRow(Collection item)
    method dispose (line 245) | void dispose()
    method onClickErrorWidget (line 251) | void onClickErrorWidget()
    method getAppBar (line 257) | AppBar getAppBar()

FILE: lib/ui/drawer/common_website.dart
  class CommonWebsitePage (line 10) | class CommonWebsitePage extends BaseWidget {
    method getState (line 12) | BaseWidgetState<BaseWidget> getState()
  class CommonWebsitePageState (line 17) | class CommonWebsitePageState extends BaseWidgetState<CommonWebsitePage> {
    method _getData (line 24) | Future<Null> _getData()
    method initState (line 70) | void initState()
    method _getBodyWidget (line 91) | Widget _getBodyWidget(List<DataListBean> datas)
    method _getColor (line 109) | Color _getColor(int index)
    method _renderItem (line 130) | Widget _renderItem(BuildContext context, int index)
    method getAppBar (line 151) | AppBar getAppBar()
    method getContentWidget (line 159) | Widget getContentWidget(BuildContext context)
    method onClickErrorWidget (line 175) | void onClickErrorWidget()
    method dispose (line 181) | void dispose()

FILE: lib/ui/drawer/drawer.dart
  class DrawerPage (line 16) | class DrawerPage extends StatefulWidget {
    method createState (line 18) | State<StatefulWidget> createState()
  class DrawerPageState (line 23) | class DrawerPageState extends State<DrawerPage> {
    method initState (line 28) | void initState()
    method registerLoginEvent (line 37) | void registerLoginEvent()
    method build (line 51) | Widget build(BuildContext context)
    method logoutWidget (line 186) | Widget logoutWidget()
    method onCollectionClick (line 209) | void onCollectionClick()
    method onLoginClick (line 215) | void onLoginClick()

FILE: lib/ui/drawer/pretty.dart
  class PrettyPage (line 6) | class PrettyPage extends StatefulWidget {
    method createState (line 8) | State<StatefulWidget> createState()
  class PrettyPageState (line 13) | class PrettyPageState extends State<PrettyPage> {
    method _getData (line 23) | Future<Null> _getData()
    method initState (line 38) | void initState()
    method build (line 44) | Widget build(BuildContext context)

FILE: lib/ui/home/banner.dart
  class BannerWidget (line 7) | class BannerWidget extends StatefulWidget {
    method createState (line 9) | State<StatefulWidget> createState()
  class BannerWidgetState (line 14) | class BannerWidgetState extends State<BannerWidget> {
    method initState (line 19) | void initState()
    method _getBanner (line 24) | Future<Null> _getBanner()
    method buildItemImageWidget (line 35) | Widget buildItemImageWidget(BuildContext context, int index)
    method build (line 52) | Widget build(BuildContext context)

FILE: lib/ui/home/home_page.dart
  class HomePage (line 10) | class HomePage extends BaseWidget {
    method getState (line 12) | BaseWidgetState<BaseWidget> getState()
  class HomePageState (line 17) | class HomePageState extends BaseWidgetState<HomePage> {
    method initState (line 26) | void initState()
    method getData (line 52) | Future<Null> getData()
    method _getMore (line 81) | Future<Null> _getMore()
    method getAppBar (line 109) | AppBar getAppBar()
    method getContentWidget (line 116) | Widget getContentWidget(BuildContext context)
    method _renderRow (line 146) | Widget _renderRow(BuildContext context, int index)
    method dispose (line 229) | void dispose()
    method onClickErrorWidget (line 238) | void onClickErrorWidget()

FILE: lib/ui/knowledge/knowledge.dart
  class KnowledgePage (line 10) | class KnowledgePage extends BaseWidget {
    method getState (line 12) | BaseWidgetState<BaseWidget> getState()
  class KnowledgePageState (line 17) | class KnowledgePageState extends BaseWidgetState<KnowledgePage> {
    method initState (line 24) | void initState()
    method _getData (line 43) | Future<Null> _getData()
    method _renderRow (line 68) | Widget _renderRow(BuildContext context, int index)
    method buildChildren (line 114) | Widget buildChildren(List<SystemTreeChild> children)
    method dispose (line 138) | void dispose()
    method getAppBar (line 144) | AppBar getAppBar()
    method getContentWidget (line 151) | Widget getContentWidget(BuildContext context)
    method onClickErrorWidget (line 183) | void onClickErrorWidget()

FILE: lib/ui/knowledge/knowledge_content.dart
  class KnowledgeContentPage (line 10) | class KnowledgeContentPage extends StatefulWidget {
    method createState (line 18) | State<StatefulWidget> createState()
  class KnowledgeContentPageState (line 23) | class KnowledgeContentPageState extends State<KnowledgeContentPage>
    method initState (line 29) | void initState()
    method dispose (line 35) | void dispose()
    method build (line 41) | Widget build(BuildContext context)
  class NewsList (line 73) | class NewsList extends BaseWidget {
    method getState (line 78) | BaseWidgetState<BaseWidget> getState()
  class _NewsListState (line 83) | class _NewsListState extends BaseWidgetState<NewsList> {
    method initState (line 89) | void initState()
    method getData (line 101) | Future<Null> getData()
    method _getMore (line 130) | Future<Null> _getMore()
    method _renderRow (line 159) | Widget _renderRow(BuildContext context, int index)
    method _newsRow (line 177) | Widget _newsRow(SystemTreeContentChild item)
    method getAppBar (line 237) | AppBar getAppBar()
    method getContentWidget (line 244) | Widget getContentWidget(BuildContext context)
    method onClickErrorWidget (line 263) | void onClickErrorWidget()

FILE: lib/ui/login/login_page.dart
  class LoginPage (line 14) | class LoginPage extends StatefulWidget {
    method createState (line 18) | _LoginPageState createState()
  class _LoginPageState (line 21) | class _LoginPageState extends State<LoginPage>
    method build (line 54) | Widget build(BuildContext context)
    method dispose (line 125) | void dispose()
    method initState (line 133) | void initState()
    method showInSnackBar (line 144) | void showInSnackBar(String value)
    method _buildMenuBar (line 161) | Widget _buildMenuBar(BuildContext context)
    method _buildSignIn (line 206) | Widget _buildSignIn(BuildContext context)
    method _login (line 208) | Future<Null> _login()
    method _buildSignUp (line 361) | Widget _buildSignUp(BuildContext context)
    method _regist (line 362) | Future<Null> _regist()
    method _onSignInButtonPress (line 529) | void _onSignInButtonPress()
    method _onSignUpButtonPress (line 535) | void _onSignUpButtonPress()
    method _toggleLogin (line 541) | void _toggleLogin()
    method _toggleSignup (line 548) | void _toggleSignup()
    method _toggleSignupConfirm (line 555) | void _toggleSignupConfirm()

FILE: lib/ui/navigation/navigation.dart
  class NavigationPage (line 10) | class NavigationPage extends BaseWidget {
    method getState (line 12) | BaseWidgetState<BaseWidget> getState()
  class NavigationState (line 17) | class NavigationState extends BaseWidgetState<NavigationPage> {
    method initState (line 24) | void initState()
    method _getData (line 45) | Future<Null> _getData()
    method _rightListView (line 73) | Widget _rightListView(BuildContext context)
    method _renderContent (line 87) | Widget _renderContent(BuildContext context, int index)
    method buildChildren (line 115) | Widget buildChildren(List<NaviArticle> children)
    method getAppBar (line 143) | AppBar getAppBar()
    method getContentWidget (line 151) | Widget getContentWidget(BuildContext context)
    method onClickErrorWidget (line 171) | void onClickErrorWidget()

FILE: lib/ui/project/project.dart
  class ProjectPage (line 13) | class ProjectPage extends BaseWidget {
    method getState (line 15) | BaseWidgetState<BaseWidget> getState()
  class ProjectPageState (line 21) | class ProjectPageState extends BaseWidgetState<ProjectPage>
    method _getData (line 28) | Future<Null> _getData()
    method initState (line 55) | void initState()
    method dispose (line 67) | void dispose()
    method getAppBar (line 76) | AppBar getAppBar()
    method getContentWidget (line 83) | Widget getContentWidget(BuildContext context)
    method onClickErrorWidget (line 117) | void onClickErrorWidget()
  class ProjectList (line 123) | class ProjectList extends StatefulWidget {
    method createState (line 129) | _ProjectListState createState()
  class _ProjectListState (line 134) | class _ProjectListState extends State<ProjectList> {
    method _getData (line 141) | Future<Null> _getData()
    method _getMore (line 151) | Future<Null> _getMore()
    method initState (line 162) | void initState()
    method dispose (line 187) | void dispose()
    method build (line 193) | Widget build(BuildContext context)
    method _renderRow (line 224) | Widget _renderRow(BuildContext context, int index)

FILE: lib/ui/public_ui/webview_page.dart
  class WebViewPage (line 5) | class WebViewPage extends StatefulWidget {
    method createState (line 16) | State<StatefulWidget> createState()
  class WebViewPageState (line 21) | class WebViewPageState extends State<WebViewPage> {
    method initState (line 26) | void initState()
    method build (line 48) | Widget build(BuildContext context)

FILE: lib/ui/publicc/publicc.dart
  class PubliccPage (line 13) | class PubliccPage extends BaseWidget {
    method getState (line 15) | BaseWidgetState<BaseWidget> getState()
  class PubliccPageState (line 20) | class PubliccPageState extends BaseWidgetState<PubliccPage>
    method _getData (line 28) | Future<Null> _getData()
    method initState (line 53) | void initState()
    method dispose (line 66) | void dispose()
    method getAppBar (line 73) | AppBar getAppBar()
    method getContentWidget (line 80) | Widget getContentWidget(BuildContext context)
    method onClickErrorWidget (line 114) | void onClickErrorWidget()
  class NewsList (line 120) | class NewsList extends StatefulWidget {
    method createState (line 125) | _NewsListState createState()
  class _NewsListState (line 130) | class _NewsListState extends State<NewsList> {
    method _getData (line 137) | Future<Null> _getData()
    method _getMore (line 148) | Future<Null> _getMore()
    method initState (line 159) | void initState()
    method dispose (line 184) | void dispose()
    method build (line 190) | Widget build(BuildContext context)
    method _renderRow (line 220) | Widget _renderRow(BuildContext context, int index)

FILE: lib/ui/search/hot_search_result.dart
  class HotResultPage (line 9) | class HotResultPage extends BaseWidget {
    method getState (line 14) | BaseWidgetState<BaseWidget> getState()
  class HotResultPageState (line 19) | class HotResultPageState extends BaseWidgetState<HotResultPage> {
    method _getData (line 26) | Future<Null> _getData()
    method _getMore (line 54) | Future<Null> _getMore()
    method initState (line 83) | void initState()
    method dispose (line 110) | void dispose()
    method _renderRow (line 115) | Widget _renderRow(BuildContext context, int index)
    method getAppBar (line 196) | AppBar getAppBar()
    method getContentWidget (line 203) | Widget getContentWidget(BuildContext context)
    method onClickErrorWidget (line 233) | void onClickErrorWidget()

FILE: lib/ui/search/search.dart
  class SearchPage (line 7) | class SearchPage extends StatefulWidget {
    method createState (line 9) | State<StatefulWidget> createState()
  class SearchPageState (line 14) | class SearchPageState extends State<SearchPage> {
    method initState (line 23) | void initState()
    method _getData (line 60) | Future<Null> _getData()
    method changeContent (line 68) | void changeContent()
    method build (line 82) | Widget build(BuildContext context)
    method buildChildren (line 103) | Widget buildChildren(List<DataListBean> children)

FILE: lib/util/bubble_indication_painter.dart
  class TabIndicationPainter (line 5) | class TabIndicationPainter extends CustomPainter {
    method paint (line 25) | void paint(Canvas canvas, Size size)
    method shouldRepaint (line 49) | bool shouldRepaint(TabIndicationPainter oldDelegate)

FILE: lib/util/style_util.dart
  class StyleUtil (line 4) | class StyleUtil {
    method getTextStyle (line 12) | TextStyle  getTextStyle(Color colors,double fontsizes,bool isFontWeight)
    method getPadding (line 24) | Widget getPadding(Widget w,double all)
    method getPaddingfromLTRB (line 36) | Widget getPaddingfromLTRB(Widget w,{double l,double t,double,r,double b})

FILE: lib/util/theme_util.dart
  class ThemeUtils (line 3) | class ThemeUtils {

FILE: lib/util/utils.dart
  class Utils (line 6) | class Utils {
    method getImgPath (line 10) | String getImgPath(String name, {String format: 'png'})
    method getPinyin (line 14) | String getPinyin(String str)
    method getChipBgColor (line 18) | Color getChipBgColor(String name)
    method nameToColor (line 24) | Color nameToColor(String name)
    method getTimeLine (line 31) | String getTimeLine(BuildContext context, int timeMillis)
    method getTitleFontSize (line 41) | double getTitleFontSize(String title)
    method setColorTheme (line 58) | setColorTheme(int colorThemeIndex)
    method getColorThemeIndex (line 63) | Future<int> getColorThemeIndex()

FILE: test/widget_test.dart
  function main (line 13) | void main()
Condensed preview — 86 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (262K chars).
[
  {
    "path": ".gitignore",
    "chars": 1294,
    "preview": "# Miscellaneous\n*.class\n*.lock\n*.log\n*.pyc\n*.swp\n.DS_Store\n.atom/\n.buildlog/\n.history\n.svn/\n\n# IntelliJ related\n*.iml\n*."
  },
  {
    "path": ".metadata",
    "chars": 305,
    "preview": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrade"
  },
  {
    "path": "README.md",
    "chars": 5592,
    "preview": "## Flutter学习资源汇总持续更新中......\n\n- [Flutter官方网站](https://flutter.dev/)\n- [Flutter中文网](https://flutterchina.club/)\n- wendux的["
  },
  {
    "path": "android/app/build.gradle",
    "chars": 2179,
    "preview": "def localProperties = new Properties()\ndef localPropertiesFile = rootProject.file('local.properties')\nif (localPropertie"
  },
  {
    "path": "android/app/src/main/AndroidManifest.xml",
    "chars": 1976,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.ngu.wanandroidngu\">\n\n    <!-- The "
  },
  {
    "path": "android/app/src/main/java/com/ngu/wanandroidngu/MainActivity.java",
    "chars": 366,
    "preview": "package com.ngu.wanandroidngu;\n\nimport android.os.Bundle;\nimport io.flutter.app.FlutterActivity;\nimport io.flutter.plugi"
  },
  {
    "path": "android/app/src/main/res/drawable/launch_background.xml",
    "chars": 434,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Modify this file to customize your launch splash screen -->\n<layer-list xmln"
  },
  {
    "path": "android/app/src/main/res/values/styles.xml",
    "chars": 361,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <style name=\"LaunchTheme\" parent=\"@android:style/Theme.Black.NoTi"
  },
  {
    "path": "android/build.gradle",
    "chars": 470,
    "preview": "buildscript {\n    repositories {\n        google()\n        jcenter()\n    }\n\n    dependencies {\n        classpath 'com.and"
  },
  {
    "path": "android/gradle/wrapper/gradle-wrapper.properties",
    "chars": 234,
    "preview": "#Fri Jun 23 08:50:38 CEST 2017\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER"
  },
  {
    "path": "android/gradle.properties",
    "chars": 82,
    "preview": "android.enableJetifier=true\nandroid.useAndroidX=true\norg.gradle.jvmargs=-Xmx1536M\n"
  },
  {
    "path": "android/key.properties",
    "chars": 103,
    "preview": "storePassword=wandroid_ngu\nkeyPassword=wandroid_ngu\nkeyAlias=wandroid_ngu\nstoreFile=../wandroid_ngu.jks"
  },
  {
    "path": "android/settings.gradle",
    "chars": 484,
    "preview": "include ':app'\n\ndef flutterProjectRoot = rootProject.projectDir.parentFile.toPath()\n\ndef plugins = new Properties()\ndef "
  },
  {
    "path": "interview.md",
    "chars": 417,
    "preview": "# 一道面试题\n\n> 分享一道面试题,结果有点出乎意料\n\n代码如下:输出结果是什么?\n\n    public class Test {\n\n    public static void main(String[] args) {\n      "
  },
  {
    "path": "ios/Flutter/AppFrameworkInfo.plist",
    "chars": 773,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "ios/Flutter/Debug.xcconfig",
    "chars": 30,
    "preview": "#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "ios/Flutter/Release.xcconfig",
    "chars": 30,
    "preview": "#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "ios/Runner/AppDelegate.h",
    "chars": 103,
    "preview": "#import <Flutter/Flutter.h>\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : FlutterAppDelegate\n\n@end\n"
  },
  {
    "path": "ios/Runner/AppDelegate.m",
    "chars": 424,
    "preview": "#include \"AppDelegate.h\"\n#include \"GeneratedPluginRegistrant.h\"\n\n@implementation AppDelegate\n\n- (BOOL)application:(UIApp"
  },
  {
    "path": "ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 2519,
    "preview": "{\n  \"images\" : [\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-20x20@2x.png\",\n   "
  },
  {
    "path": "ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json",
    "chars": 391,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage.png\",\n      \"scale\" : \"1x\"\n    },\n  "
  },
  {
    "path": "ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md",
    "chars": 336,
    "preview": "# Launch Screen Assets\n\nYou can customize the launch screen with your own desired assets by replacing the image files in"
  },
  {
    "path": "ios/Runner/Base.lproj/LaunchScreen.storyboard",
    "chars": 2377,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "ios/Runner/Base.lproj/Main.storyboard",
    "chars": 1605,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "ios/Runner/Info.plist",
    "chars": 1512,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "ios/Runner/main.m",
    "chars": 226,
    "preview": "#import <Flutter/Flutter.h>\n#import <UIKit/UIKit.h>\n#import \"AppDelegate.h\"\n\nint main(int argc, char* argv[]) {\n  @autor"
  },
  {
    "path": "ios/Runner.xcodeproj/project.pbxproj",
    "chars": 21140,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 152,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodepr"
  },
  {
    "path": "ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme",
    "chars": 3331,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0910\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "ios/Runner.xcworkspace/contents.xcworkspacedata",
    "chars": 152,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodepr"
  },
  {
    "path": "lib/app.dart",
    "chars": 3240,
    "preview": "import 'package:flutter/material.dart';\nimport 'package:wanandroid_ngu/ui/drawer/drawer.dart';\nimport 'package:wanandroi"
  },
  {
    "path": "lib/base/_base_widget.dart",
    "chars": 5814,
    "preview": "import 'dart:ui';\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\n\nabstract class BaseW"
  },
  {
    "path": "lib/common/application.dart",
    "chars": 108,
    "preview": "import 'package:event_bus/event_bus.dart';\n\nclass Application{\n  static EventBus eventBus=new EventBus();\n}\n"
  },
  {
    "path": "lib/common/user.dart",
    "chars": 1262,
    "preview": "import '../model/user_model.dart';\nimport 'package:dio/dio.dart';\nimport 'package:shared_preferences/shared_preferences."
  },
  {
    "path": "lib/db/db_helper.dart",
    "chars": 2846,
    "preview": "import 'dart:io';\nimport 'package:path_provider/path_provider.dart';\nimport 'package:sqflite/sqflite.dart';\nimport 'dart"
  },
  {
    "path": "lib/event/change_theme_event.dart",
    "chars": 133,
    "preview": "import 'package:flutter/material.dart';\n\nclass ChangeThemeEvent {\n\n  Color color;\n\n  ChangeThemeEvent(Color c) {\n    col"
  },
  {
    "path": "lib/event/login_event.dart",
    "chars": 20,
    "preview": "class LoginEvent{\n\n}"
  },
  {
    "path": "lib/http/api.dart",
    "chars": 2520,
    "preview": "\nclass Api{\n  static const String HOME_BANNER = \"https://www.wanandroid.com/banner/json\";\n\n  static const String HOME_AR"
  },
  {
    "path": "lib/http/api_service.dart",
    "chars": 7334,
    "preview": "import 'package:dio/dio.dart';\nimport 'package:wanandroid_ngu/common/user.dart';\nimport 'package:wanandroid_ngu/http/dio"
  },
  {
    "path": "lib/http/dio_manager.dart",
    "chars": 497,
    "preview": "import 'dart:io';\n\nimport 'package:dio/dio.dart';\n\nclass DioManager {\n  Dio _dio;\n\n  DioManager._internal() {\n    _dio ="
  },
  {
    "path": "lib/loading.dart",
    "chars": 1163,
    "preview": "import 'package:flutter/material.dart';\nimport 'dart:async';\n\nimport 'package:shared_preferences/shared_preferences.dart"
  },
  {
    "path": "lib/main.dart",
    "chars": 2052,
    "preview": "import 'package:flutter/material.dart';\nimport 'package:wanandroid_ngu/common/application.dart';\nimport 'package:wanandr"
  },
  {
    "path": "lib/model/article_model.dart",
    "chars": 4644,
    "preview": "import 'dart:convert' show json;\n\nclass ArticleModel {\n\n  int errorCode;\n  String errorMsg;\n  Data data;\n\n  ArticleModel"
  },
  {
    "path": "lib/model/banner_model.dart",
    "chars": 1716,
    "preview": "import 'dart:convert' show json;\n\nclass BannerModel {\n\n  int errorCode;\n  String errorMsg;\n  List<BannerData> data;\n\n  B"
  },
  {
    "path": "lib/model/base_model.dart",
    "chars": 567,
    "preview": "import 'dart:convert' show json;\n\nclass BaseModel {\n\n  int errorCode;\n  String errorMsg;\n\n  BaseModel.fromParams({ this."
  },
  {
    "path": "lib/model/collection_model.dart",
    "chars": 3483,
    "preview": "import 'dart:convert' show json;\n\nclass CollectionModel {\n\n  int errorCode;\n  String errorMsg;\n  CollectionData data;\n\n "
  },
  {
    "path": "lib/model/common_websit_model.dart",
    "chars": 1673,
    "preview": "class CommonWebsitModel {\n\n  String errorMsg;\n  int errorCode;\n  List<DataListBean> data;\n\n  static CommonWebsitModel fr"
  },
  {
    "path": "lib/model/common_website_model.dart",
    "chars": 1573,
    "preview": "import 'dart:convert' show json;\n\nclass CommonWebsiteModel {\n\n  int errorCode;\n  String errorMsg;\n  List<CommonWebsiteDa"
  },
  {
    "path": "lib/model/hotword_model.dart",
    "chars": 1264,
    "preview": "class HotwordModel {\n\n  String errorMsg;\n  int errorCode;\n  List<DataListBean> data;\n\n  static HotwordModel fromMap(Map<"
  },
  {
    "path": "lib/model/hotword_result_model.dart",
    "chars": 3771,
    "preview": "class HotwordResultModel {\n\n  String errorMsg;\n  int errorCode;\n  DataBean data;\n\n  static HotwordResultModel fromMap(Ma"
  },
  {
    "path": "lib/model/navi_model.dart",
    "chars": 4155,
    "preview": "import 'dart:convert' show json;\n\nclass NaviModel {\n\n  int errorCode;\n  String errorMsg;\n  List<NaviData> data;\n\n  NaviM"
  },
  {
    "path": "lib/model/pretty_model.dart",
    "chars": 1487,
    "preview": "class PrettyModel {\n\n\n  bool error;\n  List<ResultsListBean> results;\n\n  static PrettyModel fromMap(Map<String, dynamic> "
  },
  {
    "path": "lib/model/project_tree_model.dart",
    "chars": 1934,
    "preview": "import 'dart:convert' show json;\n\nclass ProjectTreeModel {\n\n  int errorCode;\n  String errorMsg;\n  List<ProjectTreeData> "
  },
  {
    "path": "lib/model/projectlist_model.dart",
    "chars": 4907,
    "preview": "import 'dart:convert' show json;\n\nclass ProjectTreeListModel {\n\n  int errorCode;\n  String errorMsg;\n  ProjectTreeListDat"
  },
  {
    "path": "lib/model/system_tree_content_model.dart",
    "chars": 4492,
    "preview": "import 'dart:convert' show json;\n\nclass SystemTreeContentModel {\n\n  int errorCode;\n  String errorMsg;\n  SystemTreeConten"
  },
  {
    "path": "lib/model/system_tree_model.dart",
    "chars": 3064,
    "preview": "import 'dart:convert' show json;\n\nclass SystemTreeModel {\n\n  int errorCode;\n  String errorMsg;\n  List<SystemTreeData> da"
  },
  {
    "path": "lib/model/todo_item.dart",
    "chars": 1995,
    "preview": "import 'package:flutter/material.dart';\n\nclass TodoItem extends StatelessWidget {\n  String _itemName;\n  String _dateCrea"
  },
  {
    "path": "lib/model/todolist_model.dart",
    "chars": 3383,
    "preview": "import 'dart:convert' show json;\n\nclass TodoListModel {\n\n  int errorCode;\n  String errorMsg;\n  TodoListData data;\n\n  Tod"
  },
  {
    "path": "lib/model/user_model.dart",
    "chars": 2094,
    "preview": "import 'dart:convert' show json;\n\nclass UserModel {\n\n  int errorCode;\n  String errorMsg;\n  UserData data;\n\n  UserModel.f"
  },
  {
    "path": "lib/model/website_collection_model.dart",
    "chars": 1812,
    "preview": "import 'dart:convert' show json;\n\nclass WebsiteCollectionModel {\n\n  int errorCode;\n  String errorMsg;\n  List<WebsiteColl"
  },
  {
    "path": "lib/model/wx_article_content_model.dart",
    "chars": 4933,
    "preview": "import 'dart:convert' show json;\n\nclass WxArticleContentModel {\n\n  int errorCode;\n  String errorMsg;\n  WxArticleContentD"
  },
  {
    "path": "lib/model/wx_article_title_model.dart",
    "chars": 1967,
    "preview": "import 'dart:convert' show json;\n\nclass WxArticleTitleModel {\n\n  int errorCode;\n  String errorMsg;\n  List<WxArticleTitle"
  },
  {
    "path": "lib/splash_screen.dart",
    "chars": 3118,
    "preview": "import 'package:flutter/material.dart';\nimport 'package:intro_slider/intro_slider.dart';\nimport 'package:shared_preferen"
  },
  {
    "path": "lib/ui/drawer/about.dart",
    "chars": 3337,
    "preview": "import 'package:flutter/material.dart';\nimport 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';\n\nclass AboutMePa"
  },
  {
    "path": "lib/ui/drawer/collctions.dart",
    "chars": 7214,
    "preview": "import 'dart:ui';\nimport 'package:dio/dio.dart';\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter/materi"
  },
  {
    "path": "lib/ui/drawer/common_website.dart",
    "chars": 4735,
    "preview": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\n"
  },
  {
    "path": "lib/ui/drawer/drawer.dart",
    "chars": 6580,
    "preview": "import 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nimport 'package:share/share.dart';\nimpo"
  },
  {
    "path": "lib/ui/drawer/pretty.dart",
    "chars": 1491,
    "preview": "import 'package:flutter/material.dart';\nimport 'package:photo_view/photo_view_gallery.dart';\nimport 'package:wanandroid_"
  },
  {
    "path": "lib/ui/home/banner.dart",
    "chars": 1786,
    "preview": "import 'package:flutter/material.dart';\nimport 'package:flutter_swiper/flutter_swiper.dart';\nimport 'package:wanandroid_"
  },
  {
    "path": "lib/ui/home/home_page.dart",
    "chars": 6453,
    "preview": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\n"
  },
  {
    "path": "lib/ui/knowledge/knowledge.dart",
    "chars": 5357,
    "preview": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\n"
  },
  {
    "path": "lib/ui/knowledge/knowledge_content.dart",
    "chars": 7263,
    "preview": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\n"
  },
  {
    "path": "lib/ui/login/login_page.dart",
    "chars": 20085,
    "preview": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'p"
  },
  {
    "path": "lib/ui/navigation/navigation.dart",
    "chars": 4585,
    "preview": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\n"
  },
  {
    "path": "lib/ui/project/project.dart",
    "chars": 8825,
    "preview": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\n"
  },
  {
    "path": "lib/ui/public_ui/webview_page.dart",
    "chars": 1721,
    "preview": "import 'package:flutter/material.dart';\nimport 'package:flutter_webview_plugin/flutter_webview_plugin.dart';\nimport 'pac"
  },
  {
    "path": "lib/ui/publicc/publicc.dart",
    "chars": 7868,
    "preview": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\n"
  },
  {
    "path": "lib/ui/search/hot_search_result.dart",
    "chars": 6578,
    "preview": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\n"
  },
  {
    "path": "lib/ui/search/search.dart",
    "chars": 3762,
    "preview": "import 'package:flutter/material.dart';\nimport 'package:wanandroid_ngu/http/api_service.dart';\nimport 'package:wanandroi"
  },
  {
    "path": "lib/util/bubble_indication_painter.dart",
    "chars": 1464,
    "preview": "import 'dart:math';\n\nimport 'package:flutter/material.dart';\n\nclass TabIndicationPainter extends CustomPainter {\n  Paint"
  },
  {
    "path": "lib/util/style_util.dart",
    "chars": 882,
    "preview": "import 'package:flutter/material.dart';\n\n\nclass StyleUtil {\n\n  /**\n   * TextStyle:封装\n   * colors:颜色\n   * fontsizes:字体大小\n"
  },
  {
    "path": "lib/util/theme_util.dart",
    "chars": 439,
    "preview": "import 'package:flutter/material.dart';\n\nclass ThemeUtils {\n  // 默认主题色\n  static const Color defaultColor =Colors.redAcce"
  },
  {
    "path": "lib/util/utils.dart",
    "chars": 2103,
    "preview": "import 'package:common_utils/common_utils.dart';\nimport 'package:flutter/material.dart';\nimport 'package:lpinyin/lpinyin"
  },
  {
    "path": "pubspec.yaml",
    "chars": 1810,
    "preview": "name: wanandroid_ngu\ndescription: A new Flutter application.\n\n# The following defines the version and build number for y"
  },
  {
    "path": "test/widget_test.dart",
    "chars": 1053,
    "preview": "// This is a basic Flutter widget test.\n//\n// To perform an interaction with a widget in your test, use the WidgetTester"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the ngu2008/wanandroid GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 86 files (234.2 KB), approximately 62.8k tokens, and a symbol index with 408 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!