Dependency injection, in a word, is to separate the creation of objects from its implementation.
It’s not something advanced. In fact, you are very likely to have already implemented some sort of dependency injection in your code.
For example, when implementing a server, you want to create a controller class that handles business logic. It uses a data manger class to manage the data. And the data manager in turn uses a MySQL client to manipulate the database. In a common design without dependency injection, the business logic controller will create an instance of the data manager in its constructor, and the data manager do the same in its constructor to create a MySQL client as well.