Skip to content

android 上面所有css样式不生效 #869

@chaorenluo

Description

@chaorenluo

Affected version

0.24.2

Flutter versions

3.38.10

No same issues found.

  • Yes, I search all issues but not found.

Steps to Reproduce

android运行flutter run 安装app后页面设置的css样式全部都没有生效,ios正常生效

Code example

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:webf/webf.dart';
import 'custom_hybrid_history_delegate.dart';
import 'dart:typed_data' show Uint8List;
import 'package:cronet_http/cronet_http.dart';
import 'cronet_adapter.dart';
import 'package:flutter/cupertino.dart';

final RouteObserver<ModalRoute<void>> routeObserver =
    RouteObserver<ModalRoute<void>>();
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

const String demoEntryUrl = 'http://192.168.2.120:5173/';
const String demoControllerName = 'demo';
const String demoInitialRoute = '/';
const Map<String, dynamic>? demoInitialState = null;

void main() async {
  // 初始化控制器
  WebFControllerManager.instance.initialize(
    WebFControllerManagerConfig(
      maxAliveInstances: 4,
      maxAttachedInstances: 1,
      onControllerDisposed: (String name, WebFController controller) {
        print('controller disposed: $name $controller');
      },
      onControllerDetached: (String name, WebFController controller) {
        print('controller detached: $name $controller');
      },
    ),
  );
  WebFControllerManager.instance.addWithPrerendering(
    name: demoControllerName,
    createController: () => WebFController(
      enableBlink: true,
      routeObserver: routeObserver,
      initialRoute: demoInitialRoute,
      initialState: demoInitialState,
    ),
    bundle: WebFBundle.fromUrl(demoEntryUrl),
    setup: (controller) {
      controller.hybridHistory.delegate = CustomHybridHistoryDelegate();
      controller.onLCP = (time, isEvaluated) {
        print('LCP: $time ms');
      };
    },
  );
  runApp(MyApp());
}

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

class MyAppState extends State<MyApp> {
  void initState() {
    super.initState();
  }

  Object? _buildHybridRouteArguments(
    GoRouterState state, {
    required Map<String, String> pathParameters,
    required Map<String, String> queryParameters,
  }) {
    if (state.extra is Map) {
      final merged = <String, dynamic>{};
      for (final entry in (state.extra as Map).entries) {
        merged[entry.key.toString()] = entry.value;
      }
      return <String, dynamic>{
        ...merged,
        if (pathParameters.isNotEmpty) 'pathParameters': pathParameters,
        if (queryParameters.isNotEmpty) 'queryParameters': queryParameters,
      };
    }
    if (state.extra != null) return state.extra;
    if (pathParameters.isEmpty && queryParameters.isEmpty) return null;
    return <String, dynamic>{
      'pathParameters': pathParameters,
      'queryParameters': queryParameters,
    };
  }

  late final GoRouter _router = GoRouter(
    navigatorKey: navigatorKey,
    initialLocation: '/',
    observers: [routeObserver],
    routes: <RouteBase>[
      GoRoute(
        path: '/',
        builder: (context, state) => const FirstPage(title: 'Landing Bay1'),
      ),
      // webf路由
      GoRoute(
        path: '/demo',
        pageBuilder: (context, state) => MaterialPage<void>(
          key: state.pageKey,
          name: state.uri.toString(),
          child: const WebFDemo(
            webfPageName: demoControllerName,
            initialRoute: demoInitialRoute,
            initialState: demoInitialState,
          ),
        ),
      ),
      GoRoute(
        path: '/:webfPath(.*)',
        name: 'universal-webf-route',
        pageBuilder: (context, state) => _buildWebFHybridRoutePage(state),
      ),
    ],
    errorBuilder: (context, state) => Scaffold(
      appBar: AppBar(title: const Text('Route not found')),
      body: Center(
        child: Text(state.error?.toString() ?? 'Unknown routing error'),
      ),
    ),
  );

  Page<void> _buildWebFHybridRoutePage(GoRouterState state) {
    final String path = state.uri.path.replaceFirst('webf', '');
    final pathParameters = Map<String, String>.from(state.pathParameters)
      ..remove('webfPath');
    final queryParameters = state.uri.queryParameters;

    return MaterialPage<void>(
      key: state.pageKey,
      name: state.uri.toString(),
      arguments: _buildHybridRouteArguments(
        state,
        pathParameters: pathParameters,
        queryParameters: queryParameters,
      ),
      child: WebFRouterView.fromControllerName(
        controllerName: demoControllerName,
        path: path,
        builder: (context, controller) => WebFSubView(
          controller: controller,
          onAppBarCreated: (title, routeLinkElement) =>
              AppBar(title: Text(title)),
          path: path,
          // pathParameters: pathParameters,
          // queryParameters: queryParameters,
        ),
        loadingWidget: _WebFDemoState.buildSplashScreen(),
      ),
    );
  }

  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: _router,
      title: 'WebF Demo',
      // showPerformanceOverlay: true,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
    );
  }
}

class FirstPage extends StatefulWidget {
  const FirstPage({super.key, required this.title});

  final String title;

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

class FirstPageState extends State<FirstPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Stack(
        children: [
          Center(
            child: ElevatedButton(
              onPressed: () {
                context.push('/demo');
              },
              child: Text('Open demo'),
            ),
          ),
          // WebFInspectorFloatingPanel(),
        ],
      ),
    );
  }
}

class WebFDemo extends StatefulWidget {
  final String webfPageName;
  final String initialRoute;
  final Map<String, dynamic>? initialState;

  const WebFDemo({
    super.key,
    required this.webfPageName,
    this.initialRoute = '/',
    this.initialState,
  });

  @override
  State<WebFDemo> createState() => _WebFDemoState();
}

class _WebFDemoState extends State<WebFDemo> {
  @override
  Widget build(BuildContext context) {
    // bool isDarkModeEnabled = AdaptiveTheme.of(context).
    return Scaffold(
      appBar: AppBar(
        title: Text('Web1F Demo'),
        actions: [Padding(padding: EdgeInsets.fromLTRB(0, 0, 20, 0))],
      ),
      body: Stack(
        children: [
          WebF.fromControllerName(
            controllerName: widget.webfPageName,
            loadingWidget: buildSplashScreen(),
            initialRoute: widget.initialRoute,
            initialState: widget.initialState,
            onControllerCreated: (controller) {
              print('Controller ready: $controller');
            },
            onBuildSuccess: () {
              print('UI rendered successfully');
            },
            bundle: WebFBundle.fromUrl(demoEntryUrl),
            // createController: () => WebFController(
            //   routeObserver: routeObserver,
            //   initialRoute: widget.initialRoute,
            //   onControllerInit: (controller) async {
            //     print('LJM---onControllerInit');
            //     // First Paint (FP)
            //     controller.loadingState.onFirstPaint((event) {
            //       print('FP: ${event.elapsed.inMilliseconds}ms');
            //     });
            //   },
            //   httpLoggerOptions: HttpLoggerOptions(
            //     requestHeader: true,
            //     requestBody: true,
            //   ),
            //   networkOptions: WebFNetworkOptions(
            //     android: WebFNetworkOptions(
            //       httpClientAdapter: () async {
            //         String cacheDirectory =
            //             await HttpCacheController.getCacheDirectory(
            //               WebFBundle.fromUrl(demoEntryUrl).resolvedUri!,
            //             );
            //         CronetEngine cronetEngine = CronetEngine.build(
            //           cacheMode: CacheMode.memory,
            //           cacheMaxSize: 24 * 1024 * 1024,
            //           enableBrotli: true,
            //           enableHttp2: true,
            //           enableQuic: true,
            //           storagePath: null,
            //         );
            //         return CronetAdapter(cronetEngine);
            //       },
            //       enableHttpCache:
            //           false, // Cronet have it's own http cache impls
            //     ),
            //   ),
            //   onLCPContentVerification: (contentInfo, String routePath) {
            //     print('contentInfo: $contentInfo $routePath');
            //   },
            // ),
            setup: (controller) {
              print('LJM---controller: $controller');
              controller.hybridHistory.delegate = CustomHybridHistoryDelegate();
              // Register event listeners for all main   phases
              controller.loadingState.onConstructor((event) {
                print('🏗️ Constructor at ${event.elapsed.inMilliseconds}ms');
              });

              controller.loadingState.onInit((event) {
                print('🚀 Initialize at ${event.elapsed.inMilliseconds}ms');
              });

              controller.loadingState.onPreload((event) {
                print('📦 Preload at ${event.elapsed.inMilliseconds}ms');
              });

              controller.loadingState.onResolveEntrypointStart((event) {
                print(
                  '🔍 Resolve Entrypoint Start at ${event.elapsed.inMilliseconds}ms',
                );
              });

              controller.loadingState.onResolveEntrypointEnd((event) {
                print(
                  '✅ Resolve Entrypoint End at ${event.elapsed.inMilliseconds}ms',
                );
              });

              controller.loadingState.onParseHTMLStart((event) {
                print(
                  '📄 Parse HTML Start at ${event.elapsed.inMilliseconds}ms',
                );
              });

              controller.loadingState.onParseHTMLEnd((event) {
                print('✅ Parse HTML End at ${event.elapsed.inMilliseconds}ms');
              });

              controller.loadingState.onScriptQueue((event) {
                print('📋 Script Queue at ${event.elapsed.inMilliseconds}ms');
              });

              controller.loadingState.onScriptLoadStart((event) {
                print(
                  '📥 Script Load Start at ${event.elapsed.inMilliseconds}ms',
                );
              });

              controller.loadingState.onScriptLoadComplete((event) {
                print(
                  '✅ Script Load Complete at ${event.elapsed.inMilliseconds}ms ${event.parameters}',
                );
              });

              controller.loadingState.onAttachToFlutter((event) {
                print(
                  '🔗 Attach to Flutter at ${event.elapsed.inMilliseconds}ms',
                );
              });

              controller.loadingState.onScriptExecuteStart((event) {
                print(
                  '▶️ Script Execute Start at ${event.elapsed.inMilliseconds}ms',
                );
              });

              controller.loadingState.onScriptExecuteComplete((event) {
                print(
                  '✅ Script Execute Complete at ${event.elapsed.inMilliseconds}ms',
                );
              });

              controller.loadingState.onDOMContentLoaded((event) {
                print(
                  '📄 DOM Content Loaded at ${event.elapsed.inMilliseconds}ms',
                );
              });

              controller.loadingState.onWindowLoad((event) {
                print('🪟 Window Load at ${event.elapsed.inMilliseconds}ms');
              });

              controller.loadingState.onBuildRootView((event) {
                print(
                  '🏗️ Build Root View at ${event.elapsed.inMilliseconds}ms',
                );
              });

              controller.loadingState.onFirstPaint((event) {
                print(
                  '🎨 First Paint (FP) at ${event.elapsed.inMilliseconds}ms',
                );
              });

              controller.loadingState.onFirstContentfulPaint((event) {
                print(
                  '🖼️ First Contentful Paint (FCP) at ${event.elapsed.inMilliseconds}ms',
                );
              });

              controller.loadingState.onLargestContentfulPaint((event) {
                final isCandidate = event.parameters['isCandidate'] ?? false;
                final isFinal = event.parameters['isFinal'] ?? false;
                final status = isFinal
                    ? 'FINAL'
                    : (isCandidate ? 'CANDIDATE' : 'UNKNOWN');
                print(
                  '📊 Largest Contentful Paint (LCP) ($status) at ${event.parameters['timeSinceNavigationStart']}ms',
                );
              });
            },
          ),
          // WebFInspectorFloatingPanel(),
        ],
      ),
    );
  }

  static Widget buildSplashScreen() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Image.asset('assets/webf.png', width: 150, height: 150),
          SizedBox(height: 24),
          CupertinoActivityIndicator(radius: 14),
          SizedBox(height: 16),
          Text(
            'Loading...',
            style: TextStyle(fontSize: 16, color: CupertinoColors.systemGrey),
          ),
        ],
      ),
    );
  }

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


Expected results

android能正常显示css样式

Actual results

android不显示css样式

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions