diff --git a/res/layout/activity_about.xml b/res/layout/activity_about.xml
--- a/res/layout/activity_about.xml
+++ b/res/layout/activity_about.xml
@@ -35,12 +35,12 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content" android:id="@+id/versionTextView"
             android:textAppearance="@style/TextAppearance.AppCompat.Medium"
-            android:gravity="center_vertical"
+            android:gravity="center_horizontal|center_vertical"
             android:layout_margin="10dp"
             android:layout_marginLeft="20dp"
             android:layout_marginStart="20dp"
 
-    />
+            android:textColor="@color/black"/>
 
 
 </LinearLayout>
\ No newline at end of file
diff --git a/res/layout/fragment_arrivals.xml b/res/layout/fragment_arrivals.xml
--- a/res/layout/fragment_arrivals.xml
+++ b/res/layout/fragment_arrivals.xml
@@ -86,7 +86,7 @@
                             android:layout_height="wrap_content"
                             android:layout_marginStart="15dp"
                             android:layout_marginLeft="15dp"
-                            android:text="Source of arrivals"
+                            android:text=""
                             android:textAppearance="?android:attr/textAppearanceMedium"
                             android:textSize="19sp"
 
diff --git a/res/layout/stop_card.xml b/res/layout/stop_card.xml
--- a/res/layout/stop_card.xml
+++ b/res/layout/stop_card.xml
@@ -38,9 +38,10 @@
 					android:gravity="center_vertical"
 					android:textAppearance="@style/TextAppearance.AppCompat.Medium"
 					android:layout_below="@id/stop_nameText"
-					android:textIsSelectable="true" android:layout_marginTop="6dp"
-					android:layout_margin="8dp"
-					android:textColor="@color/orange_500" android:layout_marginLeft="10dp"/>
+					android:textIsSelectable="true" android:layout_marginTop="8dp"
+					android:textColor="@color/orange_500" android:layout_marginLeft="12dp"
+					android:layout_marginStart="12dp" android:layout_marginRight="8dp" android:layout_marginEnd="8dp"
+					android:layout_marginBottom="8dp"/>
 			<TextView
 					android:text="TextView"
 					android:layout_width="wrap_content"
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -62,6 +62,7 @@
 		- <b>Fabio Mazza</b> attuale rockstar developer anziano.<br>
 		- <b>Andrea Ugo</b> attuale rockstar developer in formazione.<br>
 		- <b>Silviu Chiriac</b> designer del logo 2021.<br>
+		- <b>Marco M</b> formidabile tester e cacciatore di bug.<br>
 		- <b>Ludovico Pavesi</b> ex rockstar developer anziano asd.<br>
 		- <b>Valerio Bozzolan</b> attuale manutentore.<br>
 		- <b>Marco Gagino</b> apprezzato ex collaboratore, ideatore icona e grafica.<br>
@@ -94,18 +95,22 @@
     <string name="no_stops_nearby">Nessuna fermata nei dintorni</string>
     <string name="main_menu_pref">Preferenze</string>
     <string name="database_update_message">Aggiornamento del database&#8230;</string>
-    <string name="pref_num_elements">Numero di fermate</string>
+    <string name="pref_num_elements">Numero minimo di fermate</string>
+    <string name="num_stops_nearby_not_number">Il numero di fermate da ricercare non è valido</string>
+    <string name="invalid_number">Valore errato, inserisci un numero</string>
     <string name="title_activity_settings">Impostazioni</string>
+    <string name="settings_search_radius">Distanza massima di ricerca (m)</string>
+    <string name="settings_experimental">Funzionalità sperimentali</string>
     <string name="action_settings">Impostazioni</string>
+    <string name="general_settings">Generali</string>
     <string name="pref_recents_group_title">Fermate recenti</string>
     <string name="settings_group_general">Impostazioni generali</string>
     <string name="settings_group_database">Gestione del database</string>
     <string name="settings_reset_database">Comincia aggiornamento manuale del database</string>
 
+
     <string name="enable_position_message_map">Consenti l\'accesso alla posizione per mostrarla sulla mappa</string>
     <string name="enableGpsText">Abilitare il GPS</string>
-    <string name="settings_search_radius">Raggio di ricerca</string>
-    <string name="settings_experimental">Funzionalità sperimentali</string>
     <string name="bus_arriving_at">arriva alle</string>
     <string name="arrivals_card_at_the_stop">alla fermata</string>
     <string name="show_arrivals">Mostra arrivi</string>
diff --git a/res/values/colors.xml b/res/values/colors.xml
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -15,5 +15,6 @@
     <color name="metro_red">#DE0908</color>
     <color name="blue_extraurbano">#2060DD</color>
     <color name="white">#FFFFFF</color>
+    <color name="black">#000000</color>
 
 </resources>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -72,6 +72,7 @@
 		- <b>Fabio Mazza</b> current senior rockstar developer.<br>
         - <b>Andrea Ugo</b> current junior rockstar developer.<br>
 		- <b>Silviu Chiriac</b> designer of the 2021 logo.<br>
+		- <b>Marco M</b> rockstar tester and bug hunter.<br>
 		- <b>Ludovico Pavesi</b> previous senior rockstar developer asd.<br>
 		- <b>Valerio Bozzolan</b> maintainer and infrastructure sponsor.<br>
 		- <b>Marco Gagino</b> contributor and icon creator.<br>
@@ -91,6 +92,7 @@
 		<p>Get involved! :)</p>
     ]]>
     </string>
+
     <string name="cant_add_to_favorites">Cannot add to favorites (storage full or corrupted database?)!</string>
     <string name="action_view_on_map">View on a map</string>
     <string name="cannot_show_on_map_no_activity">Cannot find any application to show it in</string>
@@ -99,19 +101,22 @@
     <string name="list_fragment_debug" translatable="false">ListFragment - BusTO</string>
     <string name="mainSharedPreferences" translatable="false">it.reyboz.bustorino.preferences</string>
     <string name="databaseUpdatingPref" translatable="false">db_is_updating</string>
-
+    <!-- Settings -->
     <string name="nearby_stops_message">Nearby stops</string>
     <string name="nearby_arrivals_message">Nearby connections</string>
     <string name="app_version">App version</string>
+    <string name="num_stops_nearby_not_number">The number of stops to show in the recents is invalid</string>
+    <string name="invalid_number">Invalid value, put a valid number</string>
 
     <string name="position_searching_message">Finding the position&#8230;</string>
     <string name="no_stops_nearby">No stops nearby</string>
-    <string name="pref_num_elements">Number of stops</string>
+    <string name="pref_num_elements">Minimum number of stops</string>
     <string name="main_menu_pref">Preferences</string>
     <string name="title_activity_settings">Settings</string>
     <string name="action_settings">Settings</string>
+    <string name="general_settings">General</string>
     <string name="settings_experimental">Experimental features</string>
-    <string name="settings_search_radius">Search radius</string>
+    <string name="settings_search_radius">Maximum distance (meters)</string>
     <string name="pref_recents_group_title">Recent stops</string>
     <string name="settings_group_general">General settings</string>
     <string name="settings_group_database">Database management</string>
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
--- a/res/xml/preferences.xml
+++ b/res/xml/preferences.xml
@@ -2,30 +2,44 @@
 <androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto">
     <androidx.preference.PreferenceCategory
-            android:title="General">
+            android:title="@string/general_settings">
         <androidx.preference.SwitchPreferenceCompat
                 android:defaultValue="false"
                 android:title="@string/settings_experimental" android:key="@string/pref_key_experimental"/>
     </androidx.preference.PreferenceCategory>
     <androidx.preference.PreferenceCategory
             android:title="@string/pref_recents_group_title">
+        <!--
     <androidx.preference.EditTextPreference
             android:defaultValue="10"
             android:selectAllOnFocus="true"
             android:singleLine="true"
-            android:title="@string/pref_num_elements" android:key="@string/pref_key_num_recents" android:inputType="numberDecimal"
-
-            android:digits="0123456789" android:ems="10"
+            android:inputType="number"
+            android:title="@string/pref_num_elements" android:key="@string/pref_key_num_recents"
+            app:useSimpleSummaryProvider="true"
+            android:digits="0123456789"
     />
+    -->
+        <androidx.preference.SeekBarPreference
+                android:title="@string/pref_num_elements" android:key="@string/pref_key_num_recents"
+                android:defaultValue="4"
+                android:max="40"
+                app:min="1"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                app:showSeekBarValue="true"
+
+        />
     <androidx.preference.SeekBarPreference
             android:title="@string/settings_search_radius"
             android:key="@string/pref_key_radius_recents"
             android:defaultValue="500"
             android:max="1000"
-            app:min="20"
+            app:min="100"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:gravity="center_vertical"
+            app:showSeekBarValue="true"
+
     />
 
     </androidx.preference.PreferenceCategory>
diff --git a/src/it/reyboz/bustorino/ActivityPrincipal.java b/src/it/reyboz/bustorino/ActivityPrincipal.java
--- a/src/it/reyboz/bustorino/ActivityPrincipal.java
+++ b/src/it/reyboz/bustorino/ActivityPrincipal.java
@@ -265,7 +265,7 @@
                         return true;
                     }
                     //selectDrawerItem(menuItem);
-                    Log.d(DEBUG_TAG, "pressed item "+menuItem.toString());
+                    Log.d(DEBUG_TAG, "pressed item "+menuItem);
 
                     return true;
 
@@ -354,6 +354,10 @@
             mDrawer.closeDrawer(GravityCompat.START);
         else if(shownFrag != null && shownFrag.isVisible() && shownFrag.getChildFragmentManager().getBackStackEntryCount() > 0){
             //if we have been asked to show a stop from another fragment, we should go back even in the main
+            if(shownFrag instanceof MainScreenFragment){
+                //we have to stop the arrivals reload
+                ((MainScreenFragment) shownFrag).cancelReloadArrivalsIfNeeded();
+            }
             shownFrag.getChildFragmentManager().popBackStackImmediate();
             if(showingMainFragmentFromOther && getSupportFragmentManager().getBackStackEntryCount() > 0){
                 getSupportFragmentManager().popBackStack();
@@ -406,7 +410,7 @@
     private MainScreenFragment showMainFragment(){
         FragmentManager fraMan = getSupportFragmentManager();
         Fragment fragment = fraMan.findFragmentByTag(MainScreenFragment.FRAGMENT_TAG);
-        MainScreenFragment mainScreenFragment = null;
+        final MainScreenFragment mainScreenFragment;
         if (fragment==null | !(fragment instanceof MainScreenFragment)){
             mainScreenFragment = createAndShowMainFragment();
         }
diff --git a/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java b/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java
--- a/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java
+++ b/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java
@@ -130,7 +130,8 @@
 
 
     public List<Route> parseDirectionsFromResponse(String response) throws IllegalArgumentException,JSONException{
-        if(response == null || response.length()==0) throw new IllegalArgumentException("Response string is null or void");
+        if(response == null || response.equals("null") || response.length()==0)
+            throw new IllegalArgumentException("Response string is null or void");
         ArrayList<Route> routes = new ArrayList<>(10);
             JSONArray lines =new JSONArray(response);
             for(int i=0; i<lines.length();i++){
diff --git a/src/it/reyboz/bustorino/backend/Palina.java b/src/it/reyboz/bustorino/backend/Palina.java
--- a/src/it/reyboz/bustorino/backend/Palina.java
+++ b/src/it/reyboz/bustorino/backend/Palina.java
@@ -351,4 +351,27 @@
 //            return this.passaggi;
 //        }
 //    }
+    //remove duplicates
+
+    public void mergeDuplicateRoutes(int startidx){
+       //ArrayList<Route> routesCopy = new ArrayList<>(routes);
+       //for
+        if(routes.size()<=1|| startidx >= routes.size()) //we have finished
+            return;
+        Route routeCheck = routes.get(startidx);
+        boolean found = false;
+        for(int i=startidx+1; i<routes.size(); i++){
+            final Route r = routes.get(i);
+            if(routeCheck.equals(r)){
+                //we have found a match, merge
+                routes.remove(routeCheck);
+                r.mergeRouteWithAnother(routeCheck);
+                found=true;
+                break;
+            }
+        }
+        if (found) mergeDuplicateRoutes(startidx);
+        else mergeDuplicateRoutes(startidx+1);
+    }
+    //private void mergeRoute
 }
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/backend/Route.java b/src/it/reyboz/bustorino/backend/Route.java
--- a/src/it/reyboz/bustorino/backend/Route.java
+++ b/src/it/reyboz/bustorino/backend/Route.java
@@ -281,10 +281,7 @@
         if(this.stopsList!=null && other.stopsList!=null){
             int d = this.stopsList.size()-other.stopsList.size();
             if(d!=0) return d;
-            else {
-                //the two have the same number of stops
-
-            }
+            //if we are here, the two routes have the same number of stops
         }
         // probably useless, but... last attempt.
 
@@ -306,11 +303,22 @@
              Route r = (Route) obj;
              boolean result  = false;
              if(this.name.equals(r.name) && this.branchid == r.branchid){
+                 if(description!=null && r.description!=null)
+                     if(!description.trim().equals(r.description.trim()))
+                         return false;
+                 if(destinazione!=null && r.destinazione!=null){
+                         if(!this.destinazione.trim().equals(r.destinazione.trim()))
+                             // they are not the same
+                             return false;
+                 }
+                 //check stops list
                  if(this.stopsList!=null && r.stopsList!=null){
-                     int d = this.stopsList.size()-r.stopsList.size();
-                     if(d!=0) {
-                         result = false;
+                     int sizeDiff = this.stopsList.size()-r.stopsList.size();
+                     if(sizeDiff!=0) {
+                         return false;
+
                      } else {
+                         //check that the stops are the same
                          result = true;
                          for(int j=0; j<this.stopsList.size();j++){
                              if(!this.stopsList.get(j).equals(r.stopsList.get(j))) {
@@ -318,7 +326,11 @@
                                 break;
                              }
                         }
+                         return result;
                      }
+                 } else{
+                     //no stopsList in one or the other
+                     return true;
                  }
              }
              return result;
@@ -342,7 +354,7 @@
         if (other.getStopsList() != null && this.getStopsList() == null)
             this.setStopsList(other.getStopsList());
 
-        if(this.passaggi!=null && other.passaggi!=null && this.passaggi.size()==0 && other.passaggi.size()>0){
+        if(this.passaggi!=null && other.passaggi!=null && other.passaggi.size()>0){
             this.passaggi.addAll(other.passaggi);
         }
 
diff --git a/src/it/reyboz/bustorino/data/StopsDB.java b/src/it/reyboz/bustorino/data/StopsDB.java
deleted file mode 100644
--- a/src/it/reyboz/bustorino/data/StopsDB.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
-	BusTO ("backend" components)
-    Copyright (C) 2016 Ludovico Pavesi
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package it.reyboz.bustorino.data;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteException;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.readystatesoftware.sqliteasset.SQLiteAssetHelper;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import it.reyboz.bustorino.backend.Route;
-import it.reyboz.bustorino.backend.Stop;
-import it.reyboz.bustorino.backend.StopsDBInterface;
-
-
-public class StopsDB extends SQLiteAssetHelper implements StopsDBInterface {
-    private static String QUERY_TABLE_stops = "stops";
-    private static String QUERY_WHERE_ID = "ID = ?";
-    private static String QUERY_WHERE_LAT_AND_LNG_IN_RANGE = "lat >= ? AND lat <= ? AND lon >= ? AND lon <= ?";
-    private static String[] QUERY_COLUMN_name = {"name"};
-    private static final String[] QUERY_COLUMN_location = {"location"};
-    private static final String[] QUERY_COLUMN_route = {"route"};
-    private static final String[] QUERY_COLUMN_everything = {"name", "location", "type", "lat", "lon"};
-    private static final String[] QUERY_COLUMN_everything_and_ID = {"ID", "name", "location", "type", "lat", "lon"};
-
-    private static String DB_NAME = "stops.sqlite";
-    private static int DB_VERSION = 1;
-    private SQLiteDatabase db;
-    private AtomicInteger openCounter = new AtomicInteger();
-
-    public StopsDB(Context context) {
-        super(context, DB_NAME, null, DB_VERSION);
-        // WARNING: do not remove the following line, do not save anything in this database, it will be overwritten on every update!
-        setForcedUpgrade();
-
-        // remove old database (BusTo version 1.8.5 and below)
-        File filename = new File(context.getFilesDir(), "busto.sqlite");
-        if(filename.exists()) {
-            //noinspection ResultOfMethodCallIgnored
-            filename.delete();
-        }
-    }
-
-    /**
-     * Through the magic of an atomic counter, the database gets opened and closed without race
-     * conditions between threads (HOPEFULLY).
-     *
-     * @return database or null if cannot be opened
-     */
-    @Nullable
-    public synchronized SQLiteDatabase openIfNeeded() {
-        openCounter.incrementAndGet();
-        this.db = getReadableDatabase();
-        return this.db;
-    }
-
-    /**
-     * Through the magic of an atomic counter, the database gets really closed only when no thread
-     * is using it anymore (HOPEFULLY).
-     */
-    public synchronized void closeIfNeeded() {
-        // is anybody still using the database or can we close it?
-        if(openCounter.decrementAndGet() <= 0) {
-            super.close();
-            this.db = null;
-        }
-    }
-
-    public List<String> getRoutesByStop(@NonNull String stopID) {
-        String[] uselessArray = {stopID};
-        int count;
-        Cursor result;
-
-        if(this.db == null) {
-            return null;
-        }
-
-        try {
-            result = this.db.query("routemap", QUERY_COLUMN_route, "stop = ?", uselessArray, null, null, null);
-        } catch(SQLiteException e) {
-            return null;
-        }
-
-        count = result.getCount();
-        if(count == 0) {
-            return null;
-        }
-
-        List<String> routes = new ArrayList<>(count);
-
-        while(result.moveToNext()) {
-            routes.add(result.getString(0));
-        }
-
-        result.close();
-
-        return routes;
-    }
-
-    public String getLocationFromID(@NonNull String stopID) {
-        String[] uselessArray = {stopID};
-        int count;
-        String name;
-        Cursor result;
-
-        if(this.db == null) {
-            return null;
-        }
-
-        try {
-            result = this.db.query(QUERY_TABLE_stops, QUERY_COLUMN_location, QUERY_WHERE_ID, uselessArray, null, null, null);
-        } catch(SQLiteException e) {
-            return null;
-        }
-
-        count = result.getCount();
-        if(count == 0) {
-            return null;
-        }
-
-        result.moveToNext();
-        name = result.getString(0);
-
-        result.close();
-
-        return name;
-    }
-
-    public Stop getAllFromID(@NonNull String stopID) {
-        Cursor result;
-        int count;
-        Stop s;
-
-        if(this.db == null) {
-            return null;
-        }
-
-        try {
-            result = this.db.query(QUERY_TABLE_stops, QUERY_COLUMN_everything, QUERY_WHERE_ID, new String[] {stopID}, null, null, null);
-            int colName = result.getColumnIndex("name");
-            int colLocation = result.getColumnIndex("location");
-            int colType = result.getColumnIndex("type");
-            int colLat = result.getColumnIndex("lat");
-            int colLon = result.getColumnIndex("lon");
-
-            count = result.getCount();
-            if(count == 0) {
-                return null;
-            }
-
-            result.moveToNext();
-
-            Route.Type type = routeTypeFromSymbol(result.getString(colType));
-
-            String locationWhichSometimesIsAnEmptyString = result.getString(colLocation);
-            if(locationWhichSometimesIsAnEmptyString.length() <= 0) {
-                locationWhichSometimesIsAnEmptyString = null;
-            }
-
-            s = new Stop(stopID, result.getString(colName), null, locationWhichSometimesIsAnEmptyString, type, getRoutesByStop(stopID), result.getDouble(colLat), result.getDouble(colLon));
-        } catch(SQLiteException e) {
-            return null;
-        }
-
-        result.close();
-
-        return s;
-    }
-
-    /**
-     * Query some bus stops inside a map view
-     *
-     * You can obtain the coordinates from OSMDroid using something like this:
-     *  BoundingBoxE6 bb = mMapView.getBoundingBox();
-     *  double latFrom = bb.getLatSouthE6() / 1E6;
-     *  double latTo = bb.getLatNorthE6() / 1E6;
-     *  double lngFrom = bb.getLonWestE6() / 1E6;
-     *  double lngTo = bb.getLonEastE6() / 1E6;
-     */
-    public Stop[] queryAllInsideMapView(double minLat, double maxLat, double minLng, double maxLng) {
-        Stop[] stops = new Stop[0];
-
-        Cursor result;
-        int count;
-
-        // coordinates must be strings in the where condition
-        String minLatRaw = String.valueOf(minLat);
-        String maxLatRaw = String.valueOf(maxLat);
-        String minLngRaw = String.valueOf(minLng);
-        String maxLngRaw = String.valueOf(maxLng);
-
-        String stopID;
-        Route.Type type;
-
-        if(this.db == null) {
-            return stops;
-        }
-
-        try {
-            result = this.db.query(QUERY_TABLE_stops, QUERY_COLUMN_everything_and_ID, QUERY_WHERE_LAT_AND_LNG_IN_RANGE, new String[] {minLatRaw, maxLatRaw, minLngRaw, maxLngRaw}, null, null, null);
-
-            int colID = result.getColumnIndex("ID");
-            int colName = result.getColumnIndex("name");
-            int colLocation = result.getColumnIndex("location");
-            int colType = result.getColumnIndex("type");
-            int colLat = result.getColumnIndex("lat");
-            int colLon = result.getColumnIndex("lon");
-
-            count = result.getCount();
-            stops = new Stop[count];
-
-            int i = 0;
-            while(result.moveToNext()) {
-
-                stopID = result.getString(colID);
-                type = routeTypeFromSymbol(result.getString(colType));
-
-                String locationWhichSometimesIsAnEmptyString = result.getString(colLocation);
-                if (locationWhichSometimesIsAnEmptyString.length() <= 0) {
-                    locationWhichSometimesIsAnEmptyString = null;
-                }
-
-                stops[i++] = new Stop(stopID, result.getString(colName), null,
-                        locationWhichSometimesIsAnEmptyString, type, getRoutesByStop(stopID),
-                        result.getDouble(colLat), result.getDouble(colLon));
-            }
-
-        } catch(SQLiteException e) {
-            // TODO: put a warning in the log
-            return stops;
-        }
-
-        result.close();
-
-        return stops;
-    }
-
-    /**
-     * Get a Route Type from its char symbol
-     *
-     * @param route The route symbol (e.g. "B")
-     * @return The related Route.Type (e.g. Route.Type.Bus)
-     */
-    public static Route.Type routeTypeFromSymbol(String route) {
-        switch (route) {
-            case "M":
-                return Route.Type.METRO;
-            case "T":
-                return Route.Type.RAILWAY;
-        }
-
-        // default with case "B"
-        return Route.Type.BUS;
-    }
-}
diff --git a/src/it/reyboz/bustorino/fragments/MainScreenFragment.java b/src/it/reyboz/bustorino/fragments/MainScreenFragment.java
--- a/src/it/reyboz/bustorino/fragments/MainScreenFragment.java
+++ b/src/it/reyboz/bustorino/fragments/MainScreenFragment.java
@@ -96,6 +96,7 @@
     Handler mainHandler;
     private final Runnable refreshStop = new Runnable() {
         public void run() {
+            if(getContext() == null) return;
             if (fragMan.findFragmentById(R.id.resultFrame) instanceof ArrivalsFragment) {
                 ArrivalsFragment fragment = (ArrivalsFragment) fragMan.findFragmentById(R.id.resultFrame);
                 if (fragment == null){
@@ -131,8 +132,8 @@
             if(status == AppLocationManager.LOCATION_GPS_AVAILABLE && !isNearbyFragmentShown()){
                 //request Stops
                 pendingNearbyStopsRequest = false;
-
-                mainHandler.post(new NearbyStopsRequester(getContext(), cr));
+                if (getContext()!= null)
+                    mainHandler.post(new NearbyStopsRequester(getContext(), cr));
             }
         }
 
@@ -149,7 +150,7 @@
         @Override
         public void onLocationProviderAvailable() {
             //Log.w(DEBUG_TAG, "pendingNearbyStopRequest: "+pendingNearbyStopsRequest);
-            if(!isNearbyFragmentShown()){
+            if(!isNearbyFragmentShown() && getContext()!=null){
                 pendingNearbyStopsRequest = false;
                 mainHandler.post(new NearbyStopsRequester(getContext(), cr));
             }
@@ -317,6 +318,18 @@
          */
     }
 
+    /**
+     * Cancel the reload of the arrival times
+     * because we are going to pop the fragment
+     */
+    public void cancelReloadArrivalsIfNeeded(){
+        if(getContext()==null) return; //we are not attached
+
+        //Fragment fr = getChildFragmentManager().findFragmentById(R.id.resultFrame);
+        fragmentHelper.stopLastRequestIfNeeded();
+        toggleSpinner(false);
+    }
+
 
     @Override
     public void onAttach(@NonNull Context context) {
@@ -326,7 +339,7 @@
         if (context instanceof CommonFragmentListener) {
             mListener = (CommonFragmentListener) context;
         } else {
-            throw new RuntimeException(context.toString()
+            throw new RuntimeException(context
                     + " must implement CommonFragmentListener");
         }
         if (setupOnAttached) {
@@ -407,6 +420,7 @@
         fragmentHelper.stopLastRequestIfNeeded();
     }
 
+
     /*
     GUI METHODS
      */
@@ -437,11 +451,11 @@
         } else { // searchMode == SEARCH_BY_NAME
             String query = busStopSearchByNameEditText.getText().toString();
             //new asyncWgetBusStopSuggestions(query, stopsDB, StopsFindersByNameRecursionHelper);
-            new AsyncDataDownload(fragmentHelper, stopsFinderByNames, getContext()).execute(query);
+            if(getContext()!=null)
+                new AsyncDataDownload(fragmentHelper, stopsFinderByNames, getContext()).execute(query);
         }
     }
 
-
     public void onToggleKeyboardLayout(View v) {
 
         if (searchMode == SEARCH_BY_NAME) {
diff --git a/src/it/reyboz/bustorino/fragments/NearbyStopsFragment.java b/src/it/reyboz/bustorino/fragments/NearbyStopsFragment.java
--- a/src/it/reyboz/bustorino/fragments/NearbyStopsFragment.java
+++ b/src/it/reyboz/bustorino/fragments/NearbyStopsFragment.java
@@ -44,6 +44,7 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 import com.android.volley.*;
+import it.reyboz.bustorino.BuildConfig;
 import it.reyboz.bustorino.R;
 import it.reyboz.bustorino.adapters.ArrivalsStopAdapter;
 import it.reyboz.bustorino.backend.*;
@@ -225,7 +226,7 @@
         if (context instanceof FragmentListenerMain) {
             mListener = (FragmentListenerMain) context;
         } else {
-            throw new RuntimeException(context.toString()
+            throw new RuntimeException(context
                     + " must implement OnFragmentInteractionListener");
         }
         Log.d(DEBUG_TAG, "OnAttach called");
@@ -267,12 +268,31 @@
 
         mListener.enableRefreshLayout(false);
         Log.d(DEBUG_TAG,"OnResume called");
-
+        if(getContext()==null){
+            Log.e(DEBUG_TAG, "NULL CONTEXT, everything is going to crash now");
+            MIN_NUM_STOPS = 5;
+            MAX_DISTANCE = 600;
+            return;
+        }
         //Re-read preferences
         SharedPreferences shpr = PreferenceManager.getDefaultSharedPreferences(getContext().getApplicationContext());
         //For some reason, they are all saved as strings
         MAX_DISTANCE = shpr.getInt(getString(R.string.pref_key_radius_recents),600);
-        MIN_NUM_STOPS = Integer.parseInt(shpr.getString(getString(R.string.pref_key_num_recents),"10"));
+        boolean isMinStopInt = true;
+        try{
+            MIN_NUM_STOPS = shpr.getInt(getString(R.string.pref_key_num_recents), 5);
+        } catch (ClassCastException ex){
+            isMinStopInt = false;
+        }
+        if(!isMinStopInt)
+            try {
+                MIN_NUM_STOPS = Integer.parseInt(shpr.getString(getString(R.string.pref_key_num_recents), "5"));
+            } catch (NumberFormatException ex){
+                MIN_NUM_STOPS = 5;
+            }
+        if(BuildConfig.DEBUG)
+            Log.d(DEBUG_TAG, "Max distance for stops: "+MAX_DISTANCE+
+                    ", Min number of stops: "+MIN_NUM_STOPS);
     }
 
 
@@ -311,21 +331,30 @@
     public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) {
         if (0 > MAX_DISTANCE) throw new AssertionError();
         //Cursor might be null
+        Log.d(DEBUG_TAG, "Num stops found: "+data.getCount()+", Current distance: "+distance);
         if(data==null){
             Log.e(DEBUG_TAG,"Null cursor, something really wrong happened");
             return;
         }
-        if(!isDBUpdating() && (data.getCount()<MIN_NUM_STOPS || distance<=MAX_DISTANCE)){
+        if(!isDBUpdating() && (data.getCount()<MIN_NUM_STOPS && distance<=MAX_DISTANCE)){
             distance = distance*2;
             Bundle d = new Bundle();
             d.putParcelable(BUNDLE_LOCATION,lastReceivedLocation);
             getLoaderManager().restartLoader(LOADER_ID,d,this);
+            //Log.d(DEBUG_TAG, "Doubling distance now!");
             return;
         }
         Log.d("LoadFromCursor","Number of nearby stops: "+data.getCount());
         ////////
-        ArrayList<Stop> stopList = createStopListFromCursor(data);
+
         if(data.getCount()>0) {
+            ArrayList<Stop> stopList = createStopListFromCursor(data);
+            double minDistance = Double.POSITIVE_INFINITY;
+            for(Stop s: stopList){
+                minDistance = Math.min(minDistance, s.getDistanceFromLocation(lastReceivedLocation));
+            }
+
+
             //quick trial to hopefully always get the stops in the correct order
             Collections.sort(stopList,new StopSorterByDistance(lastReceivedLocation));
             switch (fragment_type){
@@ -350,7 +379,7 @@
     }
 
     @Override
-    public void onLoaderReset(Loader<Cursor> loader) {
+    public void onLoaderReset(@NonNull Loader<Cursor> loader) {
     }
 
     /**
@@ -427,6 +456,10 @@
                 routesPairList.add(new Pair<>(p,r));
             }
         }
+        if (getContext()==null){
+            Log.e(DEBUG_TAG, "Trying to show arrivals in Recycler but we're not attached");
+            return;
+        }
         if(firstLocForArrivals){
             arrivalsStopAdapter = new ArrivalsStopAdapter(routesPairList,mListener,getContext(),lastReceivedLocation);
             gridRecyclerView.setAdapter(arrivalsStopAdapter);
@@ -465,13 +498,13 @@
         final static String REQUEST_TAG = "NearbyArrivals";
         private final QueryType[] types = {QueryType.ARRIVALS,QueryType.DETAILS};
         final NetworkVolleyManager volleyManager;
-        private final int MAX_ARRIVAL_STOPS =35;
         int activeRequestCount = 0,reqErrorCount = 0, reqSuccessCount=0;
 
         ArrivalsManager(List<Stop> stops){
             mStops = new HashMap<>();
             volleyManager = NetworkVolleyManager.getInstance(getContext());
 
+            int MAX_ARRIVAL_STOPS = 35;
             for(Stop s: stops.subList(0,Math.min(stops.size(), MAX_ARRIVAL_STOPS))){
                 mStops.put(s.ID,new Palina(s));
                 for(QueryType t: types) {
@@ -594,6 +627,7 @@
             switch(status){
                 case AppLocationManager.LOCATION_GPS_AVAILABLE:
                     messageTextView.setVisibility(View.GONE);
+
                     break;
                 case AppLocationManager.LOCATION_UNAVAILABLE:
                     messageTextView.setText(R.string.enableGpsText);
diff --git a/src/it/reyboz/bustorino/fragments/SettingsFragment.java b/src/it/reyboz/bustorino/fragments/SettingsFragment.java
--- a/src/it/reyboz/bustorino/fragments/SettingsFragment.java
+++ b/src/it/reyboz/bustorino/fragments/SettingsFragment.java
@@ -3,34 +3,125 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.os.Bundle;
+import android.os.Handler;
 import android.util.Log;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceFragmentCompat;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.preference.*;
 import it.reyboz.bustorino.R;
 
+import java.lang.ref.WeakReference;
+
 public class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener {
     private static final String TAG = SettingsFragment.class.getName();
 
-    SharedPreferences preferences;
+    private static final String DIALOG_FRAGMENT_TAG =
+            "androidx.preference.PreferenceFragment.DIALOG";
+    //private static final
+    Handler mHandler;
+
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+        mHandler = new Handler();
+        return super.onCreateView(inflater, container, savedInstanceState);
+
+    }
 
     @Override
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+        //getPreferenceManager().setSharedPreferencesName(getString(R.string.mainSharedPreferences));
+        convertStringPrefToIntIfNeeded(getString(R.string.pref_key_num_recents), getContext());
+
+        getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
         setPreferencesFromResource(R.xml.preferences,rootKey);
-        Context con = getContext();
-        if (con == null){
-            Log.w("SETTINGS FRAGMENT", "context is null");
-            preferences = null;
-        }
-        else
-            preferences = getContext().getSharedPreferences(getString(R.string.mainSharedPreferences), Context.MODE_PRIVATE);
+        /*EditTextPreference editPref = findPreference(getString(R.string.pref_key_num_recents));
+        editPref.setOnBindEditTextListener(editText -> {
+            editText.setInputType(InputType.TYPE_CLASS_NUMBER);
+            editText.setSelection(0,editText.getText().length());
+        });
+         */
+
+
     }
 
     @Override
     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
         Preference pref = findPreference(key);
-        //non so a cosa serva tutto  questo
+        Log.d(TAG,"Preference key "+key+" changed");
+        //sometimes this happens
+        if(getContext()==null) return;
+        /*
+        THIS CODE STAYS COMMENTED FOR FUTURE REFERENCES
+        if (key.equals(getString(R.string.pref_key_num_recents))){
+            //check that is it an int
+
+            String value = sharedPreferences.getString(key,"");
+            boolean valid = value.length() != 0;
+            try{
+                Integer intValue = Integer.parseInt(value);
+            } catch (NumberFormatException ex){
+                valid = false;
+            }
+            if (!valid){
+                Toast.makeText(getContext(), R.string.invalid_number, Toast.LENGTH_SHORT).show();
+                if(pref instanceof EditTextPreference){
+                    EditTextPreference prefEdit = (EditTextPreference) pref;
+                    //Intent intent = prefEdit.getIntent();
+                    Log.d(TAG, "opening preference, dialog showing "+
+                            (getParentFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG)!=null) );
+                    //getPreferenceManager().showDialog(pref);
+                    //onDisplayPreferenceDialog(prefEdit);
+                    mHandler.postDelayed(new DelayedDisplay(prefEdit), 500);
+                }
+
+            }
+        }
+         */
 
         Log.d("BusTO Settings", "changed "+key+"\n "+sharedPreferences.getAll());
 
     }
+
+    private void convertStringPrefToIntIfNeeded(String preferenceKey, Context con){
+        if (con == null) return;
+        SharedPreferences defaultSharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
+        try{
+
+            Integer val = defaultSharedPref.getInt(preferenceKey, 0);
+        } catch (NumberFormatException | ClassCastException ex){
+            //convert the preference
+            //final String preferenceNumRecents = getString(R.string.pref_key_num_recents);
+            Log.d("Preference - BusTO", "Converting to integer the string preference "+preferenceKey);
+            String currentValue = defaultSharedPref.getString(preferenceKey, "10");
+            int newValue;
+            try{
+                newValue = Integer.parseInt(currentValue);
+            } catch (NumberFormatException e){
+                newValue = 10;
+            }
+            final SharedPreferences.Editor editor  = defaultSharedPref.edit();
+            editor.remove(preferenceKey);
+            editor.putInt(preferenceKey, newValue);
+            editor.apply();
+        }
+    }
+
+    class DelayedDisplay implements Runnable{
+        private final WeakReference<DialogPreference> preferenceWeakReference;
+
+        public DelayedDisplay(DialogPreference preference) {
+            this.preferenceWeakReference = new WeakReference<>(preference);
+        }
+
+        @Override
+        public void run() {
+            if(preferenceWeakReference.get()==null)
+                return;
+
+            getPreferenceManager().showDialog(preferenceWeakReference.get());
+        }
+    }
 }
diff --git a/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java b/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java
--- a/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java
+++ b/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java
@@ -116,8 +116,12 @@
                         return null;
                     }
                     //Skip the FiveTAPIFetcher for the Metro Stops because it shows incomprehensible arrival times
-                    if(f instanceof FiveTAPIFetcher && Integer.parseInt(stopID)>= 8200)
-                        continue;
+                    try {
+                        if (f instanceof FiveTAPIFetcher && Integer.parseInt(stopID) >= 8200)
+                            continue;
+                    } catch (NumberFormatException ex){
+                        Log.e(DEBUG_TAG, "The stop number is not a valid integer, expect failures");
+                    }
                     p= f.ReadArrivalTimesAll(stopID,res);
                     publishProgress(res.get());
                     //if (res.get()!= Fetcher.Result.OK)
@@ -149,7 +153,10 @@
                             }
                         }
                     }
-
+                    p.mergeDuplicateRoutes(0);
+                    if(p.queryAllRoutes().size() == 0)
+                        //skip the rest and go to the next fetcher
+                        continue;
                     result = p;
                     //TODO: find a way to avoid overloading the user with toasts
                     break;