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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions