Edit: Just saw that my answer was based on your code but didn't actually answeredanswer your question XD. I kept the old answer in case you can use that information.
I added some comments and the Viewport class I'm using in the example and added
You could simply have the current map in memory and load the surrounding maps. Imagine a world that consists of a 2d array of single levels of the size 5x5. The player starts in field 1. As the top and the left bounds of the level are on the edge of the world, they do not need to be loudedloaded. So in that case level 1/1 is active and level 1/2 and 2/1 are loaded... If the player now moves to the right, all levels (besides the one your moving to) are unloaded and the new surroundings are loaded. Means level 2/1 is now active, 1/1, 2/2 and 3/1 are now loaded.
I hope this gives you an idea, how it could be done. But this approach won't work very good, when every level has to be simulated during the game. But if you can freeze unused levels this should work fine.
Old Answer: What
What I do when rendering the level (also tile based) is to calculate, which items from the tile array intersect with the viewport and then I only render those tiles. Like that you can have big maps but only need to render the portion on screen.