Refactor DB read code to use RxJava
This commit is contained in:
parent
5db10d83f7
commit
f58a8561f8
|
@ -89,6 +89,9 @@ dependencies {
|
||||||
|
|
||||||
// For loading huge screenshots from the disk.
|
// For loading huge screenshots from the disk.
|
||||||
compile 'com.squareup.picasso:picasso:2.5.2'
|
compile 'com.squareup.picasso:picasso:2.5.2'
|
||||||
|
|
||||||
|
// Allows FRP-style asynchronous operations in Android.
|
||||||
|
compile 'io.reactivex:rxandroid:1.1.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
task setupCMake(type: Exec) {
|
task setupCMake(type: Exec) {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:name=".DolphinApplication"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package org.dolphinemu.dolphinemu;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import org.dolphinemu.dolphinemu.model.GameDatabase;
|
||||||
|
|
||||||
|
|
||||||
|
public class DolphinApplication extends Application
|
||||||
|
{
|
||||||
|
public static GameDatabase databaseHelper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate()
|
||||||
|
{
|
||||||
|
super.onCreate();
|
||||||
|
|
||||||
|
databaseHelper = new GameDatabase(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,6 @@
|
||||||
package org.dolphinemu.dolphinemu.activities;
|
package org.dolphinemu.dolphinemu.activities;
|
||||||
|
|
||||||
import android.app.LoaderManager;
|
|
||||||
import android.content.CursorLoader;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.Loader;
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -34,20 +31,11 @@ import org.dolphinemu.dolphinemu.utils.StartupHandler;
|
||||||
* The main Activity of the Lollipop style UI. Manages several PlatformGamesFragments, which
|
* The main Activity of the Lollipop style UI. Manages several PlatformGamesFragments, which
|
||||||
* individually display a grid of available games for each Fragment, in a tabbed layout.
|
* individually display a grid of available games for each Fragment, in a tabbed layout.
|
||||||
*/
|
*/
|
||||||
public final class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>
|
public final class MainActivity extends AppCompatActivity
|
||||||
{
|
{
|
||||||
public static final int REQUEST_ADD_DIRECTORY = 1;
|
public static final int REQUEST_ADD_DIRECTORY = 1;
|
||||||
public static final int REQUEST_EMULATE_GAME = 2;
|
public static final int REQUEST_EMULATE_GAME = 2;
|
||||||
|
|
||||||
/**
|
|
||||||
* It is important to keep track of loader ID separately from platform ID (see Game.java)
|
|
||||||
* because we could potentially have Loaders that load things other than Games.
|
|
||||||
*/
|
|
||||||
public static final int LOADER_ID_ALL = 100; // TODO
|
|
||||||
public static final int LOADER_ID_GAMECUBE = 0;
|
|
||||||
public static final int LOADER_ID_WII = 1;
|
|
||||||
public static final int LOADER_ID_WIIWARE = 2;
|
|
||||||
|
|
||||||
private ViewPager mViewPager;
|
private ViewPager mViewPager;
|
||||||
private PlatformPagerAdapter mPlatformPagerAdapter;
|
private PlatformPagerAdapter mPlatformPagerAdapter;
|
||||||
|
|
||||||
|
@ -175,132 +163,6 @@ public final class MainActivity extends AppCompatActivity implements LoaderManag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback that's invoked when the system has initialized the Loader and
|
|
||||||
* is ready to start the query. This usually happens when initLoader() is
|
|
||||||
* called. Here, we use it to make a DB query for games.
|
|
||||||
*
|
|
||||||
* @param id The ID value passed to the initLoader() call that triggered this.
|
|
||||||
* @param args The args bundle supplied by the caller.
|
|
||||||
* @return A new Loader instance that is ready to start loading.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Loader<Cursor> onCreateLoader(int id, Bundle args)
|
|
||||||
{
|
|
||||||
Log.d("DolphinEmu", "Creating loader with id: " + id);
|
|
||||||
|
|
||||||
// Take action based on the ID of the Loader that's being created.
|
|
||||||
switch (id)
|
|
||||||
{
|
|
||||||
case LOADER_ID_ALL:
|
|
||||||
// TODO Play some sort of load-starting animation; maybe fade the list out.
|
|
||||||
|
|
||||||
return new CursorLoader(
|
|
||||||
this, // Parent activity context
|
|
||||||
GameProvider.URI_GAME, // URI of table to query
|
|
||||||
null, // Return all columns
|
|
||||||
null, // No selection clause
|
|
||||||
null, // No selection arguments
|
|
||||||
GameDatabase.KEY_GAME_TITLE + " asc" // Sort by game name, ascending order
|
|
||||||
);
|
|
||||||
|
|
||||||
case LOADER_ID_GAMECUBE:
|
|
||||||
case LOADER_ID_WII:
|
|
||||||
case LOADER_ID_WIIWARE:
|
|
||||||
// TODO Play some sort of load-starting animation; maybe fade the list out.
|
|
||||||
|
|
||||||
return new CursorLoader(
|
|
||||||
this, // Parent activity context
|
|
||||||
GameProvider.URI_GAME, // URI of table to query
|
|
||||||
null, // Return all columns
|
|
||||||
GameDatabase.KEY_GAME_PLATFORM + " = ?", // Select by platform
|
|
||||||
new String[]{Integer.toString(id)}, // Platform id is Loader id
|
|
||||||
GameDatabase.KEY_GAME_TITLE + " asc" // Sort by game name, ascending order
|
|
||||||
);
|
|
||||||
|
|
||||||
default:
|
|
||||||
Log.e("DolphinEmu", "Bad ID passed in.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback that's invoked when the Loader returned in onCreateLoader is finished
|
|
||||||
* with its task. In this case, the game DB query is finished, so we should put the results
|
|
||||||
* on screen.
|
|
||||||
*
|
|
||||||
* @param loader The loader that finished.
|
|
||||||
* @param data The data the Loader loaded.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onLoadFinished(Loader<Cursor> loader, Cursor data)
|
|
||||||
{
|
|
||||||
int id = loader.getId();
|
|
||||||
Log.d("DolphinEmu", "Loader finished with id: " + id);
|
|
||||||
|
|
||||||
PlatformGamesFragment fragment = null;
|
|
||||||
switch (id)
|
|
||||||
{
|
|
||||||
case LOADER_ID_GAMECUBE:
|
|
||||||
fragment = getPlatformFragment(Game.PLATFORM_GC);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LOADER_ID_WII:
|
|
||||||
fragment = getPlatformFragment(Game.PLATFORM_WII);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LOADER_ID_WIIWARE:
|
|
||||||
fragment = getPlatformFragment(Game.PLATFORM_WII_WARE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// TODO case LOADER_ID_ALL:
|
|
||||||
|
|
||||||
default:
|
|
||||||
Log.e("DolphinEmu", "Bad ID passed in.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fragment != null)
|
|
||||||
{
|
|
||||||
fragment.onLoadFinished(loader, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoaderReset(Loader<Cursor> loader)
|
|
||||||
{
|
|
||||||
int id = loader.getId();
|
|
||||||
Log.e("DolphinEmu", "Loader resetting with id: " + id);
|
|
||||||
|
|
||||||
PlatformGamesFragment fragment = null;
|
|
||||||
switch (id)
|
|
||||||
{
|
|
||||||
case LOADER_ID_GAMECUBE:
|
|
||||||
fragment = getPlatformFragment(Game.PLATFORM_GC);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LOADER_ID_WII:
|
|
||||||
fragment = getPlatformFragment(Game.PLATFORM_WII);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LOADER_ID_WIIWARE:
|
|
||||||
fragment = getPlatformFragment(Game.PLATFORM_WII_WARE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// TODO case LOADER_ID_ALL:
|
|
||||||
|
|
||||||
default:
|
|
||||||
Log.e("DolphinEmu", "Bad ID passed in.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fragment != null)
|
|
||||||
{
|
|
||||||
fragment.onLoaderReset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public PlatformGamesFragment getPlatformFragment(int platform)
|
public PlatformGamesFragment getPlatformFragment(int platform)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package org.dolphinemu.dolphinemu.fragments;
|
package org.dolphinemu.dolphinemu.fragments;
|
||||||
|
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.app.LoaderManager;
|
|
||||||
import android.content.Loader;
|
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
@ -15,8 +13,14 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import org.dolphinemu.dolphinemu.BuildConfig;
|
import org.dolphinemu.dolphinemu.BuildConfig;
|
||||||
|
import org.dolphinemu.dolphinemu.DolphinApplication;
|
||||||
import org.dolphinemu.dolphinemu.R;
|
import org.dolphinemu.dolphinemu.R;
|
||||||
import org.dolphinemu.dolphinemu.adapters.GameAdapter;
|
import org.dolphinemu.dolphinemu.adapters.GameAdapter;
|
||||||
|
import org.dolphinemu.dolphinemu.model.GameDatabase;
|
||||||
|
|
||||||
|
import rx.android.schedulers.AndroidSchedulers;
|
||||||
|
import rx.functions.Action1;
|
||||||
|
import rx.schedulers.Schedulers;
|
||||||
|
|
||||||
public class PlatformGamesFragment extends Fragment
|
public class PlatformGamesFragment extends Fragment
|
||||||
{
|
{
|
||||||
|
@ -69,9 +73,7 @@ public class PlatformGamesFragment extends Fragment
|
||||||
|
|
||||||
recyclerView.addItemDecoration(new GameAdapter.SpacesItemDecoration(8));
|
recyclerView.addItemDecoration(new GameAdapter.SpacesItemDecoration(8));
|
||||||
|
|
||||||
// Create an adapter that will relate the dataset to the views on-screen. +1 because of LOADER_ID_ALL
|
loadGames();
|
||||||
getLoaderManager().initLoader(mPlatform, null,
|
|
||||||
(LoaderManager.LoaderCallbacks<Cursor>) getActivity());
|
|
||||||
|
|
||||||
mAdapter = new GameAdapter();
|
mAdapter = new GameAdapter();
|
||||||
recyclerView.setAdapter(mAdapter);
|
recyclerView.setAdapter(mAdapter);
|
||||||
|
@ -87,32 +89,35 @@ public class PlatformGamesFragment extends Fragment
|
||||||
public void refresh()
|
public void refresh()
|
||||||
{
|
{
|
||||||
Log.d("DolphinEmu", "[PlatformGamesFragment] " + mPlatform + ": Refreshing...");
|
Log.d("DolphinEmu", "[PlatformGamesFragment] " + mPlatform + ": Refreshing...");
|
||||||
// +1 because of LOADER_ID_ALL
|
loadGames();
|
||||||
getLoaderManager().restartLoader(mPlatform, null, (LoaderManager.LoaderCallbacks<Cursor>) getActivity());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onLoadFinished(Loader<Cursor> loader, Cursor data)
|
public void loadGames()
|
||||||
{
|
{
|
||||||
// TODO Play some sort of load-finished animation; maybe fade the list in.
|
Log.d("DolphinEmu", "[PlatformGamesFragment] " + mPlatform + ": Loading games...");
|
||||||
|
|
||||||
Log.d("DolphinEmu", "[PlatformGamesFragment] " + mPlatform + ": Load finished, swapping cursor...");
|
GameDatabase databaseHelper = DolphinApplication.databaseHelper;
|
||||||
Log.d("DolphinEmu", "[PlatformGamesFragment] " + mPlatform + ": Cursor size: " + data.getCount());
|
|
||||||
if (mAdapter != null)
|
|
||||||
{
|
|
||||||
mAdapter.swapCursor(data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.e("DolphinEmu", "[PlatformGamesFragment] " + mPlatform + ": No adapter available.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onLoaderReset()
|
databaseHelper.getGamesForPlatform(mPlatform)
|
||||||
{
|
.subscribeOn(Schedulers.io())
|
||||||
Log.e("DolphinEmu", "[PlatformGamesFragment] " + mPlatform + ": Loader reset; clearing data from view.");
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
if (mAdapter != null)
|
.subscribe(new Action1<Cursor>()
|
||||||
{
|
{
|
||||||
mAdapter.swapCursor(null);
|
@Override
|
||||||
}
|
public void call(Cursor data)
|
||||||
|
{
|
||||||
|
Log.d("DolphinEmu", "[PlatformGamesFragment] " + mPlatform + ": Load finished, swapping cursor...");
|
||||||
|
|
||||||
|
if (mAdapter != null)
|
||||||
|
{
|
||||||
|
mAdapter.swapCursor(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.e("DolphinEmu", "[PlatformGamesFragment] " + mPlatform + ": No adapter available.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,9 @@ import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import rx.Observable;
|
||||||
|
import rx.Subscriber;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper class that provides several utilities simplifying interaction with
|
* A helper class that provides several utilities simplifying interaction with
|
||||||
* the SQLite database.
|
* the SQLite database.
|
||||||
|
@ -252,4 +255,44 @@ public final class GameDatabase extends SQLiteOpenHelper
|
||||||
folderCursor.close();
|
folderCursor.close();
|
||||||
database.close();
|
database.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Observable<Cursor> getGamesForPlatform(final int platform)
|
||||||
|
{
|
||||||
|
return Observable.create(new Observable.OnSubscribe<Cursor>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void call(Subscriber<? super Cursor> subscriber)
|
||||||
|
{
|
||||||
|
Log.i("DolphinEmu", "[GameDatabase] Reading games list...");
|
||||||
|
|
||||||
|
String whereClause = null;
|
||||||
|
String[] whereArgs = null;
|
||||||
|
|
||||||
|
// If -1 passed in, return all games. Else, return games for one platform only.
|
||||||
|
if (platform >= 0)
|
||||||
|
{
|
||||||
|
whereClause = KEY_GAME_PLATFORM + " = ?";
|
||||||
|
whereArgs = new String[]{Integer.toString(platform)};
|
||||||
|
}
|
||||||
|
|
||||||
|
SQLiteDatabase database = getReadableDatabase();
|
||||||
|
|
||||||
|
Cursor resultCursor = database.query(
|
||||||
|
TABLE_NAME_GAMES,
|
||||||
|
null,
|
||||||
|
whereClause,
|
||||||
|
whereArgs,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
KEY_GAME_TITLE + " ASC"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Pass the result cursor to the consumer.
|
||||||
|
subscriber.onNext(resultCursor);
|
||||||
|
|
||||||
|
// Tell the consumer we're done; it will unsubscribe implicitly.
|
||||||
|
subscriber.onCompleted();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue