Bläddra i källkod

Merge pull request #1 from ditclear/provider

change to Provider
D•IT•CLEAR 6 år sedan
förälder
incheckning
fd42106903

+ 74 - 0
ios/Podfile

@@ -0,0 +1,74 @@
+# Uncomment this line to define a global platform for your project
+# platform :ios, '9.0'
+
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+  'Debug' => :debug,
+  'Profile' => :release,
+  'Release' => :release,
+}
+
+def parse_KV_file(file, separator='=')
+  file_abs_path = File.expand_path(file)
+  if !File.exists? file_abs_path
+    return [];
+  end
+  pods_ary = []
+  skip_line_start_symbols = ["#", "/"]
+  File.foreach(file_abs_path) { |line|
+      next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
+      plugin = line.split(pattern=separator)
+      if plugin.length == 2
+        podname = plugin[0].strip()
+        path = plugin[1].strip()
+        podpath = File.expand_path("#{path}", file_abs_path)
+        pods_ary.push({:name => podname, :path => podpath});
+      else
+        puts "Invalid plugin specification: #{line}"
+      end
+  }
+  return pods_ary
+end
+
+target 'Runner' do
+  use_frameworks!
+
+  # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
+  # referring to absolute paths on developers' machines.
+  system('rm -rf .symlinks')
+  system('mkdir -p .symlinks/plugins')
+
+  # Flutter Pods
+  generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
+  if generated_xcode_build_settings.empty?
+    puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first."
+  end
+  generated_xcode_build_settings.map { |p|
+    if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
+      symlink = File.join('.symlinks', 'flutter')
+      File.symlink(File.dirname(p[:path]), symlink)
+      pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
+    end
+  }
+
+  # Plugin Pods
+  plugin_pods = parse_KV_file('../.flutter-plugins')
+  plugin_pods.map { |p|
+    symlink = File.join('.symlinks', 'plugins', p[:name])
+    File.symlink(p[:path], symlink)
+    pod p[:name], :path => File.join(symlink, 'ios')
+  }
+end
+
+# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
+install! 'cocoapods', :disable_input_output_paths => true
+
+post_install do |installer|
+  installer.pods_project.targets.each do |target|
+    target.build_configurations.each do |config|
+      config.build_settings['ENABLE_BITCODE'] = 'NO'
+    end
+  end
+end

+ 70 - 5
ios/Runner.xcodeproj/project.pbxproj

@@ -8,10 +8,10 @@
 
 
 /* Begin PBXBuildFile section */
 /* Begin PBXBuildFile section */
 		1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
 		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 */; };
 		3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
 		3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
 		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, ); }; };
 		3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+		49A0E781F5DC337A78432693 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26A54D08E378E3627B6484BF /* Pods_Runner.framework */; };
 		74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
 		74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
 		9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
 		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, ); }; };
 		9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@@ -37,9 +37,10 @@
 /* End PBXCopyFilesBuildPhase section */
 /* End PBXCopyFilesBuildPhase section */
 
 
 /* Begin PBXFileReference section */
 /* Begin PBXFileReference section */
+		13F061945A06ADD12B768281 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
 		1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
 		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>"; };
 		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; };
+		26A54D08E378E3627B6484BF /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
 		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>"; };
 		3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
 		74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
 		74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
@@ -53,6 +54,8 @@
 		97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; 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>"; };
 		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>"; };
 		97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		FA257CEA54836F8FA9858BC4 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
+		FCA0781B93A5DA50A1991354 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 /* End PBXFileReference section */
 
 
 /* Begin PBXFrameworksBuildPhase section */
 /* Begin PBXFrameworksBuildPhase section */
@@ -62,16 +65,27 @@
 			files = (
 			files = (
 				9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
 				9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
 				3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
 				3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
+				49A0E781F5DC337A78432693 /* Pods_Runner.framework in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
 /* End PBXFrameworksBuildPhase section */
 /* End PBXFrameworksBuildPhase section */
 
 
 /* Begin PBXGroup section */
 /* Begin PBXGroup section */
+		563E8ED72581D5AFF1A3962A /* Pods */ = {
+			isa = PBXGroup;
+			children = (
+				FCA0781B93A5DA50A1991354 /* Pods-Runner.debug.xcconfig */,
+				13F061945A06ADD12B768281 /* Pods-Runner.release.xcconfig */,
+				FA257CEA54836F8FA9858BC4 /* Pods-Runner.profile.xcconfig */,
+			);
+			name = Pods;
+			path = Pods;
+			sourceTree = "<group>";
+		};
 		9740EEB11CF90186004384FC /* Flutter */ = {
 		9740EEB11CF90186004384FC /* Flutter */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
 				3B80C3931E831B6300D905FE /* App.framework */,
 				3B80C3931E831B6300D905FE /* App.framework */,
 				3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
 				3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
 				9740EEBA1CF902C7004384FC /* Flutter.framework */,
 				9740EEBA1CF902C7004384FC /* Flutter.framework */,
@@ -88,6 +102,8 @@
 				9740EEB11CF90186004384FC /* Flutter */,
 				9740EEB11CF90186004384FC /* Flutter */,
 				97C146F01CF9000F007C117D /* Runner */,
 				97C146F01CF9000F007C117D /* Runner */,
 				97C146EF1CF9000F007C117D /* Products */,
 				97C146EF1CF9000F007C117D /* Products */,
+				563E8ED72581D5AFF1A3962A /* Pods */,
+				D475B3F4BF2FB0CD2C2A13D4 /* Frameworks */,
 			);
 			);
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
@@ -122,6 +138,14 @@
 			name = "Supporting Files";
 			name = "Supporting Files";
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
+		D475B3F4BF2FB0CD2C2A13D4 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				26A54D08E378E3627B6484BF /* Pods_Runner.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
 /* End PBXGroup section */
 /* End PBXGroup section */
 
 
 /* Begin PBXNativeTarget section */
 /* Begin PBXNativeTarget section */
@@ -129,12 +153,14 @@
 			isa = PBXNativeTarget;
 			isa = PBXNativeTarget;
 			buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
 			buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
 			buildPhases = (
 			buildPhases = (
+				F61CDFE5D2CD14E4594A2636 /* [CP] Check Pods Manifest.lock */,
 				9740EEB61CF901F6004384FC /* Run Script */,
 				9740EEB61CF901F6004384FC /* Run Script */,
 				97C146EA1CF9000F007C117D /* Sources */,
 				97C146EA1CF9000F007C117D /* Sources */,
 				97C146EB1CF9000F007C117D /* Frameworks */,
 				97C146EB1CF9000F007C117D /* Frameworks */,
 				97C146EC1CF9000F007C117D /* Resources */,
 				97C146EC1CF9000F007C117D /* Resources */,
 				9705A1C41CF9048500538489 /* Embed Frameworks */,
 				9705A1C41CF9048500538489 /* Embed Frameworks */,
 				3B06AD1E1E4923F5004D2608 /* Thin Binary */,
 				3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+				81A2FC2B40D71C6487EA248D /* [CP] Embed Pods Frameworks */,
 			);
 			);
 			buildRules = (
 			buildRules = (
 			);
 			);
@@ -187,7 +213,6 @@
 				3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
 				3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
 				9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
 				9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
 				97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
 				97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
-				2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
 				97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
 				97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
@@ -209,6 +234,25 @@
 			shellPath = /bin/sh;
 			shellPath = /bin/sh;
 			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
 			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
 		};
 		};
+		81A2FC2B40D71C6487EA248D /* [CP] Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
 		9740EEB61CF901F6004384FC /* Run Script */ = {
 		9740EEB61CF901F6004384FC /* Run Script */ = {
 			isa = PBXShellScriptBuildPhase;
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
@@ -223,6 +267,28 @@
 			shellPath = /bin/sh;
 			shellPath = /bin/sh;
 			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
 			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
 		};
 		};
+		F61CDFE5D2CD14E4594A2636 /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
 /* End PBXShellScriptBuildPhase section */
 /* End PBXShellScriptBuildPhase section */
 
 
 /* Begin PBXSourcesBuildPhase section */
 /* Begin PBXSourcesBuildPhase section */
@@ -512,7 +578,6 @@
 			defaultConfigurationName = Release;
 			defaultConfigurationName = Release;
 		};
 		};
 /* End XCConfigurationList section */
 /* End XCConfigurationList section */
-
 	};
 	};
 	rootObject = 97C146E61CF9000F007C117D /* Project object */;
 	rootObject = 97C146E61CF9000F007C117D /* Project object */;
 }
 }

+ 3 - 0
ios/Runner.xcworkspace/contents.xcworkspacedata

@@ -4,4 +4,7 @@
    <FileRef
    <FileRef
       location = "group:Runner.xcodeproj">
       location = "group:Runner.xcodeproj">
    </FileRef>
    </FileRef>
+   <FileRef
+      location = "group:Pods/Pods.xcodeproj">
+   </FileRef>
 </Workspace>
 </Workspace>

+ 2 - 1
lib/main.dart

@@ -1,12 +1,13 @@
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 import 'package:mvvm_flutter/view/home_page.dart';
 import 'package:mvvm_flutter/view/home_page.dart';
+import 'package:provider/provider.dart';
 import 'di/app_module.dart';
 import 'di/app_module.dart';
 
 
 
 
 void main() async{
 void main() async{
   // wait init
   // wait init
   await init();
   await init();
-
+  Provider.debugCheckInvalidValueType = null;
   runApp(MyApp());
   runApp(MyApp());
 }
 }
 
 

+ 21 - 11
lib/view/base.dart

@@ -1,7 +1,8 @@
 import 'dart:async';
 import 'dart:async';
 
 
+import 'package:dartin/dartin.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
-import 'package:provide/provide.dart';
+import 'package:provider/provider.dart';
 import 'package:rxdart/rxdart.dart';
 import 'package:rxdart/rxdart.dart';
 
 
 /// normal click event
 /// normal click event
@@ -22,39 +23,48 @@ abstract class ItemPresenter<T> {
 
 
 /// BaseProvide
 /// BaseProvide
 class BaseProvide with ChangeNotifier {
 class BaseProvide with ChangeNotifier {
-
   CompositeSubscription compositeSubscription = CompositeSubscription();
   CompositeSubscription compositeSubscription = CompositeSubscription();
 
 
-
   /// add [StreamSubscription] to [compositeSubscription]
   /// add [StreamSubscription] to [compositeSubscription]
   ///
   ///
   /// 在 [dispose]的时候能进行取消
   /// 在 [dispose]的时候能进行取消
-  addSubscription(StreamSubscription subscription){
+  addSubscription(StreamSubscription subscription) {
     compositeSubscription.add(subscription);
     compositeSubscription.add(subscription);
   }
   }
 
 
   @override
   @override
   void dispose() {
   void dispose() {
+    if (!compositeSubscription.isDisposed) {
+      compositeSubscription.dispose();
+    }
     super.dispose();
     super.dispose();
-    compositeSubscription.dispose();
   }
   }
 }
 }
 
 
 /// page的基类 [PageProvideNode]
 /// page的基类 [PageProvideNode]
 ///
 ///
-/// 隐藏了 [ProviderNode] 的调用
-abstract class PageProvideNode extends StatelessWidget {
-  /// The values made available to the [child].
-  final Providers mProviders = Providers();
+/// 隐藏了 [Provider] 的调用
+abstract class PageProvideNode<T extends ChangeNotifier> extends StatelessWidget implements Presenter {
+  final T mProvider;
+
+  /// 构造函数
+  ///
+  /// [params] 代表注入ViewModel[mProvider]时所需的参数,需按照[mProvider]的构造方法顺序赋值
+  PageProvideNode({List<dynamic> params}) : mProvider = inject<T>(params: params);
 
 
   Widget buildContent(BuildContext context);
   Widget buildContent(BuildContext context);
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
-    return ProviderNode(
-      providers: mProviders,
+    return ChangeNotifierProvider<T>.value(
+      value: mProvider,
       child: buildContent(context),
       child: buildContent(context),
     );
     );
   }
   }
 
 
+  ///点击事件处理
+  ///
+  /// 可通过[action]进行分发
+  @override
+  void onClick(String action) {}
 }
 }

+ 45 - 51
lib/view/home_page.dart

@@ -1,33 +1,23 @@
-import 'package:dartin/dartin.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
-import 'package:mvvm_flutter/helper/dialog.dart';
 import 'package:mvvm_flutter/helper/toast.dart';
 import 'package:mvvm_flutter/helper/toast.dart';
 import 'package:mvvm_flutter/helper/widget_utils.dart';
 import 'package:mvvm_flutter/helper/widget_utils.dart';
 import 'package:mvvm_flutter/view/base.dart';
 import 'package:mvvm_flutter/view/base.dart';
 import 'package:mvvm_flutter/viewmodel/home_provide.dart';
 import 'package:mvvm_flutter/viewmodel/home_provide.dart';
-import 'package:provide/provide.dart';
+import 'package:provider/provider.dart';
 
 
 /// Page :HomePage
 /// Page :HomePage
 ///
 ///
 /// 获取其它页面传递来的参数
 /// 获取其它页面传递来的参数
-/// 构造出各个 Provide 对象,放入到 [mProviders]里
-class HomePage extends PageProvideNode {
-  /// 页面标题
-  final String title;
-
+class HomePage extends PageProvideNode<HomeProvide> {
   /// 提供
   /// 提供
   ///
   ///
   /// 获取参数 [title] 并生成一个[HomeProvide]对象
   /// 获取参数 [title] 并生成一个[HomeProvide]对象
-  /// 然后放入 [mProviders]中
-  HomePage(this.title) {
-    final provide = inject<HomeProvide>(params: [title]);
-    mProviders.provideValue(provide);
-  }
+  HomePage(String title) : super(params: [title]);
 
 
   @override
   @override
   Widget buildContent(BuildContext context) {
   Widget buildContent(BuildContext context) {
-    return _HomeContentPage();
+    return _HomeContentPage(mProvider);
   }
   }
 }
 }
 
 
@@ -36,15 +26,19 @@ class HomePage extends PageProvideNode {
 /// 展示UI (ps:如果有UI地址,最好附上相应的链接)
 /// 展示UI (ps:如果有UI地址,最好附上相应的链接)
 /// 与用户进行交互
 /// 与用户进行交互
 class _HomeContentPage extends StatefulWidget {
 class _HomeContentPage extends StatefulWidget {
+  final HomeProvide provide;
+
+  _HomeContentPage(this.provide);
+
   @override
   @override
   State<StatefulWidget> createState() {
   State<StatefulWidget> createState() {
     return _HomeContentState();
     return _HomeContentState();
   }
   }
 }
 }
 
 
-class _HomeContentState extends State<_HomeContentPage> with SingleTickerProviderStateMixin<_HomeContentPage>
+class _HomeContentState extends State<_HomeContentPage>
+    with TickerProviderStateMixin<_HomeContentPage>
     implements Presenter {
     implements Presenter {
-
   HomeProvide mProvide;
   HomeProvide mProvide;
 
 
   /// 处理动画
   /// 处理动画
@@ -53,11 +47,10 @@ class _HomeContentState extends State<_HomeContentPage> with SingleTickerProvide
 
 
   static const ACTION_LOGIN = "login";
   static const ACTION_LOGIN = "login";
 
 
-  final LoadingDialog loadingDialog = LoadingDialog();
-
   @override
   @override
   void initState() {
   void initState() {
     super.initState();
     super.initState();
+    mProvide = widget.provide;
     _controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 300));
     _controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 300));
     _animation = Tween(begin: 295.0, end: 48.0).animate(_controller)
     _animation = Tween(begin: 295.0, end: 48.0).animate(_controller)
       ..addListener(() {
       ..addListener(() {
@@ -74,7 +67,8 @@ class _HomeContentState extends State<_HomeContentPage> with SingleTickerProvide
 
 
   @override
   @override
   void onClick(String action) {
   void onClick(String action) {
-    if (action == ACTION_LOGIN) {
+    print("onClick:" + action);
+    if (ACTION_LOGIN == action) {
       login();
       login();
     }
     }
   }
   }
@@ -91,8 +85,6 @@ class _HomeContentState extends State<_HomeContentPage> with SingleTickerProvide
       _controller.forward();
       _controller.forward();
     }).doOnDone(() {
     }).doOnDone(() {
       _controller.reverse();
       _controller.reverse();
-    }).doOnCancel(() {
-      print("======cancel======");
     }).listen((_) {
     }).listen((_) {
       //success
       //success
       Toast.show("login success", context, type: Toast.SUCCESS);
       Toast.show("login success", context, type: Toast.SUCCESS);
@@ -105,7 +97,6 @@ class _HomeContentState extends State<_HomeContentPage> with SingleTickerProvide
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
-    mProvide = Provide.value<HomeProvide>(context);
     print("--------build--------");
     print("--------build--------");
     return Material(
     return Material(
       child: Scaffold(
       child: Scaffold(
@@ -128,7 +119,7 @@ class _HomeContentState extends State<_HomeContentPage> with SingleTickerProvide
               ),
               ),
               TextField(
               TextField(
                 obscureText: true,
                 obscureText: true,
-                keyboardType: TextInputType.number,
+                keyboardType: TextInputType.text,
                 decoration: InputDecoration(
                 decoration: InputDecoration(
                   contentPadding: EdgeInsets.all(10.0),
                   contentPadding: EdgeInsets.all(10.0),
                   icon: Icon(Icons.lock),
                   icon: Icon(Icons.lock),
@@ -152,8 +143,12 @@ class _HomeContentState extends State<_HomeContentPage> with SingleTickerProvide
                   margin: EdgeInsets.fromLTRB(12, 12, 12, 0),
                   margin: EdgeInsets.fromLTRB(12, 12, 12, 0),
                   padding: EdgeInsets.all(5.0),
                   padding: EdgeInsets.all(5.0),
                   decoration: BoxDecoration(border: Border.all(color: Colors.blue)),
                   decoration: BoxDecoration(border: Border.all(color: Colors.blue)),
-                  child: Provide<HomeProvide>(
-                    builder: (BuildContext context, Widget child, HomeProvide value) => Text(value.response),
+                  child: Selector<HomeProvide, String>(
+                    selector: (_, data) => data.response,
+                    builder: (context, value, child) {
+                      // 使用Selector,当provide.notifyListeners()时,只有data.response改变的时候才会build
+                      return Text(value);
+                    },
                   ),
                   ),
                 ),
                 ),
               )
               )
@@ -168,30 +163,29 @@ class _HomeContentState extends State<_HomeContentPage> with SingleTickerProvide
   ///
   ///
   /// 按钮宽度根据是否进行请求由[_controller]控制
   /// 按钮宽度根据是否进行请求由[_controller]控制
   /// 当 [mProvide.loading] 为true 时 ,点击事件不生效
   /// 当 [mProvide.loading] 为true 时 ,点击事件不生效
-  Provide<HomeProvide> buildLoginBtnProvide() {
-    return Provide<HomeProvide>(
-              builder: (BuildContext context, Widget child, HomeProvide value) {
-                return CupertinoButton(
-                    onPressed: value.loading ? null : () => onClick(ACTION_LOGIN),
-                    pressedOpacity: 0.8,
-                    child: Container(
-                      alignment: Alignment.center,
-                      width: value.btnWidth,
-                      height: 48,
-                      decoration: BoxDecoration(
-                          borderRadius: BorderRadius.all(Radius.circular(30.0)),
-                          gradient: LinearGradient(colors: [
-                            Color(0xFF686CF2),
-                            Color(0xFF0E5CFF),
-                          ]),
-                          boxShadow: [
-                            BoxShadow(color: Color(0x4D5E56FF), offset: Offset(0.0, 4.0), blurRadius: 13.0)
-                          ]),
-                      child: buildLoginChild(value),
-                    ),
-                  );
-              },
-            );
+  Consumer<HomeProvide> buildLoginBtnProvide() {
+    return Consumer<HomeProvide>(
+      builder: (context, value, child) {
+        // 使用 Consumer ,当provide.notifyListeners()时都会rebuild
+        return CupertinoButton(
+          onPressed: value.loading ? null : () => onClick(ACTION_LOGIN),
+          pressedOpacity: 0.8,
+          child: Container(
+            alignment: Alignment.center,
+            width: value.btnWidth,
+            height: 48,
+            decoration: BoxDecoration(
+                borderRadius: BorderRadius.all(Radius.circular(30.0)),
+                gradient: LinearGradient(colors: [
+                  Color(0xFF686CF2),
+                  Color(0xFF0E5CFF),
+                ]),
+                boxShadow: [BoxShadow(color: Color(0x4D5E56FF), offset: Offset(0.0, 4.0), blurRadius: 13.0)]),
+            child: buildLoginChild(value),
+          ),
+        );
+      },
+    );
   }
   }
 
 
   /// 登录按钮内部的 child
   /// 登录按钮内部的 child
@@ -202,9 +196,9 @@ class _HomeContentState extends State<_HomeContentPage> with SingleTickerProvide
     if (value.loading) {
     if (value.loading) {
       return const CircularProgressIndicator();
       return const CircularProgressIndicator();
     } else {
     } else {
-      return const FittedBox(
+      return FittedBox(
         fit: BoxFit.scaleDown,
         fit: BoxFit.scaleDown,
-        child: const Text(
+        child: Text(
           'Login With Github Account',
           'Login With Github Account',
           maxLines: 1,
           maxLines: 1,
           textAlign: TextAlign.center,
           textAlign: TextAlign.center,

+ 1 - 1
pubspec.yaml

@@ -19,7 +19,7 @@ dependencies:
   # The following adds the Cupertino Icons font to your application.
   # The following adds the Cupertino Icons font to your application.
   # Use with the CupertinoIcons class for iOS style icons.
   # Use with the CupertinoIcons class for iOS style icons.
   cupertino_icons: ^0.1.2
   cupertino_icons: ^0.1.2
-  provide: ^1.0.2
+  provider: ^3.1.0
   dio: 2.0.7
   dio: 2.0.7
   shared_preferences: ^0.5.1+2
   shared_preferences: ^0.5.1+2
   rxdart: ^0.21.0
   rxdart: ^0.21.0