Home fragment refactoring.

master
Tomasz Półgrabia 2016-09-24 10:09:22 +02:00
parent 2fba983ec1
commit d707da1883
6 changed files with 222 additions and 203 deletions

View File

@ -19,7 +19,7 @@ public class PanoramioProviderCallback implements ProviderStatusCallback {
public void callback(String provider, boolean enabled) {
if (enabled) {
lg.trace("Handling provider enabling - refreshing panoramio listing");
homeFragment.fetchPanoramioPhotos();
homeFragment.refresh();
}
}
}

View File

@ -1,9 +1,7 @@
package pl.tpolgrabia.urbanexplorer.fragments;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
@ -13,24 +11,17 @@ import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.gson.Gson;
import com.google.gson.stream.JsonReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pl.tpolgrabia.urbanexplorer.AppConstants;
import pl.tpolgrabia.urbanexplorer.MainActivity;
import pl.tpolgrabia.urbanexplorer.R;
import pl.tpolgrabia.urbanexplorer.callbacks.*;
import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioCacheDto;
import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioImageInfo;
import pl.tpolgrabia.urbanexplorer.handlers.PanoramioItemLongClickHandler;
import pl.tpolgrabia.urbanexplorer.handlers.PanoramioLocationsScrollListener;
import pl.tpolgrabia.urbanexplorer.utils.LocationUtils;
import pl.tpolgrabia.urbanexplorer.utils.PanoramioUtils;
import pl.tpolgrabia.urbanexplorer.utils.*;
import java.io.*;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.concurrent.Semaphore;
@ -42,28 +33,14 @@ public class HomeFragment extends Fragment implements Refreshable {
private static final Logger lg = LoggerFactory.getLogger(HomeFragment.class);
public static final String TAG = HomeFragment.class.getSimpleName();
private static final String PHOTO_LIST = "PHOTO_LIST_KEY";
public static final String PHOTO_LIST = "PHOTO_LIST_KEY";
private boolean initialized = false;
private View inflatedView;
private Long pageId;
private Semaphore loading;
private ArrayList<PanoramioImageInfo> photos;
private boolean noMorePhotos;
private String currentGeocodedLocation;
public int getPanoramioBulkDataSize() {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
final String sValue = sharedPrefs.getString(AppConstants.PANORAMIO_BULK_SIZE_KEY,
String.valueOf(AppConstants.PANORAMIO_BULK_SIZE_DEF_VALUE));
try {
return Integer.parseInt(sValue);
} catch (NumberFormatException e) {
lg.warn("Invalid panoramio bulk data size {}", sValue, e);
return AppConstants.PANORAMIO_BULK_SIZE_DEF_VALUE;
}
}
public HomeFragment() {
// Required empty public constructor
}
@ -72,10 +49,8 @@ public class HomeFragment extends Fragment implements Refreshable {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lg.trace("onCreate {}", System.identityHashCode(this));
pageId = 1L;
loading = new Semaphore(1, true);
noMorePhotos = false;
updateLocationInfo();
}
@ -118,13 +93,8 @@ public class HomeFragment extends Fragment implements Refreshable {
Bundle savedInstanceState) {
// Inflate the layout for this fragment
lg.trace("TAG: {}", getTag());
for (Fragment frag : getFragmentManager().getFragments()) {
if (frag == null) {
lg.trace("Fragment is null");
} else {
lg.trace("Fragment TAG {}", frag.getTag());
}
}
DebugUtils.dumpFragments(getFragmentManager().getFragments());
inflatedView = inflater.inflate(R.layout.fragment_home, container, false);
ListView locations = (ListView)inflatedView.findViewById(R.id.locations);
final ListView finalLocations = locations;
@ -133,44 +103,8 @@ public class HomeFragment extends Fragment implements Refreshable {
initialized = true;
lg.trace("Saved instance state {}", savedInstanceState);
if (photos == null) {
if (savedInstanceState == null) {
lg.trace("Saved instance state is null");
photos = new ArrayList<>();
}
else {
final Serializable serializable = savedInstanceState.getSerializable(PHOTO_LIST);
lg.trace("Photo list serializable {}", serializable);
photos = (ArrayList<PanoramioImageInfo>) serializable;
if (photos == null) {
photos = new ArrayList<>();
}
}
}
if (photos.isEmpty()) {
// maybe we find something in our cache file
try (Reader br =
new InputStreamReader(
new FileInputStream(
new File(getActivity().getCacheDir(),
AppConstants.PANORAMIO_CACHE_FILENAME)))) {
PanoramioCacheDto dto = new Gson().fromJson(new JsonReader(br), PanoramioCacheDto.class);
if (dto != null) {
photos = new ArrayList<>(dto.getPanoramioImages());
lg.trace("Photos size from I/O cache is {}", photos.size());
} else {
lg.trace("Sorry, photos I/O cache is null");
}
} catch (FileNotFoundException e) {
lg.error("File not found", e);
} catch (IOException e) {
lg.error("I/O error", e);
} catch (Throwable t) {
lg.error("Throwable", t);
}
lg.trace("I've read photos from I/O cache");
if (photos != null) {
photos = CacheUtils.restorePhotosFromCache(this, savedInstanceState);
}
locations.setAdapter(new PanoramioAdapter(getActivity(), R.layout.location_item, photos));
@ -182,120 +116,55 @@ public class HomeFragment extends Fragment implements Refreshable {
}
public void fetchAdditionalPhotos() throws InterruptedException {
final FragmentActivity activity = getActivity();
if (activity == null) {
lg.trace("Activity shouldn't be null. No headless fragment");
return;
}
MainActivity mainActivity = (MainActivity)getActivity();
if (noMorePhotos) {
lg.trace("No more photos - last query was zero result");
mainActivity.hideProgress();
return;
}
if (!initialized) {
lg.trace("Fetching additional photos blocked till system is initialized");
mainActivity.hideProgress();
return;
}
if (getView() == null) {
lg.trace("Application still not initialized");
mainActivity.hideProgress();
return;
}
final Location location = LocationUtils.getLastKnownLocation(activity);
if (location == null) {
lg.info("Location still not available");
Toast.makeText(activity, "Location still not available", Toast.LENGTH_SHORT).show();
mainActivity.hideProgress();
return;
}
lg.trace("Fetching additional photos. Trying loading acquirng lock");
if (!loading.tryAcquire()) {
lg.info("Fetching additional photos. Loading in progress");
return;
}
int offset = photos.size();
lg.debug("Fetching additional photos offset: {}, count: {}", offset, getPanoramioBulkDataSize());
lg.debug("Fetching additional photos offset: {}, count: {}", offset, SettingsUtils.getPanoramioBulkDataSize(this));
PanoramioUtils.fetchPanoramioImages(
activity,
location.getLatitude(),
location.getLongitude(),
fetchRadiusX(),
fetchRadiusY(),
SettingsUtils.fetchRadiusX(getActivity()),
SettingsUtils.fetchRadiusY(getActivity()),
(long)(offset),
fetchLocationPageSize(),
new FetchAdditionalPanoramioPhotosCallback(this, activity)
);
}
public void fetchPanoramioPhotos() {
lg.trace("Fetch panoramio photos");
final FragmentActivity activity = getActivity();
if (activity == null) {
lg.warn("Activity shouldn't be null. It isn't headless fragment");
return;
}
MainActivity mainActivity = (MainActivity) getActivity();
final Location location = LocationUtils.getLastKnownLocation(activity);
if (location == null) {
lg.info("Location is still not available");
mainActivity.hideProgress();
Toast.makeText(getActivity(), "Location is still not available", Toast.LENGTH_SHORT).show();
return;
}
Double radiusX = fetchRadiusX();
Double radiusY = fetchRadiusY();
PanoramioUtils.fetchPanoramioImages(
activity,
location.getLatitude(),
location.getLongitude(),
radiusX,
radiusY,
(pageId - 1) * fetchLocationPageSize(),
fetchLocationPageSize(),
new FetchPanoramioPhotosCallback(this, activity)
);
}
private Long fetchLocationPageSize() {
return Long.valueOf(getPanoramioBulkDataSize());
}
private Double fetchRadiusX() {
final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
final String pref_panoramio_radiusx = sharedPreferences.getString(
"pref_panoramio_radiusx",
String.valueOf(AppConstants.PAMNORAMIO_DEF_RADIUSX));
lg.debug("Panoramio radiusx pref equals {}", pref_panoramio_radiusx);
return Double.parseDouble(
pref_panoramio_radiusx);
}
private Double fetchRadiusY() {
final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
final String pref_panoramio_radiusy = sharedPreferences.getString(
"pref_panoramio_radiusy",
String.valueOf(AppConstants.PAMNORAMIO_DEF_RADIUSY));
lg.debug("Panoramio radiusy pref equals {}", pref_panoramio_radiusy);
return Double.parseDouble(
pref_panoramio_radiusy);
return Long.valueOf(SettingsUtils.getPanoramioBulkDataSize(this));
}
@Override
@ -327,84 +196,51 @@ public class HomeFragment extends Fragment implements Refreshable {
final Location currLocation = LocationUtils.getLastKnownLocation(activity);
lg.trace("Current location: {}, locationInfo: {}", currLocation, locationInfo);
locationInfo.setText(currentGeocodedLocation);
}
@Override
public void onPause() {
super.onPause();
lg.trace("onPause");
}
@Override
public void onDestroy() {
super.onDestroy();
lg.trace("onDestroy");
File cacheDir = getActivity().getCacheDir();
BufferedWriter br = null;
try {
br = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(
new File(cacheDir, AppConstants.PANORAMIO_CACHE_FILENAME))));
PanoramioCacheDto dto = new PanoramioCacheDto();
dto.setPanoramioImages(photos);
Location location = LocationUtils.getLastKnownLocation(getActivity());
if (location != null) {
dto.setLongitude(location.getLongitude());
dto.setLatitude(location.getLatitude());
dto.setAltitude(location.getAltitude());
}
dto.setFetchedAt(new GregorianCalendar().getTime());
// FIXME this should be a fetch time, not persist time
new Gson().toJson(dto, br);
} catch (FileNotFoundException e) {
lg.error("File not found", e);
} catch (IOException e) {
lg.error("I/O Exception", e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
lg.error("I/O error during photos cache saving", e);
}
}
}
CacheUtils.savePostsToCache(getActivity(), photos);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
lg.trace("Saving state");
super.onSaveInstanceState(outState);
outState.putSerializable(PHOTO_LIST, photos);
lg.trace("Saved photos: {}", photos);
}
@Override
public void onStop() {
super.onStop();
lg.trace("onStop {}", System.identityHashCode(this));
}
@Override
public void onStart() {
super.onStart();
lg.trace("onStart {}", System.identityHashCode(this));
}
@Override
public void refresh() {
fetchPanoramioPhotos();
lg.trace("Fetch panoramio photos");
final FragmentActivity activity = getActivity();
if (activity == null) {
lg.warn("Activity shouldn't be null. It isn't headless fragment");
return;
}
MainActivity mainActivity = (MainActivity) getActivity();
final Location location = LocationUtils.getLastKnownLocation(activity);
if (location == null) {
lg.info("Location is still not available");
mainActivity.hideProgress();
Toast.makeText(getActivity(), "Location is still not available", Toast.LENGTH_SHORT).show();
return;
}
PanoramioUtils.fetchPanoramioImages(
activity,
location.getLatitude(),
location.getLongitude(),
SettingsUtils.fetchRadiusX(getActivity()),
SettingsUtils.fetchRadiusY(getActivity()),
0L,
fetchLocationPageSize(),
new FetchPanoramioPhotosCallback(this, activity)
);
}
public Semaphore getLoading() {

View File

@ -0,0 +1,104 @@
package pl.tpolgrabia.urbanexplorer.utils;
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import com.google.gson.Gson;
import com.google.gson.stream.JsonReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pl.tpolgrabia.urbanexplorer.AppConstants;
import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioCacheDto;
import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioImageInfo;
import pl.tpolgrabia.urbanexplorer.fragments.HomeFragment;
import java.io.*;
import java.util.ArrayList;
import java.util.GregorianCalendar;
/**
* Created by tpolgrabia on 24.09.16.
*/
public class CacheUtils {
private static final Logger lg = LoggerFactory.getLogger(CacheUtils.class);
public static ArrayList<PanoramioImageInfo> restorePhotosFromCache(HomeFragment homeFragment, Bundle savedBundleSettings) {
ArrayList<PanoramioImageInfo> photos;
final Serializable serPhotos = savedBundleSettings.getSerializable(HomeFragment.PHOTO_LIST);
lg.trace("Photo list serPhotos {}", serPhotos);
photos = (ArrayList<PanoramioImageInfo>) serPhotos;
if (photos != null && !photos.isEmpty()) {
// we are using from serializable bundle photos
return photos;
} else {
// maybe we find something in our cache file
try (Reader reader =
new InputStreamReader(
new FileInputStream(
new File(homeFragment.getActivity().getCacheDir(),
AppConstants.PANORAMIO_CACHE_FILENAME)))) {
PanoramioCacheDto dto = new Gson().fromJson(new JsonReader(reader), PanoramioCacheDto.class);
if (dto == null) {
lg.trace("Sorry, photos I/O cache is null");
return new ArrayList<>();
}
photos = new ArrayList<>(dto.getPanoramioImages());
lg.trace("Photos size from I/O cache is {}", photos.size());
lg.trace("I've read photos from I/O cache");
return photos;
} catch (FileNotFoundException e) {
lg.error("File not found", e);
return new ArrayList<>();
} catch (IOException e) {
lg.error("I/O error", e);
return new ArrayList<>();
} catch (Throwable t) {
lg.error("Throwable", t);
return new ArrayList<>();
}
}
}
public static void savePostsToCache(Context ctx, ArrayList<PanoramioImageInfo> photos) {
File cacheDir = ctx.getCacheDir();
BufferedWriter br = null;
try {
br = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(
new File(cacheDir, AppConstants.PANORAMIO_CACHE_FILENAME))));
PanoramioCacheDto dto = new PanoramioCacheDto();
dto.setPanoramioImages(photos);
Location location = LocationUtils.getLastKnownLocation(ctx);
if (location != null) {
dto.setLongitude(location.getLongitude());
dto.setLatitude(location.getLatitude());
dto.setAltitude(location.getAltitude());
}
dto.setFetchedAt(new GregorianCalendar().getTime());
// FIXME this should be a fetch time, not persist time
new Gson().toJson(dto, br);
} catch (FileNotFoundException e) {
lg.error("File not found", e);
} catch (IOException e) {
lg.error("I/O Exception", e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
lg.error("I/O error during photos cache saving", e);
}
}
}
}
}

View File

@ -0,0 +1,24 @@
package pl.tpolgrabia.urbanexplorer.utils;
import android.support.v4.app.Fragment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pl.tpolgrabia.urbanexplorer.fragments.HomeFragment;
import java.util.List;
/**
* Created by tpolgrabia on 24.09.16.
*/
public class DebugUtils {
private static final Logger lg = LoggerFactory.getLogger(DebugUtils.class);
public static void dumpFragments(List<Fragment> fragments) {
for (Fragment frag : fragments) {
if (frag == null) {
lg.trace("Fragment is null");
} else {
lg.trace("Fragment TAG {}", frag.getTag());
}
}
}
}

View File

@ -1,23 +1,30 @@
package pl.tpolgrabia.urbanexplorer.utils;
import android.content.Context;
import android.location.Location;
import com.androidquery.AQuery;
import com.androidquery.callback.AjaxCallback;
import com.androidquery.callback.AjaxStatus;
import com.google.gson.Gson;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pl.tpolgrabia.urbanexplorer.AppConstants;
import pl.tpolgrabia.urbanexplorer.callbacks.PanoramioResponseCallback;
import pl.tpolgrabia.urbanexplorer.callbacks.PanoramioResponseStatus;
import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioCacheDto;
import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioImageInfo;
import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioMapLocation;
import pl.tpolgrabia.urbanexplorer.dto.panoramio.PanoramioResponse;
import pl.tpolgrabia.urbanexplorer.exceptions.PanoramioResponseNotExpected;
import pl.tpolgrabia.urbanexplorer.fragments.HomeFragment;
import java.io.*;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
/**

View File

@ -0,0 +1,48 @@
package pl.tpolgrabia.urbanexplorer.utils;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pl.tpolgrabia.urbanexplorer.AppConstants;
import pl.tpolgrabia.urbanexplorer.fragments.HomeFragment;
/**
* Created by tpolgrabia on 24.09.16.
*/
public class SettingsUtils {
private static final Logger lg = LoggerFactory.getLogger(SettingsUtils.class);
public static Double fetchRadiusY(Context ctx) {
final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ctx);
final String pref_panoramio_radiusy = sharedPreferences.getString(
"pref_panoramio_radiusy",
String.valueOf(AppConstants.PAMNORAMIO_DEF_RADIUSY));
lg.debug("Panoramio radiusy pref equals {}", pref_panoramio_radiusy);
return Double.parseDouble(
pref_panoramio_radiusy);
}
public static Double fetchRadiusX(Context ctx) {
final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ctx);
final String pref_panoramio_radiusx = sharedPreferences.getString(
"pref_panoramio_radiusx",
String.valueOf(AppConstants.PAMNORAMIO_DEF_RADIUSX));
lg.debug("Panoramio radiusx pref equals {}", pref_panoramio_radiusx);
return Double.parseDouble(
pref_panoramio_radiusx);
}
public static int getPanoramioBulkDataSize(Context ctx) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(ctx.getActivity());
final String sValue = sharedPrefs.getString(AppConstants.PANORAMIO_BULK_SIZE_KEY,
String.valueOf(AppConstants.PANORAMIO_BULK_SIZE_DEF_VALUE));
try {
return Integer.parseInt(sValue);
} catch (NumberFormatException e) {
lg.warn("Invalid panoramio bulk data size {}", sValue, e);
return AppConstants.PANORAMIO_BULK_SIZE_DEF_VALUE;
}
}
}