有没有办法强制实现LiveData值的不可空性?默认的Observer实现似乎有@Nullable注释,它强制IDE建议该值可能为null并且应该手动检查:
public interface Observer<T> {
/**
* Called when the data is changed.
* @param t The new data
*/
void onChanged(@Nullable T t);
}
Run Code Online (Sandbox Code Playgroud) 当我尝试为Room Db和Retrofit 实现NetworkBoundResource和Resource帮助类时,它完美无缺.但是,我需要在没有Room的情况下使用Retrofit实现RESTful的搜索结果.这Resources堂课很好,我不需要改变它.我想要做的是尝试删除此类中的数据库源.
public abstract class NetworkBoundResource<ResultType, RequestType> {
private final AppExecutors appExecutors;
private final MediatorLiveData<Resource<ResultType>> result = new MediatorLiveData<>();
@MainThread
public NetworkBoundResource(AppExecutors appExecutors) {
this.appExecutors = appExecutors;
result.setValue(Resource.loading(null));
LiveData<ResultType> dbSource = loadFromDb();
result.addSource(dbSource, data -> {
result.removeSource(dbSource);
if (shouldFetch(data)) {
fetchFromNetwork(dbSource);
} else {
result.addSource(dbSource, newData -> setValue(Resource.success(newData)));
}
});
}
@MainThread
private void setValue(Resource<ResultType> newValue) {
if (!Objects.equals(result.getValue(), newValue)) {
result.setValue(newValue);
}
}
private void fetchFromNetwork(final LiveData<ResultType> dbSource) …Run Code Online (Sandbox Code Playgroud) 我正在寻找一种方法来初始化ViewModel中的LiveData对象.当前只有在从活动调用setQuery方法时才会初始化项目.
public class MyListViewModel extends AndroidViewModel {
private final LiveData <List<Item>> items;
private final MutableLiveData<String> query = new MutableLiveData<>();
private MyDatabase db;
public MyListViewModel(Application application) {
super(application);
db = MyDatabase.getInstance(application);
items = Transformations.switchMap(query, (search)->{
if (search == null || search.trim().length() == 0) {
return db.itemDao().getAllItems();
} else {
return db.itemDao().findItemsBySearchTerm(search);
}
});
}
public LiveData<List<Item>> getItems() {
return items;
}
public void setQuery(String queryText) {
query.setValue(queryText);
}
Run Code Online (Sandbox Code Playgroud)
}
目前,我们正在使用LiveData,ViewModel并Room在我们的项目。
我们正在使用Java 8。
我们在下面使用 build.gradle
// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:1.1.1"
// Room (use 1.1.0-beta1 for latest beta)
implementation "android.arch.persistence.room:runtime:1.0.0"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0"
Run Code Online (Sandbox Code Playgroud)
我想知道我们什么时候需要使用
annotationProcessor "android.arch.lifecycle:compiler:1.1.1"
Run Code Online (Sandbox Code Playgroud)
(或者implementation "android.arch.lifecycle:common-java8:1.1.1"因为我们正在使用Java 8 ?!)
目前,我们的代码可以正常运行,而无需使用lifecycle:compiler或lifecycle:common-java8。
如您所知,我们可以使用attach命令从多个数据库中选择,如下所示:
String path = DBHelper.getDatabasePath(context);
String sql = "ATTACH DATABASE '" + path + "/" + dbname.toString()
+ ".db' AS \"" + dbname.toString() + "\";";
db.execSQL(sql);
Run Code Online (Sandbox Code Playgroud)
然后通过使用Cursor,我们可以从中进行选择.
通过使用Android Room,我该怎么做?是否有任何附件或类似命令来执行此操作?
java sqlite android android-room android-architecture-components
我有下一个用例:用户登录表格,输入姓名,电子邮件和密码,点击注册按钮.之后系统需要检查电子邮件是否被采用并基于该显示错误消息或创建新用户...
我试图使用Room,ViewModel和LiveData来做到这一点.这是我尝试学习这些组件的一些项目,我没有远程api,我会将所有内容存储在本地数据库中
所以我有这些课程:
所以我的想法是将有一个监听器附加到注册按钮,它将调用RegisterViewModel::register()方法.
class RegisterViewModel extends ViewModel {
//...
public void register() {
validationErrorMessage.setValue(null);
if(!validateInput())
return;
registrationService.performRegistration(name.get(), email.get(), password.get());
}
//...
}
Run Code Online (Sandbox Code Playgroud)
所以这是基本的想法,我也想performRegistration回到我新建的用户.
最困扰我的是我不知道如何performRegistration在服务中实现功能
class UsersRegistrationService {
private UsersRepository usersRepo;
//...
public LiveData<RegistrationResponse<Parent>> performRegistration(String name, String email, String password) {
// 1. check if email exists using repository
// 2. if user exists return RegistrationResponse.error("Email is taken")
// 3. if user does not exists create new user …Run Code Online (Sandbox Code Playgroud) android observer-pattern android-room android-livedata android-architecture-components
我在一个片段里面使用childFragmentManager或在一个Activity 里面显示一个对话框supportFragmentManager,在这个过程中我想设置目标片段,如下所示:
val textSearchDialog = TextSearchDialogFragment.newInstance()
textSearchDialog.setTargetFragment(PlaceSearchFragment@this, 0)
Run Code Online (Sandbox Code Playgroud)
但是当运行该代码时,我得到错误:
java.lang.IllegalStateException:Fragment TextSearchDialogFragment {b7fce67#0 0}声明的目标片段PlaceSearchFragment {f87414#0 id = 0x7f080078}不属于此FragmentManager!
我不知道如何访问FragmentManager导航组件正在使用来管理片段的显示,有没有解决方案呢?
android kotlin android-navigation android-architecture-components android-architecture-navigation
我们来看一个基本的例子
用于存储用户的表
@Entity (tableName="users")
class UsersEntity(
@PrimaryKey val id
var name:String,
...
)
Run Code Online (Sandbox Code Playgroud)
用于存储角色的表
@Entity (tableName="roles")
class RolesEntity(
@PrimaryKey val id
var name:String,
...
)
Run Code Online (Sandbox Code Playgroud)
用于存储用户和角色之间的多对多关系的表
@Entity (tableName="roles")
class UserRoles(
@PrimaryKey val id
var userId:String,
var roleId:String
)
Run Code Online (Sandbox Code Playgroud)
我在视图中需要的pojo类
class user(
var id:String,
var name:String,
.... other fields
var roles: List<Role>
)
Run Code Online (Sandbox Code Playgroud)
在我,我ViewModel怎么能把user结果传递给LiveData已经List<Role>填满?
从一般方面来看,我可以:
UserDao.getUserById(id)返回LiveData从用户表,并RoleDao.getRolesForUserId(id)返回LiveData与用户的角色列表.然后在我的片段,我所能做的viewModel.getUserById().observe{}和viewModel.getRolesForUserId().observe{}.但这基本上意味着拥有2名观察员,而且我非常有信心这不是可行的方法.MediatorLiveData android-room android-livedata android-viewmodel android-architecture-components android-jetpack
我有以下代码 Activity
@Override
public void onPause() {
super.onPause();
if (isFinishing()) {
final LiveData<StickyNoteConfig> stickyNoteConfigLiveData = StickyNoteConfigRepository.INSTANCE.getStickyNoteConfig(mAppWidgetId);
stickyNoteConfigLiveData.removeObservers(this);
stickyNoteConfigLiveData.observe(this, stickyNoteConfig -> {
// Weird, I still can receive call back.
// I thought "this" is no longer active?
});
}
}
Run Code Online (Sandbox Code Playgroud)
我感到困惑的Observer是,虽然this活动已经处于onPause状态,但仍然被触发了?根据https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.State#STARTED
为LifecycleOwner启动状态.对于活动,在两种情况下达到此状态:
Run Code Online (Sandbox Code Playgroud)after onStart call; right before onPause call.
我可以知道为什么会这样吗?
我正在使用Room并实现了Dao,它返回了LiveData。添加下面的依赖关系,它工作正常。
implementation "androidx.room:room-runtime:2.1.0-alpha04"
kapt "androidx.room:room-compiler:2.1.0-alpha04"
Run Code Online (Sandbox Code Playgroud)
但是,当我添加新的Room协程依赖性时,如下所述。
implementation "androidx.room:room-runtime:2.1.0-alpha04"
implementation "androidx.room:room-coroutines:2.1.0-alpha04"
kapt "androidx.room:room-compiler:2.1.0-alpha04"
Run Code Online (Sandbox Code Playgroud)
下面是编译的代码
@Dao
interface AccountDao{
@Query("SELECT * FROM account_master")
suspend fun getAllAccounts(): List<Account>
}
Run Code Online (Sandbox Code Playgroud)
下面是给出错误的代码。
@Dao
interface AccountDao{
@Query("SELECT * FROM account_master")
suspend fun getAllAccounts(): LiveData<List<Account>>
}
Run Code Online (Sandbox Code Playgroud)
开始收到错误。
PlayGround/app/build/tmp/kapt3/stubs/debug/com/playground/www/x/datasource/dao/AccountDao.java:11: error: Not sure how to convert a Cursor to this method's return type (androidx.lifecycle.LiveData<java.util.List<com.playground.www.x.datasource.entity.Account>>).
public abstract java.lang.Object getAllAccounts(@org.jetbrains.annotations.NotNull()
Run Code Online (Sandbox Code Playgroud)
有人面临类似问题吗?
android android-room android-architecture-components kotlin-coroutines
android-architecture-components ×10
android ×9
android-room ×4
android-architecture-navigation ×1
java ×1
kotlin ×1
sqlite ×1