Git Product home page Git Product logo

bedrock's Introduction

🐳Flutter Bedrock

🌱v 2.2.0

一款基于MVVM+Provider的快速开发框架。

欢迎提issue和pr,如果对你有帮助的话,给个⭐⭐star⭐⭐吧。 ^.^

我的联系方式:[email protected]

声明

已由 SheepYang1993 迁移到Flutter 2.0, 非常感谢帮助。
框架版本也从2.0.x开始增长。

更新日志

关于集成

框架与插件性质不太相同,且由于个人精力有限可能更新不太及时,建议clone后本地添加,或者fork后yaml依赖。
这样可以解决更新不及时,和定制化需要。

此项目的statefulWidget和路由及相关模块做了二次封装,请务必阅读下方文章加以了解

请看我——bedrock框架的widget和路由入门简介

绘声绘色的Demo

仿网易云音乐APP

主要特性

Android

Android端增加了异常保护 :
全部开启后,理论上,应用在安卓端将不再会崩溃。
(极为严重的连续性异常和系统异常依然会崩溃,不过也可以通过调整策略避免崩溃,但不建议这样)
            //在BaseApp的onCreate内
            AndroidPlatformProtect.initProtect(new DefaultActivityExceptionHandler())
                    ///处理UI线程的异常
                    .protectUIThread()
                    ///处理 activity生命周期的异常
                    .protectActivityStart()
                    ///处理子线程异常
                    .protectChildThread()
                    .init(this);

DefaultActivityExceptionHandler,发生异常后的善后类:
    默认是回退到上一页(或者退出应用),并输出log。

Tip:
建议继承ActivityExceptionHandler 并自定义相关操作。

Tip:
如果是纯flutter项目,
可以考虑注释掉这两个保护[protectUIThread]和[protectActivityStart]
混合项目(或引入的插件含有原生端)的话,可以考虑开启
[protectActivityStart]在混淆下可能会无效或者出现无法预知的问题,建议混淆方案中忽视它(或者屏蔽它)。

Flutter

1、MVVM+Provider,低耦合、逻辑分明、页面代码清晰。Provider提供的状态管理使页面控制和展现更为灵活方便

2、全局异常捕捉:接口业务型和语法型,业务型可根据需要进行处理(如未登录、未授权、超时、无网等等)并实现页面自动切换,语法型可以跳转到指定页面避免红屏(还可在此页面做日志上传)。

3、基础类PageState/WidgetState-Basestate-State、BaseStatelessWidget-StatelessWidget和BaseSkeletonWidget,对常用功能函数进行了封装,轻松配 置骨架屏、屏幕适配、异形屏适配等

4、基类ProviderWidget-Provider和ViewstateModel-ChangeNotifier对 provider等的封装、底层封装了一些常用状态和异常处理功能

5、全局cookie默认SharedPreferences,基础拦截器自动上传app版本等(可以根据需求自定)

6、页面侧滑退出,路由管理模块,常用页面跳转动画的封装等

7、全局toast、骨架屏、缓存、格式化文字、图片选择裁剪和上传、瀑布流和各种Util这些都是优秀的插件所提供的功能(再次感谢所有开源作者)

8、基于Intl的国际化、APP主题切换。

9、你的viewmodel只要是继承ViewStateModel,并注册CacheDataFactory,就可以实现首次加载自动缓存,无网自动显示上次缓存(缓存方式采用的mmkv 高速缓存)

10、viewmodel 混入ExceptionBinding后,可以在内部对所有api 业务异常进行监听。

...更多可以查看更新日志

使用方法

引入

1、将项目clone(master分支)下来,(注意,clone后不要无脑next,其中一步更换项目名时,换为你的)

2、更换 pubspec.yaml中name属性为你的项目名称, 点一下pub get (这时你的项目爆红)

3、全局查找 flutter_bedrock 替换为上面 name 的值(这时项目恢复正常)

4、删除page文件夹下的 demo_page和mine两个文件夹

5、根目录的 README.md和update_log.md 也删除

开发

墙裂建议运行DEMO并查看源码和注释,以及pub中的注释(其中有很多使用频率很高的插件,可以查看他们的文档,熟练使用能提高开发效率)。

很简单,如下操作:
    1、页面/wiget,继承PageState/WidgetState/BaseStatelessWidget
    2、骨架屏继承BaseSkeletonWidget
    3、ViewModel(VM)继承 ViewStateModel的子类,如:SingleViewStateModel、RefreshListViewStateModel(也可以根据需求自己封装)
    
页面代码如下(页面请使用PageState):

class APageState extends PageState{
@override
 Widget build(BuildContext context) {
     return switchStatusBar2Dark(
     ///全局VM 如:用户VM,可以在登录登出时对整个项目进行状态刷新和管理。
     ///框架自己也定义了一些常用地全局VM  可见DEMO
        child: Consumer<全局VM>(
        builder:(ctx,全局VM,child){
            ///当前页面的VM
            return ProviderWidget<当前页面VM>(
                model:初始化你的vm
                onModelReady:(model){
                    启动你的model,///可选
                }
                builder(ctx,你的vm,child){
                    reutrn 你的页面;
                }
            );
            
        }
        )
     );
 }

}
    
    
你的ViewModel(VM)代码:
///自定义ViewModel话,继承自ViewStateModel即可
class YourPageViewModel extends SingleViewStateModel{
    
}

具体使用方法可以见DEMO

GITHUB 集成

当你clone下项目后,可以看到一下几个文件:
    main ///入口
    base_framework ///bedrock 框架核心文件夹
    I10n  /// I10n插件创建,也可能是得你自己手动创建,具体可以百度I10n 了解
    generated ///I10n 在你编辑语言文件后自动生成的 ,请不要编辑这个文件夹下的内容
    page ///你的项目页面  
    service_api  ///项目接口 对应原生的repository
    

我暂时没有打算把base_framework摘出来,通过pub来集成,因为个人可能都有自己的定制需求,pub集成并不便于按照自己的需求修改。 
况且,直接clone集成还是非常简单的,只需要clone项目后将除了base_framework的其它文件夹删除即可。

DEMO

主要分为两部分:功能性演示和综合性演示。请直接clone项目进行运行浏览,我在DEMO加了详尽的注释,强烈建议运行和阅读DEMO的代码。

感谢

再次感谢广大开源者的奉献和大佬的分享,菜鸟的成长离不开各位的帮助。
此框架属于菜鸡初试身手,稚嫩之处还请海涵,不足之处欢迎斧正,不胜感激。

后续

我会持续维护这个库,有问题欢迎提issue和pr,我会尽快回复。
欢迎打赏一杯咖啡,哈哈哈~

image

bedrock's People

Contributors

bladeofgod avatar sheepyang1993 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bedrock's Issues

运行框架,引入的插件方法报错,另外挺多插件空安全警告,建议更新版本

/C:/Users/js03/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/dokit-0.8.0-nullsafety.0/lib/engine/dokit_binding.dart:128:12: Error: The method 'setMockMessageHandler' isn't defined for the class 'BinaryMessenger'.

  • 'BinaryMessenger' is from 'package:flutter/src/services/binary_messenger.dart' ('../../flutter/packages/flutter/lib/src/services/binary_messenger.dart').
    Try correcting the name to the name of an existing method, or defining a method named 'setMockMessageHandler'.
    origin.setMockMessageHandler(channel, handler);
    ^^^^^^^^^^^^^^^^^^^^^
    /C:/Users/js03/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/dokit-0.8.0-nullsafety.0/lib/engine/dokit_binding.dart:138:52: Error: The argument type 'Future<ByteData?>? Function(ByteData?)?' can't be assigned to the parameter type 'Future<ByteData?>? Function(ByteData?)' because 'Future<ByteData?>? Function(ByteData?)?' is nullable and 'Future<ByteData?>? Function(ByteData?)' isn't.
  • 'Future' is from 'dart:async'.
  • 'ByteData' is from 'dart:typed_data'.
    return origin.checkMockMessageHandler(channel, handler);
    ^
    /C:/Users/js03/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/dokit-0.8.0-nullsafety.0/lib/engine/dokit_http.dart:77:27: Error: A value of type 'Future Function(Uri, String, String)?' can't be assigned to a variable of type 'Future Function(Uri, String, String?)?' because 'String?' is nullable and 'String' isn't.
  • 'Future' is from 'dart:async'.
  • 'Uri' is from 'dart:core'.
    origin.authenticate = f;
    ^
    /C:/Users/js03/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/dokit-0.8.0-nullsafety.0/lib/engine/dokit_http.dart:84:32: Error: A value of type 'Future Function(String, int, String, String)?' can't be assigned to a variable of type 'Future Function(String, int, String, String?)?' because 'String?' is nullable and 'String' isn't.
  • 'Future' is from 'dart:async'.
    origin.authenticateProxy = f;
    ^

demo运行不了

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel master, 1.20.0-1.0.pre.57, on Microsoft Windows [Version 10.0.18363.900], locale zh-CN)
[!] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[✓] Visual Studio - develop for Windows (Visual Studio Community 2019 16.7.0 Preview 2.0)
[✓] Android Studio (version 4.0)
[✓] VS Code, 64-bit edition (version 1.46.0)
[✓] Connected device (2 available)

! Doctor found issues in 1 category.

用系统的BottomNavigationBar构建报错

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bedrock/base_framework/widget_state/base_state.dart';
import 'package:flutter_bedrock/base_framework/widget_state/page_state.dart';
import 'package:flutter_bedrock/page/demo_page/main/first_page.dart';
import 'package:flutter_bedrock/page/demo_page/main/second_page.dart';
import 'package:flutter_bedrock/page/demo_page/main/third_page.dart';
import 'package:oktoast/oktoast.dart';

import 'first_page.dart';
import 'second_page.dart';

typedef TransportScrollController = Function(ScrollController controller);

List itemList() {
return [
BottomNavigationBarItem(
title: Text("首页"),
// activeIcon: Image.asset(TKImages.tabbar_home_select, fit: BoxFit.contain),
// icon: Image.asset(TKImages.tabbar_home_unselect, fit: BoxFit.contain)
icon: Icon(Icons.home),
),
BottomNavigationBarItem(
title: Text("动态"),
// activeIcon: Image.asset(TKImages.tabbar_find_select, fit: BoxFit.contain),
// icon: Image.asset(TKImages.tabbar_find_unselect, fit: BoxFit.contain)
icon: Icon(Icons.insert_invitation),
),
BottomNavigationBarItem(
title: Container(),
// icon: Image.asset(TKImages.tabbar_add, fit: BoxFit.contain),
icon: Icon(
Icons.add_circle,
size: 44,
),
),
BottomNavigationBarItem(
title: Text("消息"),
// activeIcon: Image.asset(TKImages.tabbar_school_select, fit: BoxFit.contain),
// icon: Image.asset(TKImages.tabbar_school_unselect, fit: BoxFit.contain)
icon: Icon(Icons.chrome_reader_mode),
),
BottomNavigationBarItem(
title: Text("我的"),
// activeIcon: Image.asset(TKImages.tabbar_mine_select, fit: BoxFit.contain),
// icon: Image.asset(TKImages.tabbar_mine_unselect, fit: BoxFit.contain)
icon: Icon(Icons.person),
),
];
}

class MainPageState1 extends PageState {
final PageController pageController = PageController();
int selectIndex = 0;

ScrollController firstController;

DateTime lastPress;

jumpByIndex(int index) {
pageController.jumpToPage(index);
}

@OverRide
void initState() {
// TODO: implement initState
super.initState();
}

int _currentIndex = 0;

final List pageList = [
// FindPage(),
FirstPageState(null).generateWidget(),
SecondPageState().generateWidget(),
SecondPageState().generateWidget(),
SecondPageState().generateWidget(),
];

@OverRide
Widget build(BuildContext context) {
return switchStatusBar2Dark(
isSetDark: true,
child: Container(
color: Colors.white,
width: getWidthPx(750),
height: getHeightPx(1334),
child: Scaffold(
body: IndexedStack(
index: _currentIndex,
children: pageList,
),
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.red,
items: itemList(),
type: BottomNavigationBarType.fixed,
currentIndex: _currentIndex,
selectedFontSize: 10,
unselectedFontSize: 10,
selectedIconTheme: IconThemeData(
size: 24,
),
unselectedIconTheme: IconThemeData(size: 24),
onTap: (index) {
if (index == 2) {}
setState(() {
_currentIndex = index;
});
},
),
),
));
}

Widget normalIcon(IconData iconData) {
return Icon(
iconData,
color: Colors.grey,
);
}

Widget activeIcon(IconData iconData) {
return Icon(
iconData,
color: Colors.blue,
);
}

Widget buildBottomItem({
int index,
Icon icon,
Icon iconActive,
}) {
return GestureDetector(
onTap: () {
if (selectIndex != index) {
pageController.jumpToPage(index);
} else if (selectIndex == 0) {
firstController?.animateTo(0,
duration: Duration(microseconds: 500), curve: Curves.easeIn);
}
},
child: Container(
width: getWidthPx(80),
height: getWidthPx(80),
child: selectIndex == index ? iconActive : icon,
),
);
}
}

报错信息如下

════════ Exception caught by rendering library ═════════════════════════════════
Each child must be laid out exactly once.
The relevant error-causing widget was
Scaffold

ExceptionBinding是如何使ViewModel对内部api进行异常捕获和监听调用的?

看到这个功能的更新:ExceptionBinding,使viewModel可以对内部的所有api接口的异常捕获

目前我的view model实现了ExceptionBinding的notifyException方法以及监听者注册,但是看了框架代码之后,没发现在什么地方来调用注册的监听。麻烦能不能解释一下?谢谢了大佬!!

注:
1.只在exception_pitcher.dart中看到view model InitData()的异常状态捕获
2.未看到其他地方对非initData()的api异常监听回调使用

无法运行

项目无法启动
flutter Invalid Podfile file: no implicit conversion of nil into String
请问项目还需要怎么配置吗?网上的方案都试过了,始终无法运行。

拉取最新代码,插件更新到最新版本,运行报错

The plugins flutter_custom_dialog, launch_review, open_file, share use a deprecated version of the Android embedding.
To avoid unexpected runtime failures, or future build failures, try to see if these plugins support the Android V2 embedding. Otherwise, consider removing them since a future release of Flutter will remove these deprecated APIs.
If you are plugin author, take a look at the docs for migrating the plugin to the V2 embedding: https://flutter.dev/go/android-plugin-migration.
Launching lib/main.dart on Android SDK built for x86 in debug mode...
Running Gradle task 'assembleDebug'...
Error: Cannot run with sound null safety, because the following dependencies
don't support null safety:

  • package:pull_to_refresh

For solutions, see https://dart.dev/go/unsound-null-safety
../../../.pub-cache/hosted/pub.flutter-io.cn/dokit-0.8.0-nullsafety.0/lib/engine/dokit_binding.dart:128:12: Error: The method 'setMockMessageHandler' isn't defined for the class 'BinaryMessenger'.

  • 'BinaryMessenger' is from 'package:flutter/src/services/binary_messenger.dart' ('../../flutter/packages/flutter/lib/src/services/binary_messenger.dart').
    Try correcting the name to the name of an existing method, or defining a method named 'setMockMessageHandler'.
    origin.setMockMessageHandler(channel, handler);
    ^^^^^^^^^^^^^^^^^^^^^
    ../../../.pub-cache/hosted/pub.flutter-io.cn/dokit-0.8.0-nullsafety.0/lib/engine/dokit_binding.dart:138:52: Error: The argument type 'Future<ByteData?>? Function(ByteData?)?' can't be assigned to the parameter type 'Future<ByteData?>? Function(ByteData?)' because 'Future<ByteData?>? Function(ByteData?)?' is nullable and 'Future<ByteData?>? Function(ByteData?)' isn't.

  • 'Future' is from 'dart:async'.

  • 'ByteData' is from 'dart:typed_data'.
    return origin.checkMockMessageHandler(channel, handler);
    ^
    ../../../.pub-cache/hosted/pub.flutter-io.cn/pull_to_refresh-1.6.5/lib/src/internals/indicator_wrap.dart:632:9: Error: A value of type 'ValueNotifier' can't be assigned to a variable of type 'ValueNotifier'.

  • 'ValueNotifier' is from 'package:flutter/src/foundation/change_notifier.dart' ('../../flutter/packages/flutter/lib/src/foundation/change_notifier.dart').
    ? refresher.controller.headerMode
    ^
    ../../../.pub-cache/hosted/pub.flutter-io.cn/dokit-0.8.0-nullsafety.0/lib/engine/dokit_http.dart:77:27: Error: A value of type 'Future Function(Uri, String, String)?' can't be assigned to a variable of type 'Future Function(Uri, String, String?)?' because 'String?' is nullable and 'String' isn't.

  • 'Future' is from 'dart:async'.

  • 'Uri' is from 'dart:core'.
    origin.authenticate = f;
    ^
    ../../../.pub-cache/hosted/pub.flutter-io.cn/dokit-0.8.0-nullsafety.0/lib/engine/dokit_http.dart:84:32: Error: A value of type 'Future Function(String, int, String, String)?' can't be assigned to a variable of type 'Future Function(String, int, String, String?)?' because 'String?' is nullable and 'String' isn't.

  • 'Future' is from 'dart:async'.
    origin.authenticateProxy = f;
    ^

      *********************************************************
    

WARNING: This version of share will break your Android build if it or its dependencies aren't compatible with AndroidX.
See https://goo.gl/CP92wY for more information on the problem and how to fix it.
This warning prints for all Android build failures. The real root cause of the error may be unrelated.
*********************************************************

FAILURE: Build failed with an exception.

  • Where:
    Script '/Users/wanghong/Documents/flutter/packages/flutter_tools/gradle/flutter.gradle' line: 1005

  • What went wrong:
    Execution failed for task ':app:compileFlutterBuildDebug'.

Process 'command '/Users/wanghong/Documents/flutter/bin/flutter'' finished with non-zero exit value 1

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

  • Get more help at https://help.gradle.org

BUILD FAILED in 15s
Exception: Gradle task assembleDebug failed with exit code 1

拉取最新代码无法运行?

请问最新版的代码,flutter版本、androidstudio版本、dart版本分别是多少啊。我这里运行不起来
我分别用了flutter2.8.1最新的,flutter2.0.0,flutter2.5.3.androidsutdio版本是最新的,都运行不起来。

1640767666(1)
image

dialog 的问题

在BaseState里面的show对话框,我看到是直接push一个页面,什么都好,就是没处理好返回键的时候,只要show之后按下返回键,就再也show不出来了

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.