DEV Community

Cover image for Use A Package Like A Pro
Fiifi Pius
Fiifi Pius

Posted on

Use A Package Like A Pro

As a developer, you will make mistakes when learning something new. I used to make this particular mistake we are going to talk about, till I realized I couldn't live like that.

I see beginners, import packages and start using them everywhere in their project. This makes it difficult when there's a change of package. They will have to touch too many places to get things working. Or, when there's a breaking changes, they go through the same hell.

Now, let's look at using packages the right way

We are going to look a simple package but you can apply this same logic for all kinds of packages.

  • Create a class or function to handle the package however you want it. This class could be either widget class or a normal class.

Create A Class

This is my class for package_info_plus package which has a function of getting app version.

import 'package:package_info_plus/package_info_plus.dart';

class AppPackageInfo {
  static Future<String> getAppVersion() async {
    final packageInfo = await PackageInfo.fromPlatform();
    return '${packageInfo.version}';
  }
}
Enter fullscreen mode Exit fullscreen mode

You can use it in any widget you like and if in any case you would like to change the package, all you need to do is change it at one place.

class AppVersionScreen extends StatefulWidget {
  const AppVersionScreen({Key? key}) : super(key: key);

  @override
  State<AppVersionScreen> createState() => _AppVersionScreenState();
}

class _AppVersionScreenState extends State<AppVersionScreen> {
  String _appVersion = '';
  void _getAppVersion() async {
    String appVersion = await AppVersion.getAppVersion();
    if (mounted) setState(() => _appVersion = appVersion);
  }

  @override
  void initState() {
    _getAppVersion();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text('$_appVersion'),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Let's look at widget package

Say, you want to do a loading effect for your ListViews. You could use a package like shimmer to create a nice loading effect. You don't want to be using this package anywhere in your project.
If there's no support for shimmer package anymore, you have replace it with a similar package like skeleton.

This means you will have to touch places you have shimmer package and replace skeleton.

Instead, create a custom stateless widget and create your Shimmer effect there. Make it highly customizable so it could suit your use cases.

class ShimmerLoadingEffect extends StatelessWidget {
  const ShimmerLoadingEffect({
    Key? key,
    required this.child,
    this.itemCount = 4,
  }) : super(key: key);

  final Widget child;
  final int itemCount;

  @override
  Widget build(BuildContext context) {
    return Shimmer.fromColors(
      baseColor: Colors.grey.shade300,
      highlightColor: Colors.grey.shade100,
      child: ListView.builder(
        padding: EdgeInsets.zero,
        itemCount: itemCount,
        itemBuilder: (context, index){
          return child;
        },
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

This is a simple stateful widget consuming API

class ViewPeopleScreen extends StatefulWidget {
  const ViewPeopleScreen({Key? key}) : super(key: key);

  @override
  State<ViewPeopleScreen> createState() => _ViewPeopleScreenState();
}

class _ViewPeopleScreenState extends State<ViewPeopleScreen> {

List _people = [];

  void _getPeople() async{
    try{

        var response = await _peopleService.fetchPeople();
        if(!mounted) return;
        setState(() => _people = response['data'] );

    } on TimeoutException catch (t) {
      log(t.toString());
    } catch(e){
      log(e.toString());
    }
  }

  @override
  void initState() {
    _getPeople();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return  _people.length == 0 ?
      ShimmerLoadingEffect()
         :
       ListView.builder(
          itemCount: _people.length,
          itemBuilder: (context, index){
          final people = _people[index];
            return Text(people['name'].toString());
          },
       );
  }
}
Enter fullscreen mode Exit fullscreen mode

Take Away

Whenever there's a change to the shimmer package, it will affect one place and one file only. This also allows you to adhere to the DRY principle.

These are just simple examples and this technique applies to a complex use cases as well.

Writing application is hard, and as a beginner, if you don't take care, this little mistakes could frustrate you.

Top comments (0)