当我按下Android Studio中的播放按钮时,我的应用程序会编译,但会显示此错误(编辑):
错误:程序类型已存在:android.arch.lifecycle.LiveData
我试过删除.gradle文件夹,然后去Build > Clean Project和Build > Rebuild Project.但是,它不起作用.我也尝试删除源代码,然后再次克隆git并将文件夹导入Android Studio.但是,它仍会产生该错误.
这是我的应用程序app/build.gradle:
Error:Program type already present: android.arch.lifecycle.LiveData
Run Code Online (Sandbox Code Playgroud) android android-studio android-gradle-plugin android-livedata
observeAsState将 Jetpack Compose 升级到 1.0.0?beta07 后,在 LiveData 对象上运行时出现以下错误。
java.lang.NoSuchMethodError: No interface method startReplaceableGroup(ILjava/lang/String;)V in class Landroidx/compose/runtime/Composer; or its super classes
Run Code Online (Sandbox Code Playgroud)
文档说升级时会出现错误,为了解决它,必须重新编译依赖于 Compose 的库。
我不知道必须这样做。我尝试再次制作该项目,也无济于事地清除和重建它。
这是我项目中的依赖项:
dependencies {
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.ui:ui-tooling:$compose_version"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha01'
implementation 'androidx.activity:activity-compose:1.3.0-alpha07'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
implementation "io.github.vanpra.compose-material-dialogs:datetime:0.4.0"
implementation "io.github.vanpra.compose-material-dialogs:datetime:0.4.0"
implementation "androidx.appcompat:appcompat:$appCompatVersion"
implementation "androidx.activity:activity-ktx:$activityVersion"
implementation "androidx.room:room-ktx:$roomVersion"
kapt "androidx.room:room-compiler:$roomVersion"
androidTestImplementation "androidx.room:room-testing:$roomVersion"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVersion"
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.30"
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines"
api …Run Code Online (Sandbox Code Playgroud) Java POJO对象
public class Section {
@ColumnInfo(name="section_id")
public int mSectionId;
@ColumnInfo(name="section_name")
public String mSectionName;
public int getSectionId() {
return mSectionId;
}
public void setSectionId(int mSectionId) {
this.mSectionId = mSectionId;
}
public String getSectionName() {
return mSectionName;
}
public void setSectionName(String mSectionName) {
this.mSectionName = mSectionName;
}
}
Run Code Online (Sandbox Code Playgroud)
我的查询方法
@Query("SELECT * FROM section")
LiveData<List<Section>> getAllSections();
Run Code Online (Sandbox Code Playgroud)
访问数据库
final LiveData<List<Section>> sections = mDb.sectionDAO().getAllSections();
Run Code Online (Sandbox Code Playgroud)
在下一行,我正在检查sections.getValue()哪个总是给我null,虽然我在DataBase中有数据,后来我得到了onChanged()方法中的值.
sections.observe(this, new Observer<List<Section>>() {
@Override
public void onChanged(@Nullable List<Section> sections){
}
});
Run Code Online (Sandbox Code Playgroud)
但是当我从查询中省略LiveData时,我正在按预期获取数据.查询方法:
@Query("SELECT * …Run Code Online (Sandbox Code Playgroud) android android-room android-livedata android-architecture-components
在上一次 Google I/O 大会上,Jose Alcerreca 和 Yigit Boyar告诉我们,我们不应再使用 LiveData 来获取数据。现在我们应该使用挂起函数进行一次性提取并使用 Kotlin 的 Flow 创建数据流。我同意协程非常适合一次性获取或其他 CRUD 操作,例如插入等。但是在我需要数据流的情况下,我不明白 Flow 给我带来了什么优势。在我看来,LiveData 也在做同样的事情。
流程示例:
视图模型
val items = repository.fetchItems().asLiveData()
Run Code Online (Sandbox Code Playgroud)
存储库
fun fetchItems() = itemDao.getItems()
Run Code Online (Sandbox Code Playgroud)
道
@Query("SELECT * FROM item")
fun getItems(): Flow<List<Item>>
Run Code Online (Sandbox Code Playgroud)
LiveData 示例:
视图模型
val items = repository.fetchItems()
Run Code Online (Sandbox Code Playgroud)
存储库
fun fetchItems() = itemDao.getItems()
Run Code Online (Sandbox Code Playgroud)
道
@Query("SELECT * FROM item")
fun getItems(): LiveData<List<Item>>
Run Code Online (Sandbox Code Playgroud)
我还想看到一些使用协程和 Flow 来处理 Room 或 Retrofit 的项目示例。我只找到了一个 Google 的ToDo 示例,其中协程用于一次性获取,然后在更改时手动重新获取数据。
android kotlin android-livedata kotlin-coroutines kotlinx.coroutines.flow
我Transformations.switchMap在我的ViewModel中使用,因此LiveData在我的片段中观察到的我的集合会对code参数的变化做出反应.
这非常有效:
public class MyViewModel extends AndroidViewModel {
private final LiveData<DayPrices> dayPrices;
private final MutableLiveData<String> code = new MutableLiveData<>();
// private final MutableLiveData<Integer> nbDays = new MutableLiveData<>();
private final DBManager dbManager;
public MyViewModel(Application application) {
super(application);
dbManager = new DBManager(application.getApplicationContext());
dayPrices = Transformations.switchMap(
code,
value -> dbManager.getDayPriceData(value/*, nbDays*/)
);
}
public LiveData<DayPrices> getDayPrices() {
return dayPrices;
}
public void setCode(String code) {
this.code.setValue(code);
}
/*public void setNbDays(int nbDays) {
this.nbDays.setValue(nbDays);
}*/
}
public class …Run Code Online (Sandbox Code Playgroud) android observer-pattern android-livedata android-viewmodel android-architecture-components
更新: 如果我移动到另一个片段并返回到这个片段,TextView 会更新......
我无法通过使用 setValue() 或 postValue() 使 UI 中的 MutableLiveData 更新为新值。我可以通过将 MutableLiveData 更改为 ObservableData 来使其工作,但重点是使用 LiveData 而不是 ObservableData。
我在其他视图中也有类似的工作没有问题。不确定这里发生了什么......我唯一能想到的是我在相机活动(通过意图)和这个片段之间来回跳跃。在活动结果上,我将片段中的数据设置到 ViewModel。
我不相信我需要为片段中的值设置任何观察者,因为我在 XML 和 ViewModel 之间有 2 路数据绑定。
my_fragment.XML
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="myViewModel"
type="com.example.myapplication.MyViewModel" />
</data>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@={myViewModel.photosCount}"
tools:text="1" />
<Button
android:id="@+id/btnTakePhoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Take Picture"
android:onClick="@{myViewModel::navClicked}"/>
</LinearLayout>
</layout>
Run Code Online (Sandbox Code Playgroud)
视图模型.java
private MutableLiveData<String> photosCount = new MutableLiveData<>();
private MutableLiveData<Boolean> takePhoto = new MutableLiveData<>();
public MyViewModel() {
photosCount.setValue("0"); // …Run Code Online (Sandbox Code Playgroud) 我有一个简单的DAO,包括CRUD功能
FeedEntryDAO.java
@Dao
public interface FeedEntryDAO {
@Query("SELECT * FROM feedEntrys")
LiveData<List<FeedEntry>> getAll();
@Query("SELECT * FROM feedEntrys WHERE uid = :uid LIMIT 1")
LiveData<FeedEntry> findByUid(int uid);
@Insert
void insertAll(FeedEntry... feedEntries);
@Delete
void delete(FeedEntry feedEntry);
@Update
int update(FeedEntry feedEntry);
}
Run Code Online (Sandbox Code Playgroud)
对于select,可以返回LiveData类型.
在Activity中,代码非常适合选择
viewModel.getFeedEntrys().observe(this,entries -> {...});
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试插入,更新,删除数据时.代码看起来有点难看,每次都会创建一个asynctask.
new AsyncTask<FeedEntry, Void, Void>() {
@Override
protected Void doInBackground(FeedEntry... feedEntries) {
viewModel.update(feedEntries[0]);
return null;
}
}.execute(feedEntry);
Run Code Online (Sandbox Code Playgroud)
我有2个问题:
感谢任何建议和意见.谢谢.
android android-room android-livedata android-architecture-components
我发现Dao返回的LiveData会在DB中更新行时调用它的观察者,即使LiveData值显然没有改变.
考虑类似以下示例的情况:
示例实体
@Entity
public class User {
public long id;
public String name;
// example for other variables
public Date lastActiveDateTime;
}
Run Code Online (Sandbox Code Playgroud)
示例道
@Dao
public interface UserDao {
// I am only interested in the user name
@Query("SELECT name From User")
LiveData<List<String>> getAllNamesOfUser();
@Update(onConflict = OnConflictStrategy.REPLACE)
void updateUser(User user);
}
Run Code Online (Sandbox Code Playgroud)
某个地方在后台线程
UserDao userDao = //.... getting the dao
User user = // obtain from dao....
user.lastActiveDateTime = new Date(); // no change to user.name
userDao.updateUser(user);
Run Code Online (Sandbox Code Playgroud)
UI中的某个地方
// omitted ViewModel …Run Code Online (Sandbox Code Playgroud) 我一直在使用库在我的代码中使用很多RxJava Observables转换.所以我想在RxJava Observable中添加一个扩展函数来轻松转换它们.LiveDataLiveDataReactiveStreams.fromPublisher()LiveData
这些是我的扩展功能:
fun <T> Flowable<T>.toLiveData() : LiveData<T> {
return LiveDataReactiveStreams.fromPublisher(this)
}
fun <T> Observable<T>.toLiveData(backPressureStrategy: BackpressureStrategy) : LiveData<T> {
return LiveDataReactiveStreams.fromPublisher(this.toFlowable(backPressureStrategy))
}
fun <T> Single<T>.toLiveData() : LiveData<T> {
return LiveDataReactiveStreams.fromPublisher(this.toFlowable())
}
fun <T> Maybe<T>.toLiveData() : LiveData<T> {
return LiveDataReactiveStreams.fromPublisher(this.toFlowable())
}
fun <T> Completable.toLiveData() : LiveData<T> {
return LiveDataReactiveStreams.fromPublisher(this.toFlowable())
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
PS
我是Kotlin的新手,所以我问这些问题.任何有用的东西将不胜感激.非常感谢你.
android kotlin rx-java2 android-livedata android-architecture-components
通过 Viewmodel 中的 LiveData,我们可以像这样使用 switchMap 或 Transformations.map
val recipesList = cuisineType.switchMap { repository.getDisplayRecipes(it.cuisineType).asLiveData() }
Run Code Online (Sandbox Code Playgroud)
使用 StateFlow 实现此目的的最佳方法是什么?我知道我们可以像下面一样使用地图,但是这会返回 Flow<Flow<List<Recipe>>> ,这似乎不正确
val recipeListFlow = cuisineTypeStateFlow.map {
repository.getDisplayRecipes(it.cuisineType)
}
Run Code Online (Sandbox Code Playgroud) android ×10
android-livedata ×10
android-architecture-components ×4
android-room ×3
kotlin ×3
rx-java2 ×1
viewmodel ×1