Flutter开发日常问题记录

递归式读取一定要做异常处理,否则遇到异常就会停止递归
  ///递归式读取 fffa电池电量
  void recursiveReadFFFA()async{
    Future.delayed(Duration(seconds: 1),()async{
      List<int>? res;
      ///一定要try catch,否则一旦有异常,递归就会终止
      try{
        res = await observeCharacteristic?.read();
      }catch(e){
        print('BlueToothLogic.recursiveReadFFFA e:${e.toString()}');
      }

      if(res?[0] != null){
        isCharging.value = res![0];
      }
      if(res?[2] != null){
        batteryLevel.value = res![2];
      }
      int? highHex = res?[3];
      int? lowHex = res?[4];
      if(highHex != null && lowHex != null){
        timeStarted.value = highHex* 255 + lowHex;
        fffaList.value = res ?? [];
      }

      recursiveReadFFFA();
    });
  }


Flutter 打包 android端 apk 【终端生成签名文件上传Google Play】
https://juejin.cn/post/6944000831465193480

class _SignUpGuidePageState extends State<SignUpGuidePage> {
  CrossFadeState crossFadeState = CrossFadeState.showFirst;
  Timer? timer;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    timer = Timer.periodic(Duration(seconds: 2), (timer) {
      if(mounted){
        setState(() {
          if (crossFadeState == CrossFadeState.showFirst) {
            crossFadeState = CrossFadeState.showSecond;
          } else {
            crossFadeState = CrossFadeState.showFirst;
          }
        });
      }
    });
  }

  @override
  void dispose() {
    timer?.cancel();
    super.dispose();
  }
}
//断言的使用
assert(initialValue == null || controller == null),
不满足断言会抛异常
//Flutter的架构
Dart =>Skia【OpenGL】=>操作系统=>硬件
自定义UI的方式:
1.Widget组合其他组件
2.自绘CustomPainter、Canvas
3.自己实现RenderObject
ImageProvider的子类有NetworkImage和AssetImage
class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkImage> implements image_provider.NetworkImage
class AssetImage extends AssetBundleImageProvider
abstract class AssetBundleImageProvider extends ImageProvider<AssetBundleImageKey> 
图片加载流程,load=>loadAsyn=>Resolve=>PutIfAbsent
ProxyWidget
class NotificationListener<T extends Notification> extends ProxyWidget 
abstract class ParentDataWidget<T extends ParentData> extends ProxyWidget
abstract class InheritedWidget extends ProxyWidget
NotificationListerner的使用,监听onNotification可以阻止冒泡
Notificaiton的dispatch方法,调用visitAncesterElements向上遍历父级元素

-s指定设备ADB 
adb -s f40ecad7 /Users/jingkairen/Desktop/App/Lumaflex\ Mobile/build/app/outputs/apk/release/LumaFlex.apk
adb: failed to install /Users/jingkairen/Desktop/App/Lumaflex Mobile/build/app/outputs/apk/release/LumaFlex.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package com.nooancehelmet.lumaflex signatures do not match previously installed version; ignoring!]
adb -s f40ecad7 uninstall com.nooancehelmet.lumaflex
异常处理要考虑周全,asyncFunc可能抛异常,可能返回null,还有可能没返回
 ///轮询10次
  Future<void> recursiveTillSuccessFunc(Future<List<int>?> Function() asyncFunc, {bool isFactoryMode = false,int retryCount = 10}) async{
    List<int>? res;
    int count = 0;
    try{
      ///先马上调用一次
      res = await asyncFunc();
      if(res != null){
        serialCodeStreamController.sink.add(res);
        _factoryModeHandle(res, isFactoryMode);
      }
    }catch(e){

      // 创建一个重复性定时器
       Timer.periodic(Duration(milliseconds: 100), (timer) async {
         // 增加计数【一定要先执行,await asyncFunc() 可能永远没有返回,卡死当前线程】
         count++;
         // 如果调用次数达到10次,取消定时器
         if (count >= retryCount) {
           timer.cancel();
           showError(S.of(GlobalUtils.context).read_serial_code_error);
           print('调用次数达到10次,取消定时器');
         }
         print('BlueToothLogic.recursiveTillSuccessFuncTimer.periodic');
        // 调用blueToothLogic.setAmbientLight()
        res = await asyncFunc();
        if(res != null){
          serialCodeStreamController.sink.add(res);
          _factoryModeHandle(res!, isFactoryMode);
          timer.cancel();
        }
      });

    }
  }

android/app/src/main/AndroidManifest.xml 配置蓝牙权限和第三方登录跳转权限

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.kaiyan.energy_lounger_app">
<!--    Chrome谷歌浏览器-->
    <queries>
        <intent>
            <action android:name=
                "android.support.customtabs.action.CustomTabsService" />
        </intent>
    </queries>
<!--    蓝牙权限-->
    <!-- Tell Google Play Store that your app uses Bluetooth LE
     Set android:required="true" if bluetooth is necessary -->
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="false" />

    <!-- New Bluetooth permissions in Android 12
    https://developer.android.com/about/versions/12/features/bluetooth-permissions -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <!-- legacy for Android 11 or lower -->
    <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />

    <!-- legacy for Android 9 or lower -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="28" />
   <application
        android:label="Energy Lounger"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
       <!--    Chrome谷歌浏览器-->
       <activity
           android:name="com.amplifyframework.auth.cognito.activities.HostedUIRedirectActivity"
           android:exported="true">
           <intent-filter>
               <action android:name="android.intent.action.VIEW" />
               <category android:name="android.intent.category.DEFAULT" />
               <category android:name="android.intent.category.BROWSABLE" />
               <data android:scheme="energy-lounger" />
               <data android:scheme="energy-lounger-staging" />
           </intent-filter>
       </activity>
    </application>
</manifest>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容