我将用户信息存储在本地房间数据库中。在活动和片段中,我使用AndroidViewModel和LiveData来监听对数据库所做的更改并更新UI。
现在,我想分析所有过去的用户数据,为将来的决策提供建议。我的建议会随着用户对数据库的每次更改而改变,因此我需要经常更新我的推荐,同时反复进行相同的计算。
我正在考虑在应用启动时启动服务,通过ViewModel和LiveData监听数据库更改并更新我的推荐(也存储在同一个数据库中)。但不知何故,服务不能
viewModel = ViewModelProviders.of(this).get(DataViewModel.class);
基本上我只需要读取数据库中的所有条目,分析数据并在每次数据库内容更改时更新5-10个值。
如果不在服务中,我应该如何以及在何处进行计算?也许我陷入了错误的想法,服务不是正确的方式,所以非常感谢任何有关如何做到这一点的想法!
答案 0 :(得分:3)
观察LiveData对象,因为它不是LifecycleOwner
在observeForever()
上使用LiveData
,并在适当时通过removeObserver()
手动注销(服务onDestroy()
,如果不早的话)。
请记住,此处适用标准服务限制(例如,除非它们是前台服务,否则它们在Android 8.0+上运行约1分钟),因此您可能仍然需要考虑其他方法。
答案 1 :(得分:1)
我最终使用了Service并按如下方式解决了我的问题:
在我的onCreate
的{{1}}方法中,将Application object
绑定到它:
MyService
将服务绑定到应用程序上下文应该使该服务保持活动状态,只要该应用程序没有被破坏即可。在serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder iBinder) {
service = ((MyService.MyLocalBinder) iBinder ).getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
Intent intent = new Intent(this, MyService.class);
getApplicationContext().bindService(intent, serviceConnection, BIND_AUTO_CREATE);
中,我通过MyService
获得了ViewModel的实例
AndroidViewModelFactory
我可以像这样通过MyViewModel myViewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication()).create(MyViewModel.class);
观察从ViewModel获取的LiveData
observeForever
重要:从服务Observer<List<Entry>> obsEntries = new Observer<List<Entry>>() {
@Override
public void onChanged(@Nullable List<Entry> entries) {
//perform calculations with entries in here
}
};
viewModel.getEntries().observeForever(obsEntries);
中的LiveData引用中删除观察者(这就是为什么我对Observer对象保留本地引用的原因):
onDestroy
谢谢大家!
答案 2 :(得分:1)
实体没有任何变化。
在DAO中,例如
@Dao
public interface TimeDao {
// ...
// ...
// for a started Service using startService() in background
@Query("select * from times where name = :bName")
List<TimeEntity> getServiceTimes(String bName);
}
不是 LiveData
在数据库中,例如
@Database(entities = {DataEntity.class, TimeEntity.class}, version = 1)
public abstract class BrRoomDatabase extends RoomDatabase {
public abstract TimeDao iTimeDao();
public static BrRoomDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
// ...
}
return INSTANCE;
}
}
接口类
public interface SyncServiceSupport {
List<TimeEntity> getTimesEntities(String brName);
}
一个实现类。
public class SyncServiceSupportImpl implements SyncServiceSupport {
private TimeDao timeDao;
public SyncServiceSupportImpl(Context context) {
timeDao = BrRoomDatabase.getDatabase(context).iTimeDao();
// getDatabase() from where we get DB instance.
// .. and ..
// public abstract TimeDao iTimeDao(); <= defined abstract type in RoomDatabase abstract class
}
@Override
public List<TimeEntity> getTimesEntities(String name) {
return timeDao.getServiceTimes(name);
}
}
最后……在服务中。
public class SyncService extends Service {
//..
// now, iEntities will have a List of TimeEntity objects from DB ..
// .. retrieved using @Query
private static List<TimeEntity> iEntities = new ArrayList<>();
private static SyncServiceSupportImpl iSyncService;
private static void getFromDB(String brName) {
new AsyncTask<String, Void, Void>() {
@Override
protected Void doInBackground(String... params) {
iEntities = iSyncService.getTimesEntities(params[0]);
return null;
}
@Override
protected void onPostExecute(Void agentsCount) {
}
}.execute(brName);
}
@Override
public void onCreate() {
super.onCreate();
//init service
iSyncService = new SyncServiceSupportImpl(SyncService.this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// this can be elsewhere also !..
getFromDB(myName);
}
}