最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

dart - Flutter: require URL parameter in LaunchURL widget to make it reusable - Stack Overflow

programmeradmin4浏览0评论

I currently have a widget that I use to open a specific webpage using the LaunchUrl feature from the URL_Launcher package.

Throughout my app there are several instances where I'd like to open a webpage using this exact method, but I suppose it's not very efficient to copy-paste the widget I created for this over and over again, and simply replacing the URL.

This is the widget I have written, which is working. But this one is opening a specific URL.

Future<void> openHCReservationPortal(String url) async {
  final url = Uri.parse('');
  if (!await launchUrl(url, mode: LaunchMode.platformDefault)) {
    throw Exception('Kon $url niet openen');
  }
}

I'd like to have the url be a parameter, so I can reuse the widget.

I have tried to create a statefull widget with a required parameter but got all sorts of errors, so I must be missing something or doing something wrong.

This is what I wrote:

class OpenWebPageWidget extends StatefulWidget {
  final String url;
  const OpenWebPageWidget({super.key, required this.url});

  @override
  State<OpenWebPageWidget> createState() => _OpenWebPageWidgetState();
}

class _OpenWebPageWidgetState extends State<OpenWebPageWidget> {
  @override
  Widget build(BuildContext context) {
    Future<void> openWebPageWidget(String url) async {
      final url = Uri.parse(url);
      if (!await launchUrl(url, mode: LaunchMode.platformDefault)) {
        throw Exception('Kon $url niet openen');
      }
    }
  }
}

Flutter is complaining that:

  • The body might complete normally, causing 'null' to be returned, but the return type, 'Widget', is a potentially non-nullable type. Try adding either a return or a throw statement at the end.
  • The declaration 'openWebPageWidget' isn't referenced.

I currently have a widget that I use to open a specific webpage using the LaunchUrl feature from the URL_Launcher package.

Throughout my app there are several instances where I'd like to open a webpage using this exact method, but I suppose it's not very efficient to copy-paste the widget I created for this over and over again, and simply replacing the URL.

This is the widget I have written, which is working. But this one is opening a specific URL.

Future<void> openHCReservationPortal(String url) async {
  final url = Uri.parse('https://portal.mijnhandicart.nl/site/login');
  if (!await launchUrl(url, mode: LaunchMode.platformDefault)) {
    throw Exception('Kon $url niet openen');
  }
}

I'd like to have the url be a parameter, so I can reuse the widget.

I have tried to create a statefull widget with a required parameter but got all sorts of errors, so I must be missing something or doing something wrong.

This is what I wrote:

class OpenWebPageWidget extends StatefulWidget {
  final String url;
  const OpenWebPageWidget({super.key, required this.url});

  @override
  State<OpenWebPageWidget> createState() => _OpenWebPageWidgetState();
}

class _OpenWebPageWidgetState extends State<OpenWebPageWidget> {
  @override
  Widget build(BuildContext context) {
    Future<void> openWebPageWidget(String url) async {
      final url = Uri.parse(url);
      if (!await launchUrl(url, mode: LaunchMode.platformDefault)) {
        throw Exception('Kon $url niet openen');
      }
    }
  }
}

Flutter is complaining that:

  • The body might complete normally, causing 'null' to be returned, but the return type, 'Widget', is a potentially non-nullable type. Try adding either a return or a throw statement at the end.
  • The declaration 'openWebPageWidget' isn't referenced.
Share Improve this question asked Feb 15 at 15:39 El_StevoEl_Stevo 637 bronze badges 1
  • To launch a URL a reusable method may be a better option. You method only needs slight modification. Please check out my answer below. – rusty Commented Feb 16 at 2:26
Add a comment  | 

3 Answers 3

Reset to default 3

You can easily pass the URL as a string to the simple function as below:

Future<void> launchMyURL(String url) async {
  if (url.isEmpty) {
    throw 'Given URL is empty';
  }

  final Uri uri = Uri.parse(url);

  if (await canLaunchUrl(uri)) {
    await launchUrl(uri);
  } else {
    throw 'Could not launch $url';
  }
}

Then you can call the function to launch the URL from anywhere you like, e.g. from an elevated button:

ElevatedButton(
  onPressed: () async {
    try {
      await launchMyURL("https://www.google/");
    } catch (e) {
      print("#### Caught exception: ${e.toString()}");
    }
  },
  style: ElevatedButton.styleFrom(
    backgroundColor: Colors.blue,
    textStyle: const TextStyle(fontSize: 16.0),
  ),
  child: const Text(
    "Click to launch URL",
    style: TextStyle(
      color: Colors.white,
      fontWeight: FontWeight.normal,
      fontSize: 16.0,
    ),
  ),
),

Currently in your code, your build method has a Widget return type, but you are not returning any widget from the method, and only calling a function of Future<void> type, so the warning.

And, your method openHCReservationPortal can be slightly modified to achieve what you need. Here is the modified version:

Future<void> openHCReservationPortal(String url) async {
  final urlLaunch = Uri.parse('https://portal.mijnhandicart.nl/site/login');
  if (!await launchUrl(urlLaunch, mode: LaunchMode.platformDefault)) {
    throw Exception('Kon $url niet openen');
  }
}

You can modify your method with the above changes and also include the check with canLaunchUrl instead of directly calling launchUrl.

The errors you're encountering stem from two primary issues in your OpenWebPageWidget implementation:

Non-Exhaustive Return in build Method: In Dart, every code path in a function with a non-nullable return type must return a value. Your build method currently lacks a return statement.

try this :

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

class OpenWebPageWidget extends StatelessWidget {
  final String url;

  const OpenWebPageWidget({Key? key, required this.url}) : super(key: key);

  Future<void> _openWebPage() async {
    final uri = Uri.parse(url);
    if (!await launchUrl(uri, mode: LaunchMode.platformDefault)) {
      throw Exception('Could not open $url');
    }
  }

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: _openWebPage,
      child: const Text('Open Web Page'),
    );
  }
}

and use it like this:

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('URL Launcher Example'),
      ),
      body: Center(
        child: OpenWebPageWidget(url: 'https://example'),
      ),
    );
  }
}

The code you have Provided is not a Widget it is a Function of type Future<void>

Future<void> openHCReservationPortal(String url) async {
  final url = Uri.parse('https://portal.mijnhandicart.nl/site/login');
  if (!await launchUrl(url, mode: LaunchMode.platformDefault)) {
    throw Exception('Kon $url niet openen');
  }
}

The body might complete normally, causing 'null' to be returned, but the return type, 'Widget', is a potentially non-nullable type. Try adding either a return or a throw statement at the end.

This error is because the build method return type is a Widget but you did not return anything and it is need a return value of a Widget too , So try to return a Widget like a Scaffold or whatever you want to return then you can use your method when an event happened like click on a button or any change in the UI or you can call it on another method

Example

class OpenWebPageWidget extends StatelessWidget {
  const OpenWebPageWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: MaterialButton(
          onPressed: () {
            LaunchURL.openWebPageWidget(
                url: "https://portal.mijnhandicart.nl/site/login");
          },
          color: Colors.cyan,
        ),
      ),
    );
  }
}

Function: It's better to create it inside the class

class LaunchURL {
  static Future<void> openWebPageWidget({
    required String url,
  }) async {
    final Uri uri = Uri.parse(url);
    if (!await canLaunchUrl(uri)) {
      log("Error while luanch URL");
      return;
    }
    await launchUrl(uri, mode: LaunchMode.externalApplication);
  }
}
发布评论

评论列表(0)

  1. 暂无评论