Simply speaking BLoC is the best state management package out there. It's best not just because it's simple and easy to use.
But it also implements pure dart concept in your code.
When you learn BLoC you learn pure dart and flutter framework. But if your Riverpod you learn riverpod way of coding.
When you learn GetX you learn getx way of coding.
Both Riverpod and GetX introduce new programming concept. But they might not be useful if you go to other programming framework or language.
The difference between Riverpod and GetX is that, Riverpod's some concepts are hard to grasp and easy to make mistakes.
On the other GetX is easy to understand and simple but some programming concepts in GetX might not be useful if you move to a different programming paradigm.
Problems with Riverpod
There are quite a few problems with Riverpod when it comes to faciliate state management. The very first and most important problem is great number of new concepts. It introduces 8 providers, which is hard to keep track. It's difficult remembe which one to choose for usage.
Most beginners struggle here and leave Riverpod. Even after coding 10 year, I found those concepts are difficult and not easy to master their appropriate usage.
Riverpod providers are global singleton by default when they are created. It means they are accessible from anywhere in the world.
This global singletons introduces anti-pattern of clean architecture. Riverpod provides AsyncValue of Future data type, this also causes anti-pattern when it comes to error handling.
AsyncValue forces you to handle error directly within UI without using SnackBars in Flutter. The real problems happens when you use AsyncValue and non-AsyncValue together.
This could be nightmare. At least the document did not cover this how to use them together. And family modifer is a total new concept when it does network request.
You need to manually keep track of the providers that use the family modifer and dispose them when you need to.
Problems with GetX
GetX does a lot of thing like Riverpod. The big difference is that it's not as difficult as Riverpod to understand start coding.
It's easy to start writting app with GetX but this may cause bad practice for programmers. Like Riverpod, it's not a pure state management system.
It also does network request like Riverpod but in this case, it's more close to http package. Because it follows easy pattern to code, variables would be scattered in everywhere in your file, if you are not an organized developer.
One big problems with GetX, it may cause unncessary rebuild of your widgets which could be expensive.
What BLoC does
BLoC keeps things simple, just do state management. As it does state management, it perfectly introduces a lot of great Dart ideas like abstract classes, inheritance, writting pure dart classes, using models to capsulate your data structure in model based approach, callable property of Dart.
Looking up context and using them is like Provider state management.
All you need to do, create state classes and related events classes and then combine them together to create a BLoC class.
Triggers events for data transfer and emit states to save the data in the shared memory.