mirror of
https://github.com/MatomoCamp/matomocamp-companion-android.git
synced 2024-09-19 16:13:46 +02:00
Migrate all non-Cursor Loaders code to LiveData & ViewModel
This commit is contained in:
parent
9b39c73615
commit
d7ddcc4ad7
12 changed files with 439 additions and 500 deletions
|
@ -33,5 +33,6 @@ dependencies {
|
|||
implementation "com.android.support:recyclerview-v7:$supportLibraryVersion"
|
||||
implementation "com.android.support:cardview-v7:$supportLibraryVersion"
|
||||
implementation "com.android.support:customtabs:$supportLibraryVersion"
|
||||
implementation 'android.arch.lifecycle:extensions:1.1.0'
|
||||
implementation 'com.github.chrisbanes:PhotoView:2.1.3'
|
||||
}
|
||||
|
|
|
@ -1,39 +1,36 @@
|
|||
package be.digitalia.fosdem.activities;
|
||||
|
||||
import android.content.Context;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import be.digitalia.fosdem.R;
|
||||
import be.digitalia.fosdem.db.DatabaseManager;
|
||||
import be.digitalia.fosdem.fragments.EventDetailsFragment;
|
||||
import be.digitalia.fosdem.loaders.LocalCacheLoader;
|
||||
import be.digitalia.fosdem.model.Event;
|
||||
import be.digitalia.fosdem.utils.NfcUtils;
|
||||
import be.digitalia.fosdem.utils.NfcUtils.CreateNfcAppDataCallback;
|
||||
import be.digitalia.fosdem.utils.ThemeUtils;
|
||||
import be.digitalia.fosdem.viewmodels.EventViewModel;
|
||||
|
||||
/**
|
||||
* Displays a single event passed either as a complete Parcelable object in extras or as an id in data.
|
||||
*
|
||||
* @author Christophe Beyls
|
||||
*/
|
||||
public class EventDetailsActivity extends BaseActivity implements LoaderCallbacks<Event>, CreateNfcAppDataCallback {
|
||||
public class EventDetailsActivity extends BaseActivity implements Observer<Event>, CreateNfcAppDataCallback {
|
||||
|
||||
public static final String EXTRA_EVENT = "event";
|
||||
|
||||
private static final int EVENT_LOADER_ID = 1;
|
||||
|
||||
private Event event;
|
||||
|
||||
@Override
|
||||
|
@ -56,7 +53,38 @@ public class EventDetailsActivity extends BaseActivity implements LoaderCallback
|
|||
}
|
||||
} else {
|
||||
// Load the event from the DB using its id
|
||||
getSupportLoaderManager().initLoader(EVENT_LOADER_ID, null, this);
|
||||
EventViewModel viewModel = ViewModelProviders.of(this).get(EventViewModel.class);
|
||||
if (!viewModel.hasEventId()) {
|
||||
Intent intent = getIntent();
|
||||
String eventIdString;
|
||||
if (NfcUtils.hasAppData(intent)) {
|
||||
// NFC intent
|
||||
eventIdString = new String(NfcUtils.extractAppData(intent));
|
||||
} else {
|
||||
// Normal in-app intent
|
||||
eventIdString = intent.getDataString();
|
||||
}
|
||||
viewModel.setEventId(Long.parseLong(eventIdString));
|
||||
}
|
||||
viewModel.getEvent().observe(this, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChanged(@Nullable Event event) {
|
||||
if (event == null) {
|
||||
// Event not found, quit
|
||||
Toast.makeText(this, getString(R.string.event_not_found_error), Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
initEvent(event);
|
||||
|
||||
FragmentManager fm = getSupportFragmentManager();
|
||||
if (fm.findFragmentById(R.id.content) == null) {
|
||||
Fragment f = EventDetailsFragment.newInstance(event);
|
||||
fm.beginTransaction().add(R.id.content, f).commitAllowingStateLoss();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,55 +132,4 @@ public class EventDetailsActivity extends BaseActivity implements LoaderCallback
|
|||
public byte[] createNfcAppData() {
|
||||
return String.valueOf(event.getId()).getBytes();
|
||||
}
|
||||
|
||||
private static class EventLoader extends LocalCacheLoader<Event> {
|
||||
|
||||
private final long eventId;
|
||||
|
||||
public EventLoader(Context context, long eventId) {
|
||||
super(context);
|
||||
this.eventId = eventId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event loadInBackground() {
|
||||
return DatabaseManager.getInstance().getEvent(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<Event> onCreateLoader(int id, Bundle args) {
|
||||
Intent intent = getIntent();
|
||||
String eventIdString;
|
||||
if (NfcUtils.hasAppData(intent)) {
|
||||
// NFC intent
|
||||
eventIdString = new String(NfcUtils.extractAppData(intent));
|
||||
} else {
|
||||
// Normal in-app intent
|
||||
eventIdString = intent.getDataString();
|
||||
}
|
||||
return new EventLoader(this, Long.parseLong(eventIdString));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Event> loader, Event data) {
|
||||
if (data == null) {
|
||||
// Event not found, quit
|
||||
Toast.makeText(this, getString(R.string.event_not_found_error), Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
initEvent(data);
|
||||
|
||||
FragmentManager fm = getSupportFragmentManager();
|
||||
if (fm.findFragmentById(R.id.content) == null) {
|
||||
Fragment f = EventDetailsFragment.newInstance(data);
|
||||
fm.beginTransaction().add(R.id.content, f).commitAllowingStateLoss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Event> loader) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package be.digitalia.fosdem.db;
|
||||
|
||||
import android.app.SearchManager;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -11,11 +12,14 @@ import android.database.sqlite.SQLiteConstraintException;
|
|||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteStatement;
|
||||
import android.provider.BaseColumns;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -25,6 +29,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import be.digitalia.fosdem.BuildConfig;
|
||||
import be.digitalia.fosdem.livedata.AsyncTaskLiveData;
|
||||
import be.digitalia.fosdem.model.Day;
|
||||
import be.digitalia.fosdem.model.Event;
|
||||
import be.digitalia.fosdem.model.Link;
|
||||
|
@ -55,7 +60,6 @@ public class DatabaseManager {
|
|||
private final Context context;
|
||||
private final DatabaseHelper helper;
|
||||
|
||||
private List<Day> cachedDays;
|
||||
private int year = -1;
|
||||
|
||||
public static void init(Context context) {
|
||||
|
@ -128,8 +132,10 @@ public class DatabaseManager {
|
|||
* @param events
|
||||
* @return The number of events processed.
|
||||
*/
|
||||
@WorkerThread
|
||||
public int storeSchedule(Iterable<Event> events, String lastModifiedTag) {
|
||||
boolean isComplete = false;
|
||||
List<Day> daysList = null;
|
||||
|
||||
SQLiteDatabase db = helper.getWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
@ -245,6 +251,8 @@ public class DatabaseManager {
|
|||
values.put("date", (date == null) ? 0L : date.getTime());
|
||||
db.insert(DatabaseHelper.DAYS_TABLE_NAME, null, values);
|
||||
}
|
||||
daysList = new ArrayList<>(days);
|
||||
Collections.sort(daysList);
|
||||
|
||||
// 4: Purge outdated bookmarks
|
||||
if (minEventId < Long.MAX_VALUE) {
|
||||
|
@ -262,8 +270,8 @@ public class DatabaseManager {
|
|||
db.endTransaction();
|
||||
|
||||
if (isComplete) {
|
||||
// Clear cache
|
||||
cachedDays = null;
|
||||
// Update/clear cache
|
||||
daysLiveData.postValue(daysList);
|
||||
year = -1;
|
||||
// Set last update time and server's last modified tag
|
||||
getSharedPreferences().edit()
|
||||
|
@ -276,6 +284,7 @@ public class DatabaseManager {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public void clearSchedule() {
|
||||
SQLiteDatabase db = helper.getWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
@ -284,7 +293,7 @@ public class DatabaseManager {
|
|||
|
||||
db.setTransactionSuccessful();
|
||||
|
||||
cachedDays = null;
|
||||
daysLiveData.postValue(Collections.<Day>emptyList());
|
||||
year = -1;
|
||||
getSharedPreferences().edit()
|
||||
.remove(LAST_UPDATE_TIME_PREF)
|
||||
|
@ -306,21 +315,16 @@ public class DatabaseManager {
|
|||
db.delete(DatabaseHelper.DAYS_TABLE_NAME, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cached days list or null. Can be safely called on the main thread without blocking it.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<Day> getCachedDays() {
|
||||
return cachedDays;
|
||||
private final AsyncTaskLiveData<List<Day>> daysLiveData = new AsyncTaskLiveData<List<Day>>() {
|
||||
|
||||
{
|
||||
onContentChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Days the events span to.
|
||||
*/
|
||||
public List<Day> getDays() {
|
||||
Cursor cursor = helper.getReadableDatabase().query(DatabaseHelper.DAYS_TABLE_NAME, new String[]{"_index", "date"}, null, null, null, null,
|
||||
"_index ASC");
|
||||
@Override
|
||||
protected List<Day> loadInBackground() throws Exception {
|
||||
Cursor cursor = helper.getReadableDatabase().query(DatabaseHelper.DAYS_TABLE_NAME,
|
||||
new String[]{"_index", "date"}, null, null, null, null, "_index ASC");
|
||||
try {
|
||||
List<Day> result = new ArrayList<>(cursor.getCount());
|
||||
while (cursor.moveToNext()) {
|
||||
|
@ -329,12 +333,19 @@ public class DatabaseManager {
|
|||
day.setDate(new Date(cursor.getLong(1)));
|
||||
result.add(day);
|
||||
}
|
||||
cachedDays = result;
|
||||
return result;
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @return The Days the events span to.
|
||||
*/
|
||||
public LiveData<List<Day>> getDays() {
|
||||
return daysLiveData;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
// Try to get the cached value first
|
||||
|
@ -344,10 +355,11 @@ public class DatabaseManager {
|
|||
|
||||
Calendar cal = Calendar.getInstance(DateUtils.getBelgiumTimeZone(), Locale.US);
|
||||
|
||||
// Compute from cachedDays if available
|
||||
if (cachedDays != null) {
|
||||
if (cachedDays.size() > 0) {
|
||||
cal.setTime(cachedDays.get(0).getDate());
|
||||
// Compute from cached days if available
|
||||
List<Day> days = daysLiveData.getValue();
|
||||
if (days != null) {
|
||||
if (days.size() > 0) {
|
||||
cal.setTime(days.get(0).getDate());
|
||||
}
|
||||
} else {
|
||||
// Perform a quick DB query to retrieve the time of the first day
|
||||
|
@ -367,6 +379,7 @@ public class DatabaseManager {
|
|||
return year;
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public Cursor getTracks(Day day) {
|
||||
String[] selectionArgs = new String[]{String.valueOf(day.getIndex())};
|
||||
Cursor cursor = helper.getReadableDatabase().rawQuery(
|
||||
|
@ -392,13 +405,16 @@ public class DatabaseManager {
|
|||
return toTrack(cursor, null);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public long getEventsCount() {
|
||||
return queryNumEntries(helper.getReadableDatabase(), DatabaseHelper.EVENTS_TABLE_NAME, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the event with the specified id.
|
||||
* Returns the event with the specified id, or null if not found.
|
||||
*/
|
||||
@WorkerThread
|
||||
@Nullable
|
||||
public Event getEvent(long id) {
|
||||
String[] selectionArgs = new String[]{String.valueOf(id)};
|
||||
Cursor cursor = helper.getReadableDatabase().rawQuery(
|
||||
|
@ -436,6 +452,7 @@ public class DatabaseManager {
|
|||
* @param track
|
||||
* @return A cursor to Events
|
||||
*/
|
||||
@WorkerThread
|
||||
public Cursor getEvents(Day day, Track track) {
|
||||
String[] selectionArgs = new String[]{String.valueOf(day.getIndex()), track.getName(), track.getType().name()};
|
||||
Cursor cursor = helper.getReadableDatabase().rawQuery(
|
||||
|
@ -462,6 +479,7 @@ public class DatabaseManager {
|
|||
* @param ascending If true, order results from start time ascending, else order from start time descending
|
||||
* @return
|
||||
*/
|
||||
@WorkerThread
|
||||
public Cursor getEvents(long minStartTime, long maxStartTime, long minEndTime, boolean ascending) {
|
||||
ArrayList<String> selectionArgs = new ArrayList<>(3);
|
||||
StringBuilder whereCondition = new StringBuilder();
|
||||
|
@ -511,6 +529,7 @@ public class DatabaseManager {
|
|||
* @param person
|
||||
* @return A cursor to Events
|
||||
*/
|
||||
@WorkerThread
|
||||
public Cursor getEvents(Person person) {
|
||||
String[] selectionArgs = new String[]{String.valueOf(person.getId())};
|
||||
Cursor cursor = helper.getReadableDatabase().rawQuery(
|
||||
|
@ -535,6 +554,7 @@ public class DatabaseManager {
|
|||
* @param minStartTime When positive, only return the events starting after this time.
|
||||
* @return A cursor to Events
|
||||
*/
|
||||
@WorkerThread
|
||||
public Cursor getBookmarks(long minStartTime) {
|
||||
String whereCondition;
|
||||
String[] selectionArgs;
|
||||
|
@ -568,6 +588,7 @@ public class DatabaseManager {
|
|||
* @param query
|
||||
* @return A cursor to Events
|
||||
*/
|
||||
@WorkerThread
|
||||
public Cursor getSearchResults(String query) {
|
||||
final String matchQuery = query + "*";
|
||||
String[] selectionArgs = new String[]{matchQuery, "%" + query + "%", matchQuery};
|
||||
|
@ -603,6 +624,7 @@ public class DatabaseManager {
|
|||
/**
|
||||
* Method called by SearchSuggestionProvider to return search results in the format expected by the search framework.
|
||||
*/
|
||||
@WorkerThread
|
||||
public Cursor getSearchSuggestionResults(String query, int limit) {
|
||||
final String matchQuery = query + "*";
|
||||
String[] selectionArgs = new String[]{matchQuery, "%" + query + "%", matchQuery, String.valueOf(limit)};
|
||||
|
@ -720,6 +742,7 @@ public class DatabaseManager {
|
|||
/**
|
||||
* Returns all persons in alphabetical order.
|
||||
*/
|
||||
@WorkerThread
|
||||
public Cursor getPersons() {
|
||||
Cursor cursor = helper.getReadableDatabase().rawQuery(
|
||||
"SELECT rowid AS _id, name"
|
||||
|
@ -733,6 +756,7 @@ public class DatabaseManager {
|
|||
/**
|
||||
* Returns persons presenting the specified event.
|
||||
*/
|
||||
@WorkerThread
|
||||
public List<Person> getPersons(Event event) {
|
||||
String[] selectionArgs = new String[]{String.valueOf(event.getId())};
|
||||
Cursor cursor = helper.getReadableDatabase().rawQuery(
|
||||
|
@ -765,6 +789,7 @@ public class DatabaseManager {
|
|||
return toPerson(cursor, null);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public List<Link> getLinks(Event event) {
|
||||
String[] selectionArgs = new String[]{String.valueOf(event.getId())};
|
||||
Cursor cursor = helper.getReadableDatabase().rawQuery(
|
||||
|
@ -786,11 +811,13 @@ public class DatabaseManager {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public boolean isBookmarked(Event event) {
|
||||
String[] selectionArgs = new String[]{String.valueOf(event.getId())};
|
||||
return queryNumEntries(helper.getReadableDatabase(), DatabaseHelper.BOOKMARKS_TABLE_NAME, "event_id = ?", selectionArgs) > 0L;
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public boolean addBookmark(Event event) {
|
||||
boolean complete = false;
|
||||
|
||||
|
@ -823,14 +850,17 @@ public class DatabaseManager {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public boolean removeBookmark(Event event) {
|
||||
return removeBookmarks(new long[]{event.getId()});
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public boolean removeBookmark(long eventId) {
|
||||
return removeBookmarks(new long[]{eventId});
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public boolean removeBookmarks(long[] eventIds) {
|
||||
int length = eventIds.length;
|
||||
if (length == 0) {
|
||||
|
|
|
@ -2,22 +2,21 @@ package be.digitalia.fosdem.fragments;
|
|||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.provider.CalendarContract;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.customtabs.CustomTabsIntent;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.app.ShareCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
|
@ -38,19 +37,16 @@ import android.widget.Toast;
|
|||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import be.digitalia.fosdem.R;
|
||||
import be.digitalia.fosdem.activities.PersonInfoActivity;
|
||||
import be.digitalia.fosdem.db.DatabaseManager;
|
||||
import be.digitalia.fosdem.loaders.BookmarkStatusLoader;
|
||||
import be.digitalia.fosdem.loaders.LocalCacheLoader;
|
||||
import be.digitalia.fosdem.model.Building;
|
||||
import be.digitalia.fosdem.model.Event;
|
||||
import be.digitalia.fosdem.model.Link;
|
||||
import be.digitalia.fosdem.model.Person;
|
||||
import be.digitalia.fosdem.utils.DateUtils;
|
||||
import be.digitalia.fosdem.utils.StringUtils;
|
||||
import be.digitalia.fosdem.viewmodels.EventDetailsViewModel;
|
||||
|
||||
public class EventDetailsFragment extends Fragment {
|
||||
|
||||
|
@ -62,11 +58,6 @@ public class EventDetailsFragment extends Fragment {
|
|||
ImageView getActionButton();
|
||||
}
|
||||
|
||||
static class EventDetails {
|
||||
List<Person> persons;
|
||||
List<Link> links;
|
||||
}
|
||||
|
||||
static class ViewHolder {
|
||||
LayoutInflater inflater;
|
||||
TextView personsTextView;
|
||||
|
@ -74,15 +65,12 @@ public class EventDetailsFragment extends Fragment {
|
|||
ViewGroup linksContainer;
|
||||
}
|
||||
|
||||
private static final int BOOKMARK_STATUS_LOADER_ID = 1;
|
||||
private static final int EVENT_DETAILS_LOADER_ID = 2;
|
||||
|
||||
private static final String ARG_EVENT = "event";
|
||||
|
||||
Event event;
|
||||
int personsCount = 1;
|
||||
Boolean isBookmarked;
|
||||
ViewHolder holder;
|
||||
EventDetailsViewModel viewModel;
|
||||
|
||||
private MenuItem bookmarkMenuItem;
|
||||
private ImageView actionButton;
|
||||
|
@ -99,6 +87,8 @@ public class EventDetailsFragment extends Fragment {
|
|||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
event = getArguments().getParcelable(ARG_EVENT);
|
||||
viewModel = ViewModelProviders.of(this).get(EventDetailsViewModel.class);
|
||||
viewModel.setEvent(event);
|
||||
}
|
||||
|
||||
public Event getEvent() {
|
||||
|
@ -212,18 +202,25 @@ public class EventDetailsFragment extends Fragment {
|
|||
// Ensure the actionButton is initialized before creating the options menu
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
LoaderManager loaderManager = getLoaderManager();
|
||||
loaderManager.initLoader(BOOKMARK_STATUS_LOADER_ID, null, bookmarkStatusLoaderCallbacks);
|
||||
loaderManager.initLoader(EVENT_DETAILS_LOADER_ID, null, eventDetailsLoaderCallbacks);
|
||||
viewModel.getBookmarkStatus().observe(this, new Observer<Boolean>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable Boolean isBookmarked) {
|
||||
updateBookmarkMenuItem(isBookmarked, true);
|
||||
}
|
||||
});
|
||||
viewModel.getEventDetails().observe(this, new Observer<EventDetailsViewModel.EventDetails>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable EventDetailsViewModel.EventDetails eventDetails) {
|
||||
setEventDetails(eventDetails);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private final View.OnClickListener actionButtonClickListener = new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (isBookmarked != null) {
|
||||
new UpdateBookmarkAsyncTask(event).execute(isBookmarked);
|
||||
}
|
||||
viewModel.toggleBookmarkStatus();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -246,7 +243,7 @@ public class EventDetailsFragment extends Fragment {
|
|||
if (actionButton != null) {
|
||||
bookmarkMenuItem.setEnabled(false).setVisible(false);
|
||||
}
|
||||
updateBookmarkMenuItem(false);
|
||||
updateBookmarkMenuItem(viewModel.getBookmarkStatus().getValue(), false);
|
||||
}
|
||||
|
||||
private Intent getShareChooserIntent() {
|
||||
|
@ -258,7 +255,7 @@ public class EventDetailsFragment extends Fragment {
|
|||
.createChooserIntent();
|
||||
}
|
||||
|
||||
void updateBookmarkMenuItem(boolean animate) {
|
||||
void updateBookmarkMenuItem(Boolean isBookmarked, boolean animate) {
|
||||
if (actionButton != null) {
|
||||
// Action Button is used as bookmark button
|
||||
|
||||
|
@ -317,9 +314,7 @@ public class EventDetailsFragment extends Fragment {
|
|||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.bookmark:
|
||||
if (isBookmarked != null) {
|
||||
new UpdateBookmarkAsyncTask(event).execute(isBookmarked);
|
||||
}
|
||||
viewModel.toggleBookmarkStatus();
|
||||
return true;
|
||||
case R.id.add_to_agenda:
|
||||
addToAgenda();
|
||||
|
@ -328,25 +323,6 @@ public class EventDetailsFragment extends Fragment {
|
|||
return false;
|
||||
}
|
||||
|
||||
private static class UpdateBookmarkAsyncTask extends AsyncTask<Boolean, Void, Void> {
|
||||
|
||||
private final Event event;
|
||||
|
||||
public UpdateBookmarkAsyncTask(Event event) {
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Boolean... remove) {
|
||||
if (remove[0]) {
|
||||
DatabaseManager.getInstance().removeBookmark(event);
|
||||
} else {
|
||||
DatabaseManager.getInstance().addBookmark(event);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
private void addToAgenda() {
|
||||
Intent intent = new Intent(Intent.ACTION_EDIT);
|
||||
|
@ -379,54 +355,7 @@ public class EventDetailsFragment extends Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
private final LoaderCallbacks<Boolean> bookmarkStatusLoaderCallbacks = new LoaderCallbacks<Boolean>() {
|
||||
|
||||
@Override
|
||||
public Loader<Boolean> onCreateLoader(int id, Bundle args) {
|
||||
return new BookmarkStatusLoader(getActivity(), event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Boolean> loader, Boolean data) {
|
||||
if (isBookmarked != data) {
|
||||
isBookmarked = data;
|
||||
updateBookmarkMenuItem(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Boolean> loader) {
|
||||
}
|
||||
};
|
||||
|
||||
private static class EventDetailsLoader extends LocalCacheLoader<EventDetails> {
|
||||
|
||||
private final Event event;
|
||||
|
||||
public EventDetailsLoader(Context context, Event event) {
|
||||
super(context);
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventDetails loadInBackground() {
|
||||
EventDetails result = new EventDetails();
|
||||
DatabaseManager dbm = DatabaseManager.getInstance();
|
||||
result.persons = dbm.getPersons(event);
|
||||
result.links = dbm.getLinks(event);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private final LoaderCallbacks<EventDetails> eventDetailsLoaderCallbacks = new LoaderCallbacks<EventDetails>() {
|
||||
|
||||
@Override
|
||||
public Loader<EventDetails> onCreateLoader(int id, Bundle args) {
|
||||
return new EventDetailsLoader(getActivity(), event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<EventDetails> loader, EventDetails data) {
|
||||
void setEventDetails(@NonNull EventDetailsViewModel.EventDetails data) {
|
||||
// 1. Persons
|
||||
if (data.persons != null) {
|
||||
personsCount = data.persons.size();
|
||||
|
@ -466,11 +395,6 @@ public class EventDetailsFragment extends Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<EventDetails> loader) {
|
||||
}
|
||||
};
|
||||
|
||||
private static class PersonClickableSpan extends ClickableSpan {
|
||||
|
||||
private final Person person;
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
package be.digitalia.fosdem.fragments;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.Observer;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -23,11 +21,10 @@ import java.util.List;
|
|||
|
||||
import be.digitalia.fosdem.R;
|
||||
import be.digitalia.fosdem.db.DatabaseManager;
|
||||
import be.digitalia.fosdem.loaders.GlobalCacheLoader;
|
||||
import be.digitalia.fosdem.model.Day;
|
||||
import be.digitalia.fosdem.widgets.SlidingTabLayout;
|
||||
|
||||
public class TracksFragment extends Fragment implements RecycledViewPoolProvider, LoaderCallbacks<List<Day>> {
|
||||
public class TracksFragment extends Fragment implements RecycledViewPoolProvider, Observer<List<Day>> {
|
||||
|
||||
static class ViewHolder {
|
||||
View contentView;
|
||||
|
@ -38,7 +35,6 @@ public class TracksFragment extends Fragment implements RecycledViewPoolProvider
|
|||
RecyclerView.RecycledViewPool recycledViewPool;
|
||||
}
|
||||
|
||||
private static final int DAYS_LOADER_ID = 1;
|
||||
private static final String PREF_CURRENT_PAGE = "tracks_current_page";
|
||||
|
||||
private ViewHolder holder;
|
||||
|
@ -79,7 +75,9 @@ public class TracksFragment extends Fragment implements RecycledViewPoolProvider
|
|||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
getLoaderManager().initLoader(DAYS_LOADER_ID, null, this);
|
||||
LiveData<List<Day>> daysLiveData = DatabaseManager.getInstance().getDays();
|
||||
daysLiveData.removeObserver(this);
|
||||
daysLiveData.observe(this, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -100,48 +98,9 @@ public class TracksFragment extends Fragment implements RecycledViewPoolProvider
|
|||
return (holder == null) ? null : holder.recycledViewPool;
|
||||
}
|
||||
|
||||
private static class DaysLoader extends GlobalCacheLoader<List<Day>> {
|
||||
|
||||
private final BroadcastReceiver scheduleRefreshedReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
onContentChanged();
|
||||
}
|
||||
};
|
||||
|
||||
public DaysLoader(Context context) {
|
||||
super(context);
|
||||
// Reload days list when the schedule has been refreshed
|
||||
LocalBroadcastManager.getInstance(context).registerReceiver(scheduleRefreshedReceiver,
|
||||
new IntentFilter(DatabaseManager.ACTION_SCHEDULE_REFRESHED));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReset() {
|
||||
super.onReset();
|
||||
LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(scheduleRefreshedReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Day> getCachedResult() {
|
||||
return DatabaseManager.getInstance().getCachedDays();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Day> loadInBackground() {
|
||||
return DatabaseManager.getInstance().getDays();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<List<Day>> onCreateLoader(int id, Bundle args) {
|
||||
return new DaysLoader(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<List<Day>> loader, List<Day> data) {
|
||||
holder.daysAdapter.setDays(data);
|
||||
public void onChanged(@Nullable List<Day> days) {
|
||||
holder.daysAdapter.setDays(days);
|
||||
|
||||
final int totalPages = holder.daysAdapter.getCount();
|
||||
if (totalPages == 0) {
|
||||
|
@ -161,10 +120,6 @@ public class TracksFragment extends Fragment implements RecycledViewPoolProvider
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<List<Day>> loader) {
|
||||
}
|
||||
|
||||
private static class DaysAdapter extends FragmentStatePagerAdapter {
|
||||
|
||||
private List<Day> days;
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
package be.digitalia.fosdem.livedata;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.arch.lifecycle.MutableLiveData;
|
||||
import android.os.AsyncTask;
|
||||
import android.support.annotation.MainThread;
|
||||
import android.support.annotation.WorkerThread;
|
||||
|
||||
/**
|
||||
* A LiveData implementation with the same basic functionality as AsyncTaskLoader.
|
||||
*/
|
||||
public abstract class AsyncTaskLiveData<T> extends MutableLiveData<T> {
|
||||
|
||||
private boolean contentChanged = false;
|
||||
AsyncTask<Void, Void, T> task = null;
|
||||
|
||||
@MainThread
|
||||
public void onContentChanged() {
|
||||
if (hasActiveObservers()) {
|
||||
forceLoad();
|
||||
} else {
|
||||
contentChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public boolean cancelLoad() {
|
||||
if (task != null) {
|
||||
boolean result = task.cancel(false);
|
||||
task = null;
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActive() {
|
||||
if (contentChanged) {
|
||||
contentChanged = false;
|
||||
forceLoad();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(T value) {
|
||||
// Setting a value will cancel any pending AsyncTask
|
||||
contentChanged = false;
|
||||
cancelLoad();
|
||||
super.setValue(value);
|
||||
}
|
||||
|
||||
@MainThread
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public void forceLoad() {
|
||||
cancelLoad();
|
||||
task = new AsyncTask<Void, Void, T>() {
|
||||
|
||||
private Throwable error;
|
||||
|
||||
@Override
|
||||
protected T doInBackground(Void... voids) {
|
||||
try {
|
||||
return loadInBackground();
|
||||
} catch (Throwable e) {
|
||||
error = e;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(T result) {
|
||||
task = null;
|
||||
if (error == null) {
|
||||
onSuccess(result);
|
||||
} else {
|
||||
onError(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
|
||||
@WorkerThread
|
||||
protected abstract T loadInBackground() throws Exception;
|
||||
|
||||
@MainThread
|
||||
protected void onSuccess(T result) {
|
||||
setValue(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method for custom error handling.
|
||||
*/
|
||||
@MainThread
|
||||
protected void onError(Throwable error) {
|
||||
error.printStackTrace();
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
package be.digitalia.fosdem.loaders;
|
||||
|
||||
import be.digitalia.fosdem.db.DatabaseManager;
|
||||
import be.digitalia.fosdem.model.Event;
|
||||
import be.digitalia.fosdem.utils.ArrayUtils;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
|
||||
/**
|
||||
* This loader retrieves the bookmark status of an event from the database, then updates it in real time by listening to broadcasts.
|
||||
*
|
||||
* @author Christophe Beyls
|
||||
*
|
||||
*/
|
||||
public class BookmarkStatusLoader extends AsyncTaskLoader<Boolean> {
|
||||
|
||||
final Event event;
|
||||
private Boolean isBookmarked;
|
||||
|
||||
private final BroadcastReceiver addBookmarkReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (event.getId() == intent.getLongExtra(DatabaseManager.EXTRA_EVENT_ID, -1L)) {
|
||||
updateBookmark(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final BroadcastReceiver removeBookmarksReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
long[] eventIds = intent.getLongArrayExtra(DatabaseManager.EXTRA_EVENT_IDS);
|
||||
if (ArrayUtils.indexOf(eventIds, event.getId()) != -1) {
|
||||
updateBookmark(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public BookmarkStatusLoader(Context context, Event event) {
|
||||
super(context);
|
||||
this.event = event;
|
||||
|
||||
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getContext());
|
||||
lbm.registerReceiver(addBookmarkReceiver, new IntentFilter(DatabaseManager.ACTION_ADD_BOOKMARK));
|
||||
lbm.registerReceiver(removeBookmarksReceiver, new IntentFilter(DatabaseManager.ACTION_REMOVE_BOOKMARKS));
|
||||
}
|
||||
|
||||
void updateBookmark(Boolean result) {
|
||||
if (isStarted()) {
|
||||
cancelLoad();
|
||||
}
|
||||
deliverResult(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
if (isBookmarked != null) {
|
||||
// If we currently have a result available, deliver it
|
||||
// immediately.
|
||||
super.deliverResult(isBookmarked);
|
||||
} else {
|
||||
forceLoad();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStopLoading() {
|
||||
// Attempt to cancel the current load task if possible.
|
||||
cancelLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReset() {
|
||||
super.onReset();
|
||||
|
||||
onStopLoading();
|
||||
isBookmarked = null;
|
||||
|
||||
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getContext());
|
||||
lbm.unregisterReceiver(addBookmarkReceiver);
|
||||
lbm.unregisterReceiver(removeBookmarksReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliverResult(Boolean data) {
|
||||
isBookmarked = data;
|
||||
|
||||
if (isStarted()) {
|
||||
// If the Loader is currently started, we can immediately
|
||||
// deliver its results.
|
||||
super.deliverResult(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean loadInBackground() {
|
||||
return DatabaseManager.getInstance().isBookmarked(event);
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package be.digitalia.fosdem.loaders;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
|
||||
/**
|
||||
* A Loader working with a global application cache instead of a local cache.
|
||||
* This allows to avoid starting a background thread if the result is already in cache.
|
||||
* You do NOT need to destroy this loader after the result has been delivered.
|
||||
* The cache will be checked each time the fragment is started.
|
||||
*
|
||||
* @author Christophe Beyls
|
||||
*/
|
||||
public abstract class GlobalCacheLoader<T> extends AsyncTaskLoader<T> {
|
||||
|
||||
public GlobalCacheLoader(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
T cachedResult = getCachedResult();
|
||||
if (cachedResult != null) {
|
||||
// If we currently have a result available, deliver it
|
||||
// immediately.
|
||||
deliverResult(cachedResult);
|
||||
}
|
||||
|
||||
if (takeContentChanged() || cachedResult == null) {
|
||||
// If the data has changed since the last time it was loaded
|
||||
// or is not currently available, start a load.
|
||||
forceLoad();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStopLoading() {
|
||||
// Attempt to cancel the current load task if possible.
|
||||
cancelLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReset() {
|
||||
super.onReset();
|
||||
|
||||
onStopLoading();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliverResult(T data) {
|
||||
if (isStarted()) {
|
||||
// If the Loader is currently started, we can immediately
|
||||
// deliver its results.
|
||||
super.deliverResult(data);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract T getCachedResult();
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package be.digitalia.fosdem.loaders;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
|
||||
public abstract class LocalCacheLoader<T> extends AsyncTaskLoader<T> {
|
||||
|
||||
private T mResult;
|
||||
|
||||
public LocalCacheLoader(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
if (mResult != null) {
|
||||
// If we currently have a result available, deliver it
|
||||
// immediately.
|
||||
deliverResult(mResult);
|
||||
}
|
||||
|
||||
if (takeContentChanged() || mResult == null) {
|
||||
// If the data has changed since the last time it was loaded
|
||||
// or is not currently available, start a load.
|
||||
forceLoad();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStopLoading() {
|
||||
// Attempt to cancel the current load task if possible.
|
||||
cancelLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReset() {
|
||||
super.onReset();
|
||||
|
||||
onStopLoading();
|
||||
mResult = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliverResult(T data) {
|
||||
mResult = data;
|
||||
|
||||
if (isStarted()) {
|
||||
// If the Loader is currently started, we can immediately
|
||||
// deliver its results.
|
||||
super.deliverResult(data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +1,17 @@
|
|||
package be.digitalia.fosdem.model;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import be.digitalia.fosdem.utils.DateUtils;
|
||||
|
||||
public class Day implements Parcelable {
|
||||
public class Day implements Comparable<Day>, Parcelable {
|
||||
|
||||
private static final DateFormat DAY_DATE_FORMAT = DateUtils.withBelgiumTimeZone(new SimpleDateFormat("EEEE", Locale.US));
|
||||
|
||||
|
@ -63,6 +65,11 @@ public class Day implements Parcelable {
|
|||
return (index == other.index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NonNull Day other) {
|
||||
return index - other.index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
package be.digitalia.fosdem.viewmodels;
|
||||
|
||||
import android.app.Application;
|
||||
import android.arch.lifecycle.AndroidViewModel;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.AsyncTask;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import be.digitalia.fosdem.db.DatabaseManager;
|
||||
import be.digitalia.fosdem.livedata.AsyncTaskLiveData;
|
||||
import be.digitalia.fosdem.model.Event;
|
||||
import be.digitalia.fosdem.model.Link;
|
||||
import be.digitalia.fosdem.model.Person;
|
||||
import be.digitalia.fosdem.utils.ArrayUtils;
|
||||
|
||||
public class EventDetailsViewModel extends AndroidViewModel {
|
||||
|
||||
public static class EventDetails {
|
||||
public List<Person> persons;
|
||||
public List<Link> links;
|
||||
}
|
||||
|
||||
private Event event = null;
|
||||
|
||||
private final AsyncTaskLiveData<Boolean> bookmarkStatus = new AsyncTaskLiveData<Boolean>() {
|
||||
|
||||
@Override
|
||||
protected Boolean loadInBackground() throws Exception {
|
||||
return DatabaseManager.getInstance().isBookmarked(event);
|
||||
}
|
||||
};
|
||||
private final AsyncTaskLiveData<EventDetails> eventDetails = new AsyncTaskLiveData<EventDetails>() {
|
||||
|
||||
@Override
|
||||
protected EventDetails loadInBackground() throws Exception {
|
||||
EventDetails result = new EventDetails();
|
||||
DatabaseManager dbm = DatabaseManager.getInstance();
|
||||
result.persons = dbm.getPersons(event);
|
||||
result.links = dbm.getLinks(event);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
private final BroadcastReceiver addBookmarkReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (event.getId() == intent.getLongExtra(DatabaseManager.EXTRA_EVENT_ID, -1L)) {
|
||||
bookmarkStatus.setValue(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
private final BroadcastReceiver removeBookmarksReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
long[] eventIds = intent.getLongArrayExtra(DatabaseManager.EXTRA_EVENT_IDS);
|
||||
if (ArrayUtils.indexOf(eventIds, event.getId()) != -1) {
|
||||
bookmarkStatus.setValue(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public EventDetailsViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
}
|
||||
|
||||
public void setEvent(@NonNull Event event) {
|
||||
if (this.event == null) {
|
||||
this.event = event;
|
||||
|
||||
bookmarkStatus.forceLoad();
|
||||
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getApplication());
|
||||
lbm.registerReceiver(addBookmarkReceiver, new IntentFilter(DatabaseManager.ACTION_ADD_BOOKMARK));
|
||||
lbm.registerReceiver(removeBookmarksReceiver, new IntentFilter(DatabaseManager.ACTION_REMOVE_BOOKMARKS));
|
||||
|
||||
eventDetails.forceLoad();
|
||||
}
|
||||
}
|
||||
|
||||
public LiveData<Boolean> getBookmarkStatus() {
|
||||
return bookmarkStatus;
|
||||
}
|
||||
|
||||
public void toggleBookmarkStatus() {
|
||||
Boolean isBookmarked = bookmarkStatus.getValue();
|
||||
if (isBookmarked != null) {
|
||||
new ToggleBookmarkAsyncTask(event).execute(isBookmarked);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ToggleBookmarkAsyncTask extends AsyncTask<Boolean, Void, Void> {
|
||||
|
||||
private final Event event;
|
||||
|
||||
public ToggleBookmarkAsyncTask(Event event) {
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Boolean... remove) {
|
||||
if (remove[0]) {
|
||||
DatabaseManager.getInstance().removeBookmark(event);
|
||||
} else {
|
||||
DatabaseManager.getInstance().addBookmark(event);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public LiveData<EventDetails> getEventDetails() {
|
||||
return eventDetails;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCleared() {
|
||||
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getApplication());
|
||||
lbm.unregisterReceiver(addBookmarkReceiver);
|
||||
lbm.unregisterReceiver(removeBookmarksReceiver);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package be.digitalia.fosdem.viewmodels;
|
||||
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.ViewModel;
|
||||
|
||||
import be.digitalia.fosdem.db.DatabaseManager;
|
||||
import be.digitalia.fosdem.livedata.AsyncTaskLiveData;
|
||||
import be.digitalia.fosdem.model.Event;
|
||||
|
||||
public class EventViewModel extends ViewModel {
|
||||
|
||||
private long eventId = -1L;
|
||||
|
||||
private final AsyncTaskLiveData<Event> event = new AsyncTaskLiveData<Event>() {
|
||||
@Override
|
||||
protected Event loadInBackground() throws Exception {
|
||||
return DatabaseManager.getInstance().getEvent(eventId);
|
||||
}
|
||||
};
|
||||
|
||||
public boolean hasEventId() {
|
||||
return this.eventId != -1L;
|
||||
}
|
||||
|
||||
public void setEventId(long eventId) {
|
||||
if (this.eventId != eventId) {
|
||||
this.eventId = eventId;
|
||||
event.forceLoad();
|
||||
}
|
||||
}
|
||||
|
||||
public LiveData<Event> getEvent() {
|
||||
return event;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue