kaina404 / FlutterDouBan

🔥🔥🔥Flutter豆瓣客户端,Awesome Flutter Project,全网最100%还原豆瓣客户端。首页、书影音、小组、市集及个人中心,一个不拉。( https://img.xuvip.top/douyademo.mp4)
8.71k stars 1.82k forks source link

项目报错 #36

Open pangliming opened 5 years ago

pangliming commented 5 years ago

image 项目down下来,就报错,这是怎么回事

kaina404 commented 5 years ago

你的sdk环境

pangliming commented 5 years ago

image 就是这样的,刚刚接触,不知道怎么回事

rongcheng2017 commented 5 years ago

我也是这个问题 ,我觉得我项目环境没问题

kaina404 commented 5 years ago

@rongchen2017 好的。我看看

kaina404 commented 5 years ago

@rongcheng2017

CrazyCoderShi commented 5 years ago

@pangliming @rongcheng2017 贴一个flutter doctor出来呀

rongcheng2017 commented 5 years ago

image 上面是flutter doctor的输出,目前用的是android studio ,下面是报错的地方 image

kaina404 commented 5 years ago

@rongcheng2017 你的dart版本是多少,我的是

kaina404 commented 5 years ago

image

rongcheng2017 commented 5 years ago

@kaina404 image

rongcheng2017 commented 5 years ago

@kaina404 麻烦您了

kaina404 commented 5 years ago

@rongcheng2017 安装我下面的代码复制过去试一下。(PS: 你可以吧GitHub跟你的email关联起来,这样我的回复你会立即看到的...)

library cached_network_image;

import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui show instantiateImageCodec, Codec;

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';

/// CachedNetworkImage for Flutter
///
/// Copyright (c) 2017 Rene Floor
///
/// Released under MIT License.
///缓存网络图片
class CachedNetworkImage extends StatefulWidget {
  static List<Object> _registeredErrors = <Object>[];

  /// Creates a widget that displays a [placeholder] while an [imageUrl] is loading
  /// then cross-fades to display the [imageUrl].
  /// Optional [httpHeaders] can be used for example for authentication on the server.
  ///
  /// The [imageUrl], [fadeOutDuration], [fadeOutCurve],
  /// [fadeInDuration], [fadeInCurve], [alignment], [repeat], and
  /// [matchTextDirection] arguments must not be null. Arguments [width],
  /// [height], [fit], [alignment], [repeat] and [matchTextDirection]
  /// are only used for the image and not for the placeholder.
  const CachedNetworkImage({
    Key key,
    this.placeholder,
    @required this.imageUrl,
    this.errorWidget,
    this.fadeOutDuration: const Duration(milliseconds: 300),
    this.fadeOutCurve: Curves.easeOut,
    this.fadeInDuration: const Duration(milliseconds: 700),
    this.fadeInCurve: Curves.easeIn,
    this.width,
    this.height,
    this.fit,
    this.alignment: Alignment.center,
    this.repeat: ImageRepeat.noRepeat,
    this.matchTextDirection: false,
    this.httpHeaders,
  })  : assert(imageUrl != null),
        assert(fadeOutDuration != null),
        assert(fadeOutCurve != null),
        assert(fadeInDuration != null),
        assert(fadeInCurve != null),
        assert(alignment != null),
        assert(repeat != null),
        assert(matchTextDirection != null),
        super(key: key);

  /// Widget displayed while the target [imageUrl] is loading.
  final Widget placeholder;

  /// The target image that is displayed.
  final String imageUrl;

  /// Widget displayed while the target [imageUrl] failed loading.
  final Widget errorWidget;

  /// The duration of the fade-out animation for the [placeholder].
  final Duration fadeOutDuration;

  /// The curve of the fade-out animation for the [placeholder].
  final Curve fadeOutCurve;

  /// The duration of the fade-in animation for the [imageUrl].
  final Duration fadeInDuration;

  /// The curve of the fade-in animation for the [imageUrl].
  final Curve fadeInCurve;

  /// If non-null, require the image to have this width.
  ///
  /// If null, the image will pick a size that best preserves its intrinsic
  /// aspect ratio. This may result in a sudden change if the size of the
  /// placeholder widget does not match that of the target image. The size is
  /// also affected by the scale factor.
  final double width;

  /// If non-null, require the image to have this height.
  ///
  /// If null, the image will pick a size that best preserves its intrinsic
  /// aspect ratio. This may result in a sudden change if the size of the
  /// placeholder widget does not match that of the target image. The size is
  /// also affected by the scale factor.
  final double height;

  /// How to inscribe the image into the space allocated during layout.
  ///
  /// The default varies based on the other fields. See the discussion at
  /// [paintImage].
  final BoxFit fit;

  /// How to align the image within its bounds.
  ///
  /// The alignment aligns the given position in the image to the given position
  /// in the layout bounds. For example, a [Alignment] alignment of (-1.0,
  /// -1.0) aligns the image to the top-left corner of its layout bounds, while a
  /// [Alignment] alignment of (1.0, 1.0) aligns the bottom right of the
  /// image with the bottom right corner of its layout bounds. Similarly, an
  /// alignment of (0.0, 1.0) aligns the bottom middle of the image with the
  /// middle of the bottom edge of its layout bounds.
  ///
  /// If the [alignment] is [TextDirection]-dependent (i.e. if it is a
  /// [AlignmentDirectional]), then an ambient [Directionality] widget
  /// must be in scope.
  ///
  /// Defaults to [Alignment.center].
  ///
  /// See also:
  ///
  ///  * [Alignment], a class with convenient constants typically used to
  ///    specify an [AlignmentGeometry].
  ///  * [AlignmentDirectional], like [Alignment] for specifying alignments
  ///    relative to text direction.
  final AlignmentGeometry alignment;

  /// How to paint any portions of the layout bounds not covered by the image.
  final ImageRepeat repeat;

  /// Whether to paint the image in the direction of the [TextDirection].
  ///
  /// If this is true, then in [TextDirection.ltr] contexts, the image will be
  /// drawn with its origin in the top left (the "normal" painting direction for
  /// images); and in [TextDirection.rtl] contexts, the image will be drawn with
  /// a scaling factor of -1 in the horizontal direction so that the origin is
  /// in the top right.
  ///
  /// This is occasionally used with images in right-to-left environments, for
  /// images that were designed for left-to-right locales. Be careful, when
  /// using this, to not flip images with integral shadows, text, or other
  /// effects that will look incorrect when flipped.
  ///
  /// If this is true, there must be an ambient [Directionality] widget in
  /// scope.
  final bool matchTextDirection;

  // Optional headers for the http request of the image url
  final Map<String, String> httpHeaders;

  @override
  State<StatefulWidget> createState() => new _CachedNetworkImageState();
}

/// The phases a [CachedNetworkImage] goes through.
@visibleForTesting
enum ImagePhase {
  /// The initial state.
  ///
  /// We do not yet know whether the target image is ready and therefore no
  /// animation is necessary, or whether we need to use the placeholder and
  /// wait for the image to load.
  start,

  /// Waiting for the target image to load.
  waiting,

  /// Fading out previous image.
  fadeOut,

  /// Fading in new image.
  fadeIn,

  /// Fade-in complete.
  completed,
}

typedef void _ImageProviderResolverListener();

class _ImageProviderResolver {
  _ImageProviderResolver({
    @required this.state,
    @required this.listener,
  });

  final _CachedNetworkImageState state;
  final _ImageProviderResolverListener listener;

  CachedNetworkImage get widget => state.widget;

  ImageStream _imageStream;
  ImageInfo _imageInfo;

  void resolve(CachedNetworkImageProvider provider) {
    final ImageStream oldImageStream = _imageStream;
    _imageStream = provider.resolve(createLocalImageConfiguration(state.context,
        size: widget.width != null && widget.height != null
            ? new Size(widget.width, widget.height)
            : null));

    if (_imageStream.key != oldImageStream?.key) {
      oldImageStream?.removeListener(_handleImageChanged);
      _imageStream.addListener(_handleImageChanged);
    }
  }

    get _handleImageChanged => _handleImageChanged2;

  void _handleImageChanged2(ImageInfo imageInfo, bool synchronousCall) {
    _imageInfo = imageInfo;
    listener();
  }

  void stopListening() {
    _imageStream?.removeListener(_handleImageChanged);
  }
}

class _CachedNetworkImageState extends State<CachedNetworkImage>
    with TickerProviderStateMixin {
  _ImageProviderResolver _imageResolver;
  CachedNetworkImageProvider _imageProvider;

  AnimationController _controller;
  Animation<double> _animation;

  ImagePhase _phase = ImagePhase.start;
  ImagePhase get phase => _phase;

  bool _hasError;

  @override
  void initState() {
    _hasError = false;
    _imageProvider = new CachedNetworkImageProvider(widget.imageUrl,
        headers: widget.httpHeaders, errorListener: _imageLoadingFailed);
    _imageResolver =
        new _ImageProviderResolver(state: this, listener: _updatePhase);

    _controller = new AnimationController(
      value: 1.0,
      vsync: this,
    );
    _controller.addListener(() {
      setState(() {
        // Trigger rebuild to update opacity value.
      });
    });
    _controller.addStatusListener((AnimationStatus status) {
      _updatePhase();
    });

    super.initState();
  }

  @override
  void didChangeDependencies() {
    _imageProvider
        .obtainKey(createLocalImageConfiguration(context))
        .then<void>((CachedNetworkImageProvider key) {
      if (CachedNetworkImage._registeredErrors.contains(key)) {
        setState(() => _hasError = true);
      }
    });

    _resolveImage();
    super.didChangeDependencies();
  }

  @override
  void didUpdateWidget(CachedNetworkImage oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.imageUrl != oldWidget.imageUrl ||
        widget.placeholder != widget.placeholder) {
      _imageProvider = new CachedNetworkImageProvider(widget.imageUrl,
          headers: widget.httpHeaders,
          errorListener: _imageLoadingFailed);

      _resolveImage();
    }
  }

  @override
  void reassemble() {
    _resolveImage(); // in case the image cache was flushed
    super.reassemble();
  }

  void _resolveImage() {
    _imageResolver.resolve(_imageProvider);

    if (_phase == ImagePhase.start) _updatePhase();
  }

  void _updatePhase() {
    setState(() {
      switch (_phase) {
        case ImagePhase.start:
          if (_imageResolver._imageInfo != null || _hasError)
            _phase = ImagePhase.completed;
          else
            _phase = ImagePhase.waiting;
          break;
        case ImagePhase.waiting:
          if (_hasError && widget.errorWidget == null) {
            _phase = ImagePhase.completed;
            return;
          }

          if (_imageResolver._imageInfo != null || _hasError) {
            if (widget.placeholder == null) {
              _startFadeIn();
            } else {
              _startFadeOut();
            }
          }
          break;
        case ImagePhase.fadeOut:
          if (_controller.status == AnimationStatus.dismissed) {
            _startFadeIn();
          }
          break;
        case ImagePhase.fadeIn:
          if (_controller.status == AnimationStatus.completed) {
            // Done finding in new image.
            _phase = ImagePhase.completed;
          }
          break;
        case ImagePhase.completed:
          // Nothing to do.
          break;
      }
    });
  }

  // Received image data. Begin placeholder fade-out.
  void _startFadeOut() {
    _controller.duration = widget.fadeOutDuration;
    _animation = new CurvedAnimation(
      parent: _controller,
      curve: widget.fadeOutCurve,
    );
    _phase = ImagePhase.fadeOut;
    _controller.reverse(from: 1.0);
  }

  // Done fading out placeholder. Begin target image fade-in.
  void _startFadeIn() {
    _controller.duration = widget.fadeInDuration;
    _animation = new CurvedAnimation(
      parent: _controller,
      curve: widget.fadeInCurve,
    );
    _phase = ImagePhase.fadeIn;
    _controller.forward(from: 0.0);
  }

  @override
  void dispose() {
    _imageResolver.stopListening();
    _controller.dispose();
    super.dispose();
  }

  bool get _isShowingPlaceholder {
    assert(_phase != null);
    switch (_phase) {
      case ImagePhase.start:
      case ImagePhase.waiting:
      case ImagePhase.fadeOut:
        return true;
      case ImagePhase.fadeIn:
      case ImagePhase.completed:
        return _hasError && widget.errorWidget == null;
    }

    return null;
  }

  void _imageLoadingFailed() {
    _imageProvider
        .obtainKey(createLocalImageConfiguration(context))
        .then<void>((CachedNetworkImageProvider key) {
      if (!CachedNetworkImage._registeredErrors.contains(key)) {
        CachedNetworkImage._registeredErrors.add(key);
      }
    });
    _hasError = true;
    _updatePhase();
  }

  @override
  Widget build(BuildContext context) {
    assert(_phase != ImagePhase.start);
    if (_isShowingPlaceholder && widget.placeholder != null) {
      return _fadedWidget(widget.placeholder);
    }

    if (_hasError && widget.errorWidget != null) {
      return _fadedWidget(widget.errorWidget);
    }

    final ImageInfo imageInfo = _imageResolver._imageInfo;
    return new RawImage(
      image: imageInfo?.image,
      width: widget.width,
      height: widget.height,
      scale: imageInfo?.scale ?? 1.0,
      color: new Color.fromRGBO(255, 255, 255, _animation?.value ?? 1.0),
      colorBlendMode: BlendMode.modulate,
      fit: widget.fit,
      alignment: widget.alignment,
      repeat: widget.repeat,
      matchTextDirection: widget.matchTextDirection,
    );
  }

  Widget _fadedWidget(Widget w) {
    return new Opacity(
      opacity: _animation?.value ?? 1.0,
      child: w,
    );
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder description) {
    super.debugFillProperties(description);
    description.add(new EnumProperty<ImagePhase>('phase', _phase));
    description.add(new DiagnosticsProperty<ImageInfo>(
        'pixels', _imageResolver._imageInfo));
    description.add(new DiagnosticsProperty<ImageStream>(
        'image stream', _imageResolver._imageStream));
  }
}

typedef void ErrorListener();

class CachedNetworkImageProvider
    extends ImageProvider<CachedNetworkImageProvider> {
  /// Creates an ImageProvider which loads an image from the [url], using the [scale].
  /// When the image fails to load [errorListener] is called.
  const CachedNetworkImageProvider(this.url,
      {this.scale: 1.0, this.errorListener, this.headers})
      : assert(url != null),
        assert(scale != null);

  /// Web url of the image to load
  final String url;

  /// Scale of the image
  final double scale;

  /// Listener to be called when images fails to load.
  final ErrorListener errorListener;

  // Set headers for the image provider, for example for authentication
  final Map<String, String> headers;

  @override
  Future<CachedNetworkImageProvider> obtainKey(
      ImageConfiguration configuration) {
    return new SynchronousFuture<CachedNetworkImageProvider>(this);
  }

  @override
  ImageStreamCompleter load(CachedNetworkImageProvider key) {
    return new MultiFrameImageStreamCompleter(
        codec: _loadAsync(key),
        scale: key.scale,
        informationCollector: (StringBuffer information) {
          information.writeln('Image provider: $this');
          information.write('Image key: $key');
        });
  }

  Future<ui.Codec> _loadAsync(CachedNetworkImageProvider key) async {
    var cacheManager = await CacheManager.getInstance();
    var file = await cacheManager.getFile(url, headers: headers);
    if (file == null) {
      if (errorListener != null) errorListener();
      return Future<ui.Codec>.error("Couldn't download or retreive file.");
    }
    return await _loadAsyncFromFile(key, file);
  }

  Future<ui.Codec> _loadAsyncFromFile(
      CachedNetworkImageProvider key, File file) async {
    assert(key == this);

    final Uint8List bytes = await file.readAsBytes();

    if (bytes.lengthInBytes == 0) {
      if (errorListener != null) errorListener();
      throw new Exception("File was empty");
    }

    return await ui.instantiateImageCodec(bytes);
  }

  @override
  bool operator ==(dynamic other) {
    if (other.runtimeType != runtimeType) return false;
    final CachedNetworkImageProvider typedOther = other;
    return url == typedOther.url && scale == typedOther.scale;
  }

  @override
  int get hashCode => hashValues(url, scale);

  @override
  String toString() => '$runtimeType("$url", scale: $scale)';
}
zhennayw commented 5 years ago

替换了还是报错: error: The argument type '(StringBuffer) → Null' can't be assigned to the parameter type '() → Iterable'. (argument_type_not_assignable at [doubanapp] lib/widgets/image/cached_network_image.dart:464)

image

/Users/cibn/flutter/bin/flutter doctor --verbose [✓] Flutter (Channel beta, v1.6.3, on Mac OS X 10.14.5 18F132, locale zh-Hans-CN) • Flutter version 1.6.3 at /Users/cibn/flutter • Framework revision bc7bc94083 (5 weeks ago), 2019-05-23 10:29:07 -0700 • Engine revision 8dc3a4cde2 • Dart version 2.3.2 (build 2.3.2-dev.0.0 e3edfd36b2)

[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3) • Android SDK at /Users/cibn/Library/Android/sdk • Android NDK location not configured (optional; useful for native profiling support) • Platform android-28, build-tools 28.0.3 • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01) • All Android licenses accepted.

[✓] iOS toolchain - develop for iOS devices (Xcode 10.2.1) • Xcode at /Applications/Xcode.app/Contents/Developer • Xcode 10.2.1, Build version 10E1001 • ios-deploy 1.9.4 • CocoaPods version 1.6.1

[✓] Android Studio (version 3.3) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin version 34.0.1 • Dart plugin version 182.5215 • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)

[✓] VS Code (version 1.34.0) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.0.2

[✓] Connected device (1 available) • iPhone Xʀ • 80609203-33C1-46F4-B5E3-F7984DE9A1B8 • ios • com.apple.CoreSimulator.SimRuntime.iOS-12-1 (simulator)

kaina404 commented 5 years ago

@zhennayw 你这是什么问题?

yousaywhat commented 5 years ago

@kaina404 _image The argument type '(StringBuffer) → Null' can't be assigned to the parameter type '() → Iterable'.

yousaywhat commented 5 years ago

@kaina404 把这3行注释了也还是不行,还是运行不起来 会报错: Error: The argument type 'void Function(ImageIn fo, bool)' can't be assigned to the parameter type 'ImageStreamListener'

kaina404 commented 5 years ago

@yousaywhat


@override
  ImageStreamCompleter load(CachedNetworkImageProvider key) {
    return new MultiFrameImageStreamCompleter(
        codec: _loadAsync(key),
        scale: key.scale);
  }
yousaywhat commented 5 years ago

@kaina404 删除了报错的三行还是无法运行项目: Compiler message: file:///C:/Users/STARTIASOFT/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/palette_generator-0.1.1/lib/palette_generator.dart:188:29: Error: The argument type 'void Function(ImageIn fo, bool)' can't be assigned to the parameter type 'ImageStreamListener'.

FAILURE: Build failed with an exception.

kaina404 commented 5 years ago

@yousaywhat 你这样改了么? image

yousaywhat commented 5 years ago

@kaina404
改过了 是直接Copy你上面的那份代码粘贴进去的

kaina404 commented 5 years ago

@yousaywhat 你介意变更你的dart sdk 跟我相同的版本么?我感觉是dart sdk问题

yousaywhat commented 5 years ago

@kaina404 我现在的Dart版本是2.3.2 不知道如何回退到2.3.0

kaina404 commented 5 years ago

@yousaywhat 我升级下我的sdk 稍等

passioncsu commented 5 years ago

flutter channel stable && flutter upgrade

切稳定分支即可, beta的分支果然坑很多.

Wycers commented 5 years ago

这应该是官方修改了API。 现在stable分支下也出现这个问题了(版本flutter 1.7.8+hotfix.2)。

guangxingmao commented 5 years ago

同样的报错,用的是最新的Flutter SDK

Wycers commented 5 years ago

似乎这样改就可以了: _imageStream.addListener(_handleImageChanged); 替换为 _imageStream.addListener(ImageStreamListener(_handleImageChanged));

但是项目中使用的palette_generator还存在着无法通过升级解决的问题

kaina404 commented 5 years ago

@Wycers 你把palette_generator的依赖中前面的"^"去掉试一试

Wycers commented 5 years ago

应该不行,我是直接在pubspec.yaml里把它改到了^0.1.1(这个包在pub上的最新版本)然后pub get了

然后我直接进这个包的源码把那个api修了,现在已经能跑了。

但是这种解决方式非常强行,建议找同类包替换一下。

kaina404 commented 5 years ago

@Wycers 是这样的 我是使用0.1.0开发的“^”这个玩意表示支持最新版本,所以你要把这个依赖改成palette_generator: 0.1.0 注意,没有"^"。你这样尝试下。

Wycers commented 5 years ago

我应该是知道你的意思的。项目在flutter 1.5.4的时候是可以正常运行不需要修改的。

但是flutter前两天把stable channel的版本推到了1.7.8,palette_generator已经在flutter 1.7.8中无法运行了。

kaina404 commented 5 years ago

恩恩额 好的 @Wycers

guiyatao commented 5 years ago

image image 1.7.8运行不了报4个错误

kaina404 commented 5 years ago

@guiyatao

改动一:

 @override
  ImageStreamCompleter load(CachedNetworkImageProvider key) {
    return new MultiFrameImageStreamCompleter(
        codec: _loadAsync(key),
        scale: key.scale,
//        informationCollector: (StringBuffer information) {
//          information.writeln('Image provider: $this');
//          information.write('Image key: $key');
//        }
        );
  }

改动二

void resolve(CachedNetworkImageProvider provider) {
    final ImageStream oldImageStream = _imageStream;
    _imageStream = provider.resolve(createLocalImageConfiguration(state.context,
        size: widget.width != null && widget.height != null
            ? new Size(widget.width, widget.height)
            : null));

    if (_imageStream.key != oldImageStream?.key) {
      oldImageStream?.removeListener(_handleImageChanged);
      _imageStream.addListener(_handleImageChanged);
    }
  }

  get _handleImageChanged => _handleImageChanged2;

  void _handleImageChanged2(ImageInfo imageInfo, bool synchronousCall) {
    _imageInfo = imageInfo;
    listener();
  }
guiyatao commented 5 years ago

image 改动之后的报错

kaina404 commented 5 years ago

@guiyatao @Wycers @pangliming @rongcheng2017 @CrazyCoderShi @zhennayw 更新代码即可

guiyatao commented 5 years ago

ok

CalvinLeo commented 5 years ago

`Compiler message: lib/http/http_request.dart:18:64: Error: The argument type 'Utf8Decoder' can't be assigned to the parameter type 'StreamTransformer<Uint8List, dynamic>'.

kaina404 commented 5 years ago

@CalvinLeo 这应该是版本的问题

CalvinLeo commented 5 years ago

是我Flutter版本太低吗?

kaina404 commented 5 years ago

@CalvinLeo 貌似较高🙃

wangyuuuu commented 5 years ago

老哥写的真牛逼,就是新版本好像运行不起来。建议老哥更新一下最新版sdk。运行一下 哈哈哈哈哈

HpBoss commented 4 years ago

运行不了,有一些类提示不存在,而且还有100多个警告!

kaina404 commented 4 years ago

@HpBoss 我的down下来可以的啊 ,下面是我的环境: image

HpBoss commented 4 years ago

image我的flutter完全没问题吧, 他们都在说flutter sdk你的太旧了

HpBoss commented 4 years ago

@HpBoss 我的down下来可以的啊 ,下面是我的环境: image

我用windows run的

HpBoss commented 4 years ago

@HpBoss 我的版本貌似比你的还新些 😁 我是mac。 image

好嘛,我更新一下再试

HpBoss commented 4 years ago

image这是什么问题啊

kaina404 commented 4 years ago

@HpBoss 只是警告而已,命名没有全部小写。

HpBoss commented 4 years ago

那没法运行啊------------------ 原始邮件 ------------------ 发件人: "kaina404"notifications@github.com 发送时间: 2019年9月22日(星期天) 晚上9:58 收件人: "kaina404/FlutterDouBan"FlutterDouBan@noreply.github.com; 抄送: "Joson"193220847@qq.com;"Mention"mention@noreply.github.com; 主题: Re: [kaina404/FlutterDouBan] 项目报错 (#36)

@HpBoss 只是警告而已,命名没有全部小写。

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.