Browse Source
Merge pull request #400 from ammargitham/add-room
Merge pull request #400 from ammargitham/add-room
Add Room Persistence Libraryrenovate/org.robolectric-robolectric-4.x
Austin Huang
4 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 1959 additions and 982 deletions
-
27app/build.gradle
-
7app/proguard-rules.pro
-
114app/schemas/awais.instagrabber.db.AppDatabase/4.json
-
3app/src/main/AndroidManifest.xml
-
7app/src/main/java/awais/instagrabber/InstaGrabberApplication.java
-
3app/src/main/java/awais/instagrabber/activities/DirectDownload.java
-
18app/src/main/java/awais/instagrabber/adapters/AccountSwitcherAdapter.java
-
18app/src/main/java/awais/instagrabber/adapters/FavoritesAdapter.java
-
4app/src/main/java/awais/instagrabber/adapters/viewholder/FavoriteViewHolder.java
-
4app/src/main/java/awais/instagrabber/asyncs/NotificationsFetcher.java
-
3app/src/main/java/awais/instagrabber/asyncs/PostFetcher.java
-
229app/src/main/java/awais/instagrabber/db/AppDatabase.java
-
33app/src/main/java/awais/instagrabber/db/Converters.java
-
34app/src/main/java/awais/instagrabber/db/dao/AccountDao.java
-
35app/src/main/java/awais/instagrabber/db/dao/FavoriteDao.java
-
68app/src/main/java/awais/instagrabber/db/datasources/AccountDataSource.java
-
62app/src/main/java/awais/instagrabber/db/datasources/FavoriteDataSource.java
-
124app/src/main/java/awais/instagrabber/db/entities/Account.java
-
110app/src/main/java/awais/instagrabber/db/entities/Favorite.java
-
131app/src/main/java/awais/instagrabber/db/repositories/AccountRepository.java
-
88app/src/main/java/awais/instagrabber/db/repositories/FavoriteRepository.java
-
11app/src/main/java/awais/instagrabber/db/repositories/RepositoryCallback.java
-
58app/src/main/java/awais/instagrabber/dialogs/AccountSwitcherDialogFragment.java
-
10app/src/main/java/awais/instagrabber/dialogs/CreateBackupDialogFragment.java
-
5app/src/main/java/awais/instagrabber/dialogs/RestoreBackupDialogFragment.java
-
157app/src/main/java/awais/instagrabber/fragments/FavoritesFragment.java
-
93app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java
-
97app/src/main/java/awais/instagrabber/fragments/LocationFragment.java
-
6app/src/main/java/awais/instagrabber/fragments/NotificationsViewerFragment.java
-
147app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java
-
138app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java
-
98app/src/main/java/awais/instagrabber/utils/AppExecutors.java
-
25app/src/main/java/awais/instagrabber/utils/CookieUtils.java
-
552app/src/main/java/awais/instagrabber/utils/DataBox.java
-
402app/src/main/java/awais/instagrabber/utils/ExportImportUtils.java
-
1app/src/main/java/awais/instagrabber/utils/Utils.java
-
6app/src/main/java/awais/instagrabber/viewmodels/FavoritesViewModel.java
-
9app/src/main/res/layout/activity_login.xml
-
2app/src/main/res/layout/layout_profile_details.xml
-
2build.gradle
@ -0,0 +1,114 @@ |
|||||
|
{ |
||||
|
"formatVersion": 1, |
||||
|
"database": { |
||||
|
"version": 4, |
||||
|
"identityHash": "538d64adaeb8c3a98db9204955932e59", |
||||
|
"entities": [ |
||||
|
{ |
||||
|
"tableName": "accounts", |
||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `uid` TEXT, `username` TEXT, `cookie` TEXT, `full_name` TEXT, `profile_pic` TEXT)", |
||||
|
"fields": [ |
||||
|
{ |
||||
|
"fieldPath": "id", |
||||
|
"columnName": "id", |
||||
|
"affinity": "INTEGER", |
||||
|
"notNull": true |
||||
|
}, |
||||
|
{ |
||||
|
"fieldPath": "uid", |
||||
|
"columnName": "uid", |
||||
|
"affinity": "TEXT", |
||||
|
"notNull": false |
||||
|
}, |
||||
|
{ |
||||
|
"fieldPath": "username", |
||||
|
"columnName": "username", |
||||
|
"affinity": "TEXT", |
||||
|
"notNull": false |
||||
|
}, |
||||
|
{ |
||||
|
"fieldPath": "cookie", |
||||
|
"columnName": "cookie", |
||||
|
"affinity": "TEXT", |
||||
|
"notNull": false |
||||
|
}, |
||||
|
{ |
||||
|
"fieldPath": "fullName", |
||||
|
"columnName": "full_name", |
||||
|
"affinity": "TEXT", |
||||
|
"notNull": false |
||||
|
}, |
||||
|
{ |
||||
|
"fieldPath": "profilePic", |
||||
|
"columnName": "profile_pic", |
||||
|
"affinity": "TEXT", |
||||
|
"notNull": false |
||||
|
} |
||||
|
], |
||||
|
"primaryKey": { |
||||
|
"columnNames": [ |
||||
|
"id" |
||||
|
], |
||||
|
"autoGenerate": true |
||||
|
}, |
||||
|
"indices": [], |
||||
|
"foreignKeys": [] |
||||
|
}, |
||||
|
{ |
||||
|
"tableName": "favorites", |
||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `query_text` TEXT, `type` TEXT, `display_name` TEXT, `pic_url` TEXT, `date_added` INTEGER)", |
||||
|
"fields": [ |
||||
|
{ |
||||
|
"fieldPath": "id", |
||||
|
"columnName": "id", |
||||
|
"affinity": "INTEGER", |
||||
|
"notNull": true |
||||
|
}, |
||||
|
{ |
||||
|
"fieldPath": "query", |
||||
|
"columnName": "query_text", |
||||
|
"affinity": "TEXT", |
||||
|
"notNull": false |
||||
|
}, |
||||
|
{ |
||||
|
"fieldPath": "type", |
||||
|
"columnName": "type", |
||||
|
"affinity": "TEXT", |
||||
|
"notNull": false |
||||
|
}, |
||||
|
{ |
||||
|
"fieldPath": "displayName", |
||||
|
"columnName": "display_name", |
||||
|
"affinity": "TEXT", |
||||
|
"notNull": false |
||||
|
}, |
||||
|
{ |
||||
|
"fieldPath": "picUrl", |
||||
|
"columnName": "pic_url", |
||||
|
"affinity": "TEXT", |
||||
|
"notNull": false |
||||
|
}, |
||||
|
{ |
||||
|
"fieldPath": "dateAdded", |
||||
|
"columnName": "date_added", |
||||
|
"affinity": "INTEGER", |
||||
|
"notNull": false |
||||
|
} |
||||
|
], |
||||
|
"primaryKey": { |
||||
|
"columnNames": [ |
||||
|
"id" |
||||
|
], |
||||
|
"autoGenerate": true |
||||
|
}, |
||||
|
"indices": [], |
||||
|
"foreignKeys": [] |
||||
|
} |
||||
|
], |
||||
|
"views": [], |
||||
|
"setupQueries": [ |
||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", |
||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '538d64adaeb8c3a98db9204955932e59')" |
||||
|
] |
||||
|
} |
||||
|
} |
@ -0,0 +1,229 @@ |
|||||
|
package awais.instagrabber.db; |
||||
|
|
||||
|
import android.content.ContentValues; |
||||
|
import android.content.Context; |
||||
|
import android.database.Cursor; |
||||
|
import android.database.sqlite.SQLiteDatabase; |
||||
|
import android.util.Log; |
||||
|
import android.util.Pair; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
import androidx.room.Database; |
||||
|
import androidx.room.Room; |
||||
|
import androidx.room.RoomDatabase; |
||||
|
import androidx.room.TypeConverters; |
||||
|
import androidx.room.migration.Migration; |
||||
|
import androidx.sqlite.db.SupportSQLiteDatabase; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.Date; |
||||
|
import java.util.List; |
||||
|
|
||||
|
import awais.instagrabber.db.dao.AccountDao; |
||||
|
import awais.instagrabber.db.dao.FavoriteDao; |
||||
|
import awais.instagrabber.db.entities.Account; |
||||
|
import awais.instagrabber.db.entities.Favorite; |
||||
|
import awais.instagrabber.models.enums.FavoriteType; |
||||
|
import awais.instagrabber.utils.Utils; |
||||
|
|
||||
|
@Database(entities = {Account.class, Favorite.class}, |
||||
|
version = 4) |
||||
|
@TypeConverters({Converters.class}) |
||||
|
public abstract class AppDatabase extends RoomDatabase { |
||||
|
private static final String TAG = AppDatabase.class.getSimpleName(); |
||||
|
|
||||
|
private static AppDatabase INSTANCE; |
||||
|
|
||||
|
public abstract AccountDao accountDao(); |
||||
|
|
||||
|
public abstract FavoriteDao favoriteDao(); |
||||
|
|
||||
|
public static AppDatabase getDatabase(final Context context) { |
||||
|
if (INSTANCE == null) { |
||||
|
synchronized (AppDatabase.class) { |
||||
|
if (INSTANCE == null) { |
||||
|
INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "cookiebox.db") |
||||
|
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4) |
||||
|
.build(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return INSTANCE; |
||||
|
} |
||||
|
|
||||
|
static final Migration MIGRATION_1_2 = new Migration(1, 2) { |
||||
|
@Override |
||||
|
public void migrate(@NonNull SupportSQLiteDatabase db) { |
||||
|
db.execSQL("ALTER TABLE cookies ADD " + Account.COL_FULL_NAME + " TEXT"); |
||||
|
db.execSQL("ALTER TABLE cookies ADD " + Account.COL_PROFILE_PIC + " TEXT"); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
static final Migration MIGRATION_2_3 = new Migration(2, 3) { |
||||
|
@Override |
||||
|
public void migrate(@NonNull SupportSQLiteDatabase db) { |
||||
|
final List<Favorite> oldFavorites = backupOldFavorites(db); |
||||
|
// recreate with new columns (as there will be no doubt about the `query_display` column being present or not in the future versions) |
||||
|
db.execSQL("DROP TABLE " + Favorite.TABLE_NAME); |
||||
|
db.execSQL("CREATE TABLE " + Favorite.TABLE_NAME + " (" |
||||
|
+ Favorite.COL_ID + " INTEGER PRIMARY KEY," |
||||
|
+ Favorite.COL_QUERY + " TEXT," |
||||
|
+ Favorite.COL_TYPE + " TEXT," |
||||
|
+ Favorite.COL_DISPLAY_NAME + " TEXT," |
||||
|
+ Favorite.COL_PIC_URL + " TEXT," |
||||
|
+ Favorite.COL_DATE_ADDED + " INTEGER)"); |
||||
|
// add the old favorites back |
||||
|
for (final Favorite oldFavorite : oldFavorites) { |
||||
|
insertOrUpdateFavorite(db, oldFavorite); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
static final Migration MIGRATION_3_4 = new Migration(3, 4) { |
||||
|
@Override |
||||
|
public void migrate(@NonNull SupportSQLiteDatabase db) { |
||||
|
// Required when migrating to Room. |
||||
|
// The original table primary keys were not 'NOT NULL', so the migration to Room were failing without the below migration. |
||||
|
// Taking this opportunity to rename cookies table to accounts |
||||
|
|
||||
|
// Create new table with name 'accounts' |
||||
|
db.execSQL("CREATE TABLE " + Account.TABLE_NAME + " (" |
||||
|
+ Account.COL_ID + " INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," |
||||
|
+ Account.COL_UID + " TEXT," |
||||
|
+ Account.COL_USERNAME + " TEXT," |
||||
|
+ Account.COL_COOKIE + " TEXT," |
||||
|
+ Account.COL_FULL_NAME + " TEXT," |
||||
|
+ Account.COL_PROFILE_PIC + " TEXT)"); |
||||
|
// Insert all data from table 'cookies' to 'accounts' |
||||
|
db.execSQL("INSERT INTO " + Account.TABLE_NAME + " (" |
||||
|
+ Account.COL_UID + "," |
||||
|
+ Account.COL_USERNAME + "," |
||||
|
+ Account.COL_COOKIE + "," |
||||
|
+ Account.COL_FULL_NAME + "," |
||||
|
+ Account.COL_PROFILE_PIC + ") " |
||||
|
+ "SELECT " |
||||
|
+ Account.COL_UID + "," |
||||
|
+ Account.COL_USERNAME + "," |
||||
|
+ Account.COL_COOKIE + "," |
||||
|
+ Account.COL_FULL_NAME + "," |
||||
|
+ Account.COL_PROFILE_PIC |
||||
|
+ " FROM cookies"); |
||||
|
// Drop old cookies table |
||||
|
db.execSQL("DROP TABLE cookies"); |
||||
|
|
||||
|
// Create favorite backup table |
||||
|
db.execSQL("CREATE TABLE " + Favorite.TABLE_NAME + "_backup (" |
||||
|
+ Favorite.COL_ID + " INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," |
||||
|
+ Favorite.COL_QUERY + " TEXT," |
||||
|
+ Favorite.COL_TYPE + " TEXT," |
||||
|
+ Favorite.COL_DISPLAY_NAME + " TEXT," |
||||
|
+ Favorite.COL_PIC_URL + " TEXT," |
||||
|
+ Favorite.COL_DATE_ADDED + " INTEGER)"); |
||||
|
// Insert all data from table 'favorite' to 'favorite_backup' |
||||
|
db.execSQL("INSERT INTO " + Favorite.TABLE_NAME + "_backup (" |
||||
|
+ Favorite.COL_QUERY + "," |
||||
|
+ Favorite.COL_TYPE + "," |
||||
|
+ Favorite.COL_DISPLAY_NAME + "," |
||||
|
+ Favorite.COL_PIC_URL + "," |
||||
|
+ Favorite.COL_DATE_ADDED + ") " |
||||
|
+ "SELECT " |
||||
|
+ Favorite.COL_QUERY + "," |
||||
|
+ Favorite.COL_TYPE + "," |
||||
|
+ Favorite.COL_DISPLAY_NAME + "," |
||||
|
+ Favorite.COL_PIC_URL + "," |
||||
|
+ Favorite.COL_DATE_ADDED |
||||
|
+ " FROM " + Favorite.TABLE_NAME); |
||||
|
// Drop favorites |
||||
|
db.execSQL("DROP TABLE " + Favorite.TABLE_NAME); |
||||
|
// Rename favorite_backup to favorites |
||||
|
db.execSQL("ALTER TABLE " + Favorite.TABLE_NAME + "_backup RENAME TO " + Favorite.TABLE_NAME); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
@NonNull |
||||
|
private static List<Favorite> backupOldFavorites(@NonNull final SupportSQLiteDatabase db) { |
||||
|
// check if old favorites table had the column query_display |
||||
|
final boolean queryDisplayExists = checkColumnExists(db, Favorite.TABLE_NAME, "query_display"); |
||||
|
Log.d(TAG, "backupOldFavorites: queryDisplayExists: " + queryDisplayExists); |
||||
|
final List<Favorite> oldModels = new ArrayList<>(); |
||||
|
final String sql = "SELECT " |
||||
|
+ "query_text," |
||||
|
+ "date_added" |
||||
|
+ (queryDisplayExists ? ",query_display" : "") |
||||
|
+ " FROM " + Favorite.TABLE_NAME; |
||||
|
try (final Cursor cursor = db.query(sql)) { |
||||
|
if (cursor != null && cursor.moveToFirst()) { |
||||
|
do { |
||||
|
try { |
||||
|
final String queryText = cursor.getString(cursor.getColumnIndex("query_text")); |
||||
|
final Pair<FavoriteType, String> favoriteTypeQueryPair = Utils.migrateOldFavQuery(queryText); |
||||
|
if (favoriteTypeQueryPair == null) continue; |
||||
|
final FavoriteType type = favoriteTypeQueryPair.first; |
||||
|
final String query = favoriteTypeQueryPair.second; |
||||
|
oldModels.add(new Favorite( |
||||
|
-1, |
||||
|
query, |
||||
|
type, |
||||
|
queryDisplayExists ? cursor.getString(cursor.getColumnIndex("query_display")) |
||||
|
: null, |
||||
|
null, |
||||
|
new Date(cursor.getLong(cursor.getColumnIndex("date_added"))) |
||||
|
)); |
||||
|
} catch (Exception e) { |
||||
|
Log.e(TAG, "onUpgrade", e); |
||||
|
} |
||||
|
} while (cursor.moveToNext()); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
Log.e(TAG, "onUpgrade", e); |
||||
|
} |
||||
|
Log.d(TAG, "backupOldFavorites: oldModels:" + oldModels); |
||||
|
return oldModels; |
||||
|
} |
||||
|
|
||||
|
private static synchronized void insertOrUpdateFavorite(@NonNull final SupportSQLiteDatabase db, @NonNull final Favorite model) { |
||||
|
final ContentValues values = new ContentValues(); |
||||
|
values.put(Favorite.COL_QUERY, model.getQuery()); |
||||
|
values.put(Favorite.COL_TYPE, model.getType().toString()); |
||||
|
values.put(Favorite.COL_DISPLAY_NAME, model.getDisplayName()); |
||||
|
values.put(Favorite.COL_PIC_URL, model.getPicUrl()); |
||||
|
values.put(Favorite.COL_DATE_ADDED, model.getDateAdded().getTime()); |
||||
|
int rows; |
||||
|
if (model.getId() >= 1) { |
||||
|
rows = db.update(Favorite.TABLE_NAME, |
||||
|
SQLiteDatabase.CONFLICT_IGNORE, |
||||
|
values, |
||||
|
Favorite.COL_ID + "=?", |
||||
|
new String[]{String.valueOf(model.getId())}); |
||||
|
} else { |
||||
|
rows = db.update(Favorite.TABLE_NAME, |
||||
|
SQLiteDatabase.CONFLICT_IGNORE, |
||||
|
values, |
||||
|
Favorite.COL_QUERY + "=?" + " AND " + Favorite.COL_TYPE + "=?", |
||||
|
new String[]{model.getQuery(), model.getType().toString()}); |
||||
|
} |
||||
|
if (rows != 1) { |
||||
|
db.insert(Favorite.TABLE_NAME, SQLiteDatabase.CONFLICT_IGNORE, values); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static boolean checkColumnExists(@NonNull final SupportSQLiteDatabase db, |
||||
|
@NonNull final String tableName, |
||||
|
@NonNull final String columnName) { |
||||
|
boolean exists = false; |
||||
|
try (Cursor cursor = db.query("PRAGMA table_info(" + tableName + ")")) { |
||||
|
if (cursor.moveToFirst()) { |
||||
|
do { |
||||
|
final String currentColumn = cursor.getString(cursor.getColumnIndex("name")); |
||||
|
if (currentColumn.equals(columnName)) { |
||||
|
exists = true; |
||||
|
} |
||||
|
} while (cursor.moveToNext()); |
||||
|
|
||||
|
} |
||||
|
} catch (Exception ex) { |
||||
|
Log.e(TAG, "checkColumnExists", ex); |
||||
|
} |
||||
|
return exists; |
||||
|
} |
||||
|
} |
@ -0,0 +1,33 @@ |
|||||
|
package awais.instagrabber.db; |
||||
|
|
||||
|
import androidx.room.TypeConverter; |
||||
|
|
||||
|
import java.util.Date; |
||||
|
|
||||
|
import awais.instagrabber.models.enums.FavoriteType; |
||||
|
|
||||
|
public class Converters { |
||||
|
@TypeConverter |
||||
|
public static Date fromTimestamp(Long value) { |
||||
|
return value == null ? null : new Date(value); |
||||
|
} |
||||
|
|
||||
|
@TypeConverter |
||||
|
public static Long dateToTimestamp(Date date) { |
||||
|
return date == null ? null : date.getTime(); |
||||
|
} |
||||
|
|
||||
|
@TypeConverter |
||||
|
public static FavoriteType fromFavoriteTypeString(String value) { |
||||
|
try { |
||||
|
return FavoriteType.valueOf(value); |
||||
|
} catch (Exception e) { |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@TypeConverter |
||||
|
public static String favoriteTypeToString(FavoriteType favoriteType) { |
||||
|
return favoriteType == null ? null : favoriteType.toString(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,34 @@ |
|||||
|
package awais.instagrabber.db.dao; |
||||
|
|
||||
|
import androidx.room.Dao; |
||||
|
import androidx.room.Delete; |
||||
|
import androidx.room.Insert; |
||||
|
import androidx.room.OnConflictStrategy; |
||||
|
import androidx.room.Query; |
||||
|
import androidx.room.Update; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
import awais.instagrabber.db.entities.Account; |
||||
|
|
||||
|
@Dao |
||||
|
public interface AccountDao { |
||||
|
|
||||
|
@Query("SELECT * FROM accounts") |
||||
|
List<Account> getAllAccounts(); |
||||
|
|
||||
|
@Query("SELECT * FROM accounts WHERE uid = :uid") |
||||
|
Account findAccountByUid(String uid); |
||||
|
|
||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE) |
||||
|
List<Long> insertAccounts(Account... accounts); |
||||
|
|
||||
|
@Update |
||||
|
void updateAccounts(Account... accounts); |
||||
|
|
||||
|
@Delete |
||||
|
void deleteAccounts(Account... accounts); |
||||
|
|
||||
|
@Query("DELETE from accounts") |
||||
|
void deleteAllAccounts(); |
||||
|
} |
@ -0,0 +1,35 @@ |
|||||
|
package awais.instagrabber.db.dao; |
||||
|
|
||||
|
import androidx.room.Dao; |
||||
|
import androidx.room.Delete; |
||||
|
import androidx.room.Insert; |
||||
|
import androidx.room.OnConflictStrategy; |
||||
|
import androidx.room.Query; |
||||
|
import androidx.room.Update; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
import awais.instagrabber.db.entities.Favorite; |
||||
|
import awais.instagrabber.models.enums.FavoriteType; |
||||
|
|
||||
|
@Dao |
||||
|
public interface FavoriteDao { |
||||
|
|
||||
|
@Query("SELECT * FROM favorites") |
||||
|
List<Favorite> getAllFavorites(); |
||||
|
|
||||
|
@Query("SELECT * FROM favorites WHERE query_text = :query and type = :type") |
||||
|
Favorite findFavoriteByQueryAndType(String query, FavoriteType type); |
||||
|
|
||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE) |
||||
|
List<Long> insertFavorites(Favorite... favorites); |
||||
|
|
||||
|
@Update |
||||
|
void updateFavorites(Favorite... favorites); |
||||
|
|
||||
|
@Delete |
||||
|
void deleteFavorites(Favorite... favorites); |
||||
|
|
||||
|
@Query("DELETE from favorites") |
||||
|
void deleteAllFavorites(); |
||||
|
} |
@ -0,0 +1,68 @@ |
|||||
|
package awais.instagrabber.db.datasources; |
||||
|
|
||||
|
import android.content.Context; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
import androidx.annotation.Nullable; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
import awais.instagrabber.db.AppDatabase; |
||||
|
import awais.instagrabber.db.dao.AccountDao; |
||||
|
import awais.instagrabber.db.entities.Account; |
||||
|
|
||||
|
public class AccountDataSource { |
||||
|
private static final String TAG = AccountDataSource.class.getSimpleName(); |
||||
|
|
||||
|
private static AccountDataSource INSTANCE; |
||||
|
|
||||
|
private final AccountDao accountDao; |
||||
|
|
||||
|
private AccountDataSource(final AccountDao accountDao) { |
||||
|
this.accountDao = accountDao; |
||||
|
} |
||||
|
|
||||
|
public static AccountDataSource getInstance(@NonNull Context context) { |
||||
|
if (INSTANCE == null) { |
||||
|
synchronized (AccountDataSource.class) { |
||||
|
if (INSTANCE == null) { |
||||
|
final AppDatabase database = AppDatabase.getDatabase(context); |
||||
|
INSTANCE = new AccountDataSource(database.accountDao()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return INSTANCE; |
||||
|
} |
||||
|
|
||||
|
@Nullable |
||||
|
public final Account getAccount(final String uid) { |
||||
|
return accountDao.findAccountByUid(uid); |
||||
|
} |
||||
|
|
||||
|
@NonNull |
||||
|
public final List<Account> getAllAccounts() { |
||||
|
return accountDao.getAllAccounts(); |
||||
|
} |
||||
|
|
||||
|
public final void insertOrUpdateAccount(final String uid, |
||||
|
final String username, |
||||
|
final String cookie, |
||||
|
final String fullName, |
||||
|
final String profilePicUrl) { |
||||
|
final Account account = getAccount(uid); |
||||
|
final Account toUpdate = new Account(account == null ? 0 : account.getId(), uid, username, cookie, fullName, profilePicUrl); |
||||
|
if (account != null) { |
||||
|
accountDao.updateAccounts(toUpdate); |
||||
|
return; |
||||
|
} |
||||
|
accountDao.insertAccounts(toUpdate); |
||||
|
} |
||||
|
|
||||
|
public final void deleteAccount(@NonNull final Account account) { |
||||
|
accountDao.deleteAccounts(account); |
||||
|
} |
||||
|
|
||||
|
public final void deleteAllAccounts() { |
||||
|
accountDao.deleteAllAccounts(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,62 @@ |
|||||
|
package awais.instagrabber.db.datasources; |
||||
|
|
||||
|
import android.content.Context; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
import androidx.annotation.Nullable; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
import awais.instagrabber.db.AppDatabase; |
||||
|
import awais.instagrabber.db.dao.FavoriteDao; |
||||
|
import awais.instagrabber.db.entities.Favorite; |
||||
|
import awais.instagrabber.models.enums.FavoriteType; |
||||
|
|
||||
|
public class FavoriteDataSource { |
||||
|
private static final String TAG = FavoriteDataSource.class.getSimpleName(); |
||||
|
|
||||
|
private static FavoriteDataSource INSTANCE; |
||||
|
|
||||
|
private final FavoriteDao favoriteDao; |
||||
|
|
||||
|
private FavoriteDataSource(final FavoriteDao favoriteDao) { |
||||
|
this.favoriteDao = favoriteDao; |
||||
|
} |
||||
|
|
||||
|
public static synchronized FavoriteDataSource getInstance(@NonNull Context context) { |
||||
|
if (INSTANCE == null) { |
||||
|
synchronized (FavoriteDataSource.class) { |
||||
|
if (INSTANCE == null) { |
||||
|
final AppDatabase database = AppDatabase.getDatabase(context); |
||||
|
INSTANCE = new FavoriteDataSource(database.favoriteDao()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return INSTANCE; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@Nullable |
||||
|
public final Favorite getFavorite(@NonNull final String query, @NonNull final FavoriteType type) { |
||||
|
return favoriteDao.findFavoriteByQueryAndType(query, type); |
||||
|
} |
||||
|
|
||||
|
@NonNull |
||||
|
public final List<Favorite> getAllFavorites() { |
||||
|
return favoriteDao.getAllFavorites(); |
||||
|
} |
||||
|
|
||||
|
public final void insertOrUpdateFavorite(@NonNull final Favorite favorite) { |
||||
|
if (favorite.getId() > 0) { |
||||
|
favoriteDao.updateFavorites(favorite); |
||||
|
return; |
||||
|
} |
||||
|
favoriteDao.insertFavorites(favorite); |
||||
|
} |
||||
|
|
||||
|
public final void deleteFavorite(@NonNull final String query, @NonNull final FavoriteType type) { |
||||
|
final Favorite favorite = getFavorite(query, type); |
||||
|
if (favorite == null) return; |
||||
|
favoriteDao.deleteFavorites(favorite); |
||||
|
} |
||||
|
} |
@ -0,0 +1,124 @@ |
|||||
|
package awais.instagrabber.db.entities; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
import androidx.core.util.ObjectsCompat; |
||||
|
import androidx.room.ColumnInfo; |
||||
|
import androidx.room.Entity; |
||||
|
import androidx.room.Ignore; |
||||
|
import androidx.room.PrimaryKey; |
||||
|
|
||||
|
import awais.instagrabber.utils.Constants; |
||||
|
import awais.instagrabber.utils.TextUtils; |
||||
|
|
||||
|
@Entity(tableName = Account.TABLE_NAME) |
||||
|
public class Account { |
||||
|
public final static String TABLE_NAME = "accounts"; |
||||
|
public final static String COL_ID = "id"; |
||||
|
public final static String COL_USERNAME = Constants.EXTRAS_USERNAME; |
||||
|
public final static String COL_COOKIE = "cookie"; |
||||
|
public final static String COL_UID = "uid"; |
||||
|
public final static String COL_FULL_NAME = "full_name"; |
||||
|
public final static String COL_PROFILE_PIC = "profile_pic"; |
||||
|
|
||||
|
@PrimaryKey(autoGenerate = true) |
||||
|
@ColumnInfo(name = COL_ID) |
||||
|
private final int id; |
||||
|
|
||||
|
@ColumnInfo(name = COL_UID) |
||||
|
private final String uid; |
||||
|
|
||||
|
@ColumnInfo(name = COL_USERNAME) |
||||
|
private final String username; |
||||
|
|
||||
|
@ColumnInfo(name = COL_COOKIE) |
||||
|
private final String cookie; |
||||
|
|
||||
|
@ColumnInfo(name = COL_FULL_NAME) |
||||
|
private final String fullName; |
||||
|
|
||||
|
@ColumnInfo(name = COL_PROFILE_PIC) |
||||
|
private final String profilePic; |
||||
|
|
||||
|
@Ignore |
||||
|
private boolean selected; |
||||
|
|
||||
|
public Account(final int id, |
||||
|
final String uid, |
||||
|
final String username, |
||||
|
final String cookie, |
||||
|
final String fullName, |
||||
|
final String profilePic) { |
||||
|
this.id = id; |
||||
|
this.uid = uid; |
||||
|
this.username = username; |
||||
|
this.cookie = cookie; |
||||
|
this.fullName = fullName; |
||||
|
this.profilePic = profilePic; |
||||
|
} |
||||
|
|
||||
|
public int getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public String getUid() { |
||||
|
return uid; |
||||
|
} |
||||
|
|
||||
|
public String getUsername() { |
||||
|
return username; |
||||
|
} |
||||
|
|
||||
|
public String getCookie() { |
||||
|
return cookie; |
||||
|
} |
||||
|
|
||||
|
public String getFullName() { |
||||
|
return fullName; |
||||
|
} |
||||
|
|
||||
|
public String getProfilePic() { |
||||
|
return profilePic; |
||||
|
} |
||||
|
|
||||
|
public boolean isSelected() { |
||||
|
return selected; |
||||
|
} |
||||
|
|
||||
|
public void setSelected(final boolean selected) { |
||||
|
this.selected = selected; |
||||
|
} |
||||
|
|
||||
|
public boolean isValid() { |
||||
|
return !TextUtils.isEmpty(uid) |
||||
|
&& !TextUtils.isEmpty(username) |
||||
|
&& !TextUtils.isEmpty(cookie); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean equals(final Object o) { |
||||
|
if (this == o) return true; |
||||
|
if (o == null || getClass() != o.getClass()) return false; |
||||
|
final Account that = (Account) o; |
||||
|
return ObjectsCompat.equals(uid, that.uid) && |
||||
|
ObjectsCompat.equals(username, that.username) && |
||||
|
ObjectsCompat.equals(cookie, that.cookie); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int hashCode() { |
||||
|
return ObjectsCompat.hash(uid, username, cookie); |
||||
|
} |
||||
|
|
||||
|
@NonNull |
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return "Account{" + |
||||
|
"uid='" + uid + '\'' + |
||||
|
", username='" + username + '\'' + |
||||
|
", cookie='" + cookie + '\'' + |
||||
|
", fullName='" + fullName + '\'' + |
||||
|
", profilePic='" + profilePic + '\'' + |
||||
|
", selected=" + selected + |
||||
|
'}'; |
||||
|
} |
||||
|
} |
@ -0,0 +1,110 @@ |
|||||
|
package awais.instagrabber.db.entities; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
import androidx.core.util.ObjectsCompat; |
||||
|
import androidx.room.ColumnInfo; |
||||
|
import androidx.room.Entity; |
||||
|
import androidx.room.PrimaryKey; |
||||
|
|
||||
|
import java.util.Date; |
||||
|
|
||||
|
import awais.instagrabber.models.enums.FavoriteType; |
||||
|
|
||||
|
@Entity(tableName = Favorite.TABLE_NAME) |
||||
|
public class Favorite { |
||||
|
public final static String TABLE_NAME = "favorites"; |
||||
|
public final static String COL_ID = "id"; |
||||
|
public final static String COL_QUERY = "query_text"; |
||||
|
public final static String COL_TYPE = "type"; |
||||
|
public final static String COL_DISPLAY_NAME = "display_name"; |
||||
|
public final static String COL_PIC_URL = "pic_url"; |
||||
|
public final static String COL_DATE_ADDED = "date_added"; |
||||
|
|
||||
|
@PrimaryKey(autoGenerate = true) |
||||
|
@ColumnInfo(name = COL_ID) |
||||
|
private final int id; |
||||
|
|
||||
|
@ColumnInfo(name = COL_QUERY) |
||||
|
private final String query; |
||||
|
|
||||
|
@ColumnInfo(name = COL_TYPE) |
||||
|
private final FavoriteType type; |
||||
|
|
||||
|
@ColumnInfo(name = COL_DISPLAY_NAME) |
||||
|
private final String displayName; |
||||
|
|
||||
|
@ColumnInfo(name = COL_PIC_URL) |
||||
|
private final String picUrl; |
||||
|
|
||||
|
@ColumnInfo(name = COL_DATE_ADDED) |
||||
|
private final Date dateAdded; |
||||
|
|
||||
|
public Favorite(final int id, |
||||
|
final String query, |
||||
|
final FavoriteType type, |
||||
|
final String displayName, |
||||
|
final String picUrl, |
||||
|
final Date dateAdded) { |
||||
|
this.id = id; |
||||
|
this.query = query; |
||||
|
this.type = type; |
||||
|
this.displayName = displayName; |
||||
|
this.picUrl = picUrl; |
||||
|
this.dateAdded = dateAdded; |
||||
|
} |
||||
|
|
||||
|
public int getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public String getQuery() { |
||||
|
return query; |
||||
|
} |
||||
|
|
||||
|
public FavoriteType getType() { |
||||
|
return type; |
||||
|
} |
||||
|
|
||||
|
public String getDisplayName() { |
||||
|
return displayName; |
||||
|
} |
||||
|
|
||||
|
public String getPicUrl() { |
||||
|
return picUrl; |
||||
|
} |
||||
|
|
||||
|
public Date getDateAdded() { |
||||
|
return dateAdded; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean equals(final Object o) { |
||||
|
if (this == o) return true; |
||||
|
if (o == null || getClass() != o.getClass()) return false; |
||||
|
final Favorite that = (Favorite) o; |
||||
|
return id == that.id && |
||||
|
ObjectsCompat.equals(query, that.query) && |
||||
|
type == that.type && |
||||
|
ObjectsCompat.equals(displayName, that.displayName) && |
||||
|
ObjectsCompat.equals(picUrl, that.picUrl) && |
||||
|
ObjectsCompat.equals(dateAdded, that.dateAdded); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int hashCode() { |
||||
|
return ObjectsCompat.hash(id, query, type, displayName, picUrl, dateAdded); |
||||
|
} |
||||
|
|
||||
|
@NonNull |
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return "FavoriteModel{" + |
||||
|
"id=" + id + |
||||
|
", query='" + query + '\'' + |
||||
|
", type=" + type + |
||||
|
", displayName='" + displayName + '\'' + |
||||
|
", picUrl='" + picUrl + '\'' + |
||||
|
", dateAdded=" + dateAdded + |
||||
|
'}'; |
||||
|
} |
||||
|
} |
@ -0,0 +1,131 @@ |
|||||
|
package awais.instagrabber.db.repositories; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
import awais.instagrabber.db.datasources.AccountDataSource; |
||||
|
import awais.instagrabber.db.entities.Account; |
||||
|
import awais.instagrabber.utils.AppExecutors; |
||||
|
|
||||
|
public class AccountRepository { |
||||
|
private static final String TAG = AccountRepository.class.getSimpleName(); |
||||
|
|
||||
|
private static AccountRepository instance; |
||||
|
|
||||
|
private final AppExecutors appExecutors; |
||||
|
private final AccountDataSource accountDataSource; |
||||
|
|
||||
|
// private List<Account> cachedAccounts; |
||||
|
|
||||
|
private AccountRepository(final AppExecutors appExecutors, final AccountDataSource accountDataSource) { |
||||
|
this.appExecutors = appExecutors; |
||||
|
this.accountDataSource = accountDataSource; |
||||
|
} |
||||
|
|
||||
|
public static AccountRepository getInstance(final AccountDataSource accountDataSource) { |
||||
|
if (instance == null) { |
||||
|
instance = new AccountRepository(AppExecutors.getInstance(), accountDataSource); |
||||
|
} |
||||
|
return instance; |
||||
|
} |
||||
|
|
||||
|
public void getAccount(final String uid, |
||||
|
final RepositoryCallback<Account> callback) { |
||||
|
// request on the I/O thread |
||||
|
appExecutors.diskIO().execute(() -> { |
||||
|
final Account account = accountDataSource.getAccount(uid); |
||||
|
// notify on the main thread |
||||
|
appExecutors.mainThread().execute(() -> { |
||||
|
if (callback == null) return; |
||||
|
if (account == null) { |
||||
|
callback.onDataNotAvailable(); |
||||
|
return; |
||||
|
} |
||||
|
callback.onSuccess(account); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public void getAllAccounts(final RepositoryCallback<List<Account>> callback) { |
||||
|
// request on the I/O thread |
||||
|
appExecutors.diskIO().execute(() -> { |
||||
|
final List<Account> accounts = accountDataSource.getAllAccounts(); |
||||
|
// notify on the main thread |
||||
|
appExecutors.mainThread().execute(() -> { |
||||
|
if (callback == null) return; |
||||
|
if (accounts == null) { |
||||
|
callback.onDataNotAvailable(); |
||||
|
return; |
||||
|
} |
||||
|
// cachedAccounts = accounts; |
||||
|
callback.onSuccess(accounts); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public void insertOrUpdateAccounts(final List<Account> accounts, |
||||
|
final RepositoryCallback<Void> callback) { |
||||
|
// request on the I/O thread |
||||
|
appExecutors.diskIO().execute(() -> { |
||||
|
for (final Account account : accounts) { |
||||
|
accountDataSource.insertOrUpdateAccount(account.getUid(), |
||||
|
account.getUsername(), |
||||
|
account.getCookie(), |
||||
|
account.getFullName(), |
||||
|
account.getProfilePic()); |
||||
|
} |
||||
|
// notify on the main thread |
||||
|
appExecutors.mainThread().execute(() -> { |
||||
|
if (callback == null) return; |
||||
|
callback.onSuccess(null); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public void insertOrUpdateAccount(final String uid, |
||||
|
final String username, |
||||
|
final String cookie, |
||||
|
final String fullName, |
||||
|
final String profilePicUrl, |
||||
|
final RepositoryCallback<Account> callback) { |
||||
|
// request on the I/O thread |
||||
|
appExecutors.diskIO().execute(() -> { |
||||
|
accountDataSource.insertOrUpdateAccount(uid, username, cookie, fullName, profilePicUrl); |
||||
|
final Account updated = accountDataSource.getAccount(uid); |
||||
|
// notify on the main thread |
||||
|
appExecutors.mainThread().execute(() -> { |
||||
|
if (callback == null) return; |
||||
|
if (updated == null) { |
||||
|
callback.onDataNotAvailable(); |
||||
|
return; |
||||
|
} |
||||
|
callback.onSuccess(updated); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public void deleteAccount(final Account account, |
||||
|
final RepositoryCallback<Void> callback) { |
||||
|
// request on the I/O thread |
||||
|
appExecutors.diskIO().execute(() -> { |
||||
|
accountDataSource.deleteAccount(account); |
||||
|
// notify on the main thread |
||||
|
appExecutors.mainThread().execute(() -> { |
||||
|
if (callback == null) return; |
||||
|
callback.onSuccess(null); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public void deleteAllAccounts(final RepositoryCallback<Void> callback) { |
||||
|
// request on the I/O thread |
||||
|
appExecutors.diskIO().execute(() -> { |
||||
|
accountDataSource.deleteAllAccounts(); |
||||
|
// notify on the main thread |
||||
|
appExecutors.mainThread().execute(() -> { |
||||
|
if (callback == null) return; |
||||
|
callback.onSuccess(null); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,88 @@ |
|||||
|
package awais.instagrabber.db.repositories; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
import awais.instagrabber.db.datasources.FavoriteDataSource; |
||||
|
import awais.instagrabber.db.entities.Favorite; |
||||
|
import awais.instagrabber.models.enums.FavoriteType; |
||||
|
import awais.instagrabber.utils.AppExecutors; |
||||
|
|
||||
|
public class FavoriteRepository { |
||||
|
private static final String TAG = FavoriteRepository.class.getSimpleName(); |
||||
|
|
||||
|
private static FavoriteRepository instance; |
||||
|
|
||||
|
private final AppExecutors appExecutors; |
||||
|
private final FavoriteDataSource favoriteDataSource; |
||||
|
|
||||
|
private FavoriteRepository(final AppExecutors appExecutors, final FavoriteDataSource favoriteDataSource) { |
||||
|
this.appExecutors = appExecutors; |
||||
|
this.favoriteDataSource = favoriteDataSource; |
||||
|
} |
||||
|
|
||||
|
public static FavoriteRepository getInstance(final FavoriteDataSource favoriteDataSource) { |
||||
|
if (instance == null) { |
||||
|
instance = new FavoriteRepository(AppExecutors.getInstance(), favoriteDataSource); |
||||
|
} |
||||
|
return instance; |
||||
|
} |
||||
|
|
||||
|
public void getFavorite(final String query, final FavoriteType type, final RepositoryCallback<Favorite> callback) { |
||||
|
// request on the I/O thread |
||||
|
appExecutors.diskIO().execute(() -> { |
||||
|
final Favorite favorite = favoriteDataSource.getFavorite(query, type); |
||||
|
// notify on the main thread |
||||
|
appExecutors.mainThread().execute(() -> { |
||||
|
if (callback == null) return; |
||||
|
if (favorite == null) { |
||||
|
callback.onDataNotAvailable(); |
||||
|
return; |
||||
|
} |
||||
|
callback.onSuccess(favorite); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public void getAllFavorites(final RepositoryCallback<List<Favorite>> callback) { |
||||
|
// request on the I/O thread |
||||
|
appExecutors.diskIO().execute(() -> { |
||||
|
final List<Favorite> favorites = favoriteDataSource.getAllFavorites(); |
||||
|
// notify on the main thread |
||||
|
appExecutors.mainThread().execute(() -> { |
||||
|
if (callback == null) return; |
||||
|
if (favorites == null) { |
||||
|
callback.onDataNotAvailable(); |
||||
|
return; |
||||
|
} |
||||
|
callback.onSuccess(favorites); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public void insertOrUpdateFavorite(final Favorite favorite, |
||||
|
final RepositoryCallback<Void> callback) { |
||||
|
// request on the I/O thread |
||||
|
appExecutors.diskIO().execute(() -> { |
||||
|
favoriteDataSource.insertOrUpdateFavorite(favorite); |
||||
|
// notify on the main thread |
||||
|
appExecutors.mainThread().execute(() -> { |
||||
|
if (callback == null) return; |
||||
|
callback.onSuccess(null); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public void deleteFavorite(final String query, |
||||
|
final FavoriteType type, |
||||
|
final RepositoryCallback<Void> callback) { |
||||
|
// request on the I/O thread |
||||
|
appExecutors.diskIO().execute(() -> { |
||||
|
favoriteDataSource.deleteFavorite(query, type); |
||||
|
// notify on the main thread |
||||
|
appExecutors.mainThread().execute(() -> { |
||||
|
if (callback == null) return; |
||||
|
callback.onSuccess(null); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
package awais.instagrabber.db.repositories; |
||||
|
|
||||
|
import androidx.annotation.MainThread; |
||||
|
|
||||
|
public interface RepositoryCallback<T> { |
||||
|
@MainThread |
||||
|
void onSuccess(T result); |
||||
|
|
||||
|
@MainThread |
||||
|
void onDataNotAvailable(); |
||||
|
} |
@ -0,0 +1,98 @@ |
|||||
|
/* |
||||
|
* Copyright (C) 2017 The Android Open Source Project |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
|
||||
|
package awais.instagrabber.utils; |
||||
|
|
||||
|
import android.os.Handler; |
||||
|
import android.os.Looper; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
|
||||
|
import com.google.common.util.concurrent.ListeningExecutorService; |
||||
|
import com.google.common.util.concurrent.MoreExecutors; |
||||
|
|
||||
|
import java.util.concurrent.Executor; |
||||
|
import java.util.concurrent.Executors; |
||||
|
|
||||
|
/** |
||||
|
* Global executor pools for the whole application. |
||||
|
* <p> |
||||
|
* Grouping tasks like this avoids the effects of task starvation (e.g. disk reads don't wait behind |
||||
|
* webservice requests). |
||||
|
*/ |
||||
|
public class AppExecutors { |
||||
|
|
||||
|
private static final int THREAD_COUNT = 3; |
||||
|
private static final Object LOCK = new Object(); |
||||
|
|
||||
|
private static AppExecutors instance; |
||||
|
|
||||
|
private final Executor diskIO; |
||||
|
private final Executor networkIO; |
||||
|
private final Executor mainThread; |
||||
|
private final ListeningExecutorService tasksThread; |
||||
|
|
||||
|
private AppExecutors(Executor diskIO, |
||||
|
Executor networkIO, |
||||
|
Executor mainThread, |
||||
|
ListeningExecutorService tasksThread) { |
||||
|
this.diskIO = diskIO; |
||||
|
this.networkIO = networkIO; |
||||
|
this.mainThread = mainThread; |
||||
|
this.tasksThread = tasksThread; |
||||
|
} |
||||
|
|
||||
|
public static AppExecutors getInstance() { |
||||
|
if (instance == null) { |
||||
|
synchronized (LOCK) { |
||||
|
if (instance == null) { |
||||
|
instance = new AppExecutors(Executors.newSingleThreadExecutor(), |
||||
|
Executors.newFixedThreadPool(THREAD_COUNT), |
||||
|
new MainThreadExecutor(), |
||||
|
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10))); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return instance; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public Executor diskIO() { |
||||
|
return diskIO; |
||||
|
} |
||||
|
|
||||
|
public Executor networkIO() { |
||||
|
return networkIO; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public ListeningExecutorService tasksThread() { |
||||
|
return tasksThread; |
||||
|
} |
||||
|
|
||||
|
public Executor mainThread() { |
||||
|
return mainThread; |
||||
|
} |
||||
|
|
||||
|
private static class MainThreadExecutor implements Executor { |
||||
|
private final Handler mainThreadHandler = new Handler(Looper.getMainLooper()); |
||||
|
|
||||
|
@Override |
||||
|
public void execute(@NonNull Runnable command) { |
||||
|
mainThreadHandler.post(command); |
||||
|
} |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue