我有一个小部件,每次更新数据库时都想更新,并且即使应用程序未运行,也希望在小部件上显示数据库中的内容。
我的db
是使用Room
实现的,而小部件是使用
IntentService
。每次进行更新时,onHandleIntent
都会尝试从数据库中获取新条目并更新小部件。
但是对于下面的代码,它总是从数据库中返回空List
是否有实现此目的的替代方法? AsyncTask
在这里不起作用,因为它需要在主线程上执行。
我是Room
和RxJava
的新手,所以不确定我是否错过任何明显的事情。
@Override
protected void onHandleIntent(@Nullable Intent intent) {
if (intent == null || intent.getAction() == null) return;
if (intent.getAction().equals(UPDATE_WIDGET)) {
Context context = getApplicationContext();
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(this, ParkWidgetProvider.class));
Observable.fromCallable(() -> {
db = FavDatabase.getInstance(context);
return db;
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
List<FavParkEntity> favParkEntityList = result.favDoa().getFavPark().getValue();
if (favParkEntityList != null) {
if (favParkEntityList.size() == 1) {
FavParkEntity favParkEntity = favParkEntityList.get(0);
latLong = favParkEntity.getLatLong();
parkCode = favParkEntity.getParkCode();
imgUrl = favParkEntity.getImage();
title = favParkEntity.getPark_name();
Log.e(TAG, "onHandleIntent: HERE: " + title);
StringToGPSCoordinates stringToGPSCoordinates = new StringToGPSCoordinates();
final String gpsCoodinates[] = stringToGPSCoordinates.convertToGPS(latLong);
getLastLocation(gpsCoodinates);
String weatherDetails[] = getCurrentWeather(context, gpsCoodinates);
ParkWidgetProvider.updateAppWidgets(context, appWidgetManager, appWidgetIds, parkCode, imgUrl, title, weatherDetails, distance);
} else {
Log.e(TAG, "onHandleIntent: HERE SIZE");
}
} else {
Log.e(TAG, "onHandleIntent: HERE NULL");
}
});
}
}
数据库:
@Database(entities = {FavParkEntity.class},version = 1, exportSchema = false)
@TypeConverters({Converters.class})
public abstract class FavDatabase extends RoomDatabase {
public static final String DATABASE_NAME = "favorites";
private static final Object LOCK = new Object();
private static FavDatabase sInstance;
public static FavDatabase getInstance(Context context){
if(sInstance==null){
synchronized (LOCK){
sInstance = Room.databaseBuilder(context.getApplicationContext(),FavDatabase.class, FavDatabase.DATABASE_NAME)
.build();
}
}
return sInstance;
}
public RoomDatabase dbExist(){
return sInstance;
}
public abstract FavDao favDoa();
}
道:
@Dao
public interface FavDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void save(FavParkEntity park);
@Query("SELECT * FROM favorites")
LiveData<List<FavParkEntity>> getFavPark();
@Query("DELETE FROM favorites")
void clearTable();
}
型号:
@Entity(tableName = "favorites")
public class FavParkEntity extends ParkEntity {
public FavParkEntity() {
}
public FavParkEntity (ParkEntity parkEntity){
this.setPark_id(parkEntity.getPark_id());
this.setPark_name(parkEntity.getPark_name());
this.setStates(parkEntity.getStates());
this.setParkCode(parkEntity.getParkCode());
this.setLatLong(parkEntity.getLatLong());
this.setDescription(parkEntity.getDescription());
this.setDesignation(parkEntity.getDesignation());
this.setAddress(parkEntity.getAddress());
this.setPhone(parkEntity.getPhone());
this.setEmail(parkEntity.getEmail());
this.setImage(parkEntity.getImage());
}
}
答案 0 :(得分:1)
实施中有很多问题。
首先,result.favDoa().getFavPark().getValue()
将始终返回null,因为LiveData
是异步的。 LiveData
是要遵守的。
使用RxJava
的方式似乎也不正确。您没有异步完成任何实际工作。可以完全不使用RxJava
来编写该实现。
还要注意,没有一种简单的方法可以将LiveData
和RxJava
一起使用,因为它们不能直接互换。人们喜欢使用“完整LiveData
”,“完整RxJava
”或“ RxJava
”,直到UI组件然后切换到LiveData
。
有很多解决方法。一种选择是将您的实现完全更改为RxJava。 (房间具有RxJava支持:https://developer.android.com/topic/libraries/architecture/adding-components#room)
道:
@Dao
public interface FavDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void save(FavParkEntity park);
@Query("SELECT * FROM favorites")
Single<List<FavParkEntity>> getFavPark(); // Switch to RxJava
@Query("DELETE FROM favorites")
void clearTable();
}
您的主要代码:
@Override
protected void onHandleIntent(@Nullable Intent intent) {
if (intent == null || intent.getAction() == null) return;
if (intent.getAction().equals(UPDATE_WIDGET)) {
Context context = getApplicationContext();
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(this, ParkWidgetProvider.class));
FavDatabase.getInstance(context).favDoa().getFavPark() // Access database here.
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(favParkEntityList -> {
// Put your mainThread works here.
if (favParkEntityList != null) {
if (favParkEntityList.size() == 1) {
FavParkEntity favParkEntity = favParkEntityList.get(0);
latLong = favParkEntity.getLatLong();
parkCode = favParkEntity.getParkCode();
imgUrl = favParkEntity.getImage();
title = favParkEntity.getPark_name();
Log.e(TAG, "onHandleIntent: HERE: " + title);
...
} else {
Log.e(TAG, "onHandleIntent: HERE SIZE");
}
} else {
Log.e(TAG, "onHandleIntent: HERE NULL");
}
});
}
}
(可选)如果无法将Dao从LiveData
切换到RxJava
,则可以创建getFavPark()
的同步版本。
道:
@Dao
public interface FavDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void save(FavParkEntity park);
@Query("SELECT * FROM favorites")
LiveData<List<FavParkEntity>> getFavPark();
@Query("SELECT * FROM favorites")
List<FavParkEntity> getFavParkSync(); // Synchronous access
@Query("DELETE FROM favorites")
void clearTable();
}
您的主要代码:
@Override
protected void onHandleIntent(@Nullable Intent intent) {
if (intent == null || intent.getAction() == null) return;
if (intent.getAction().equals(UPDATE_WIDGET)) {
Context context = getApplicationContext();
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(this, ParkWidgetProvider.class));
Observable.fromCallable(() -> {
// fromCallable and subscribeOn will make
// below code run in a worker thread asynchronously.
return FavDatabase.getInstance(context).favDoa().getFavParkSync();
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(favParkEntityList -> {
// Put your mainThread works here.
if (favParkEntityList != null) {
if (favParkEntityList.size() == 1) {
FavParkEntity favParkEntity = favParkEntityList.get(0);
latLong = favParkEntity.getLatLong();
parkCode = favParkEntity.getParkCode();
imgUrl = favParkEntity.getImage();
title = favParkEntity.getPark_name();
Log.e(TAG, "onHandleIntent: HERE: " + title);
...
} else {
Log.e(TAG, "onHandleIntent: HERE SIZE");
}
} else {
Log.e(TAG, "onHandleIntent: HERE NULL");
}
});
}
}