简体   繁体   中英

Room Livedata.observeforever not working after activity resumes

I have tested some test cases using the simple Room test code as below. "dao.getAll().observeForever()" does not work after main activity resumes. new words are inserted correctly but only observation does not work. If I use dao.getAll().observe(), it always works correctly. Is not allowed to use observeForever on activity's onCreate() method?

AppDatabase.java

@Database(entities = {Word.class}, version = 2)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase sInstance;

public abstract WordDao wordDao();

public static AppDatabase getInstance(Context context) {
    if (sInstance == null) {
        synchronized (AppDatabase.class) {
            if (sInstance == null) {
                sInstance = Room.databaseBuilder(context.getApplicationContext(),
                        AppDatabase.class, "word.db").addMigrations(new Migration(1, 2) {
                    @Override
                    public void migrate(@NonNull SupportSQLiteDatabase database) {
                    }
                }).build();
            }
        }
    }

    return sInstance;
}

}

Word.java

@Entity
public class Word {
@PrimaryKey(autoGenerate = true)
public int uid;

public String word;

public Word(String word) {
    this.word = word;
}

}

WordDao.java

@Dao
public interface WordDao {
@Query("Select * from word")
LiveData<List<Word>> getAll();

@Update
void update(Word word);

@Insert
void insert(Word word);

}

MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    TextView tv = findViewById(R.id.textview);

    WordDao dao = AppDatabase.getInstance(this).wordDao();

    dao.getAll().observeForever(wordlist -> {
        StringBuilder builder = new StringBuilder();

        for (Word w : wordlist ) {
            builder.append(w.word).append(", ");
        }

        tv.setText(builder.toString());
    });

    findViewById(R.id.add).setOnClickListener(view -> new Thread(() -> {
        dao.insert(new Word("haha"));
    }).start());
}

build.gradle

dependencies {
    def lifecycle_version = "1.1.1"
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
    implementation "android.arch.lifecycle:common-java8:$lifecycle_version"
    testImplementation "android.arch.core:core-testing:$lifecycle_version"

    def room_version = "1.1.1"
    implementation "android.arch.persistence.room:runtime:$room_version"
    annotationProcessor "android.arch.persistence.room:compiler:$room_version"
    testImplementation "android.arch.persistence.room:testing:$room_version"
}

Never use Architecture components like that. You should use MVVM as they are designed to work on that. Model should encompass your data of which room will do. Then Your View should contain presentation only and a reference to the third component the View-Model. The ViewModel is missing in your code and it goes something like this:

public class WordViewModel extends ViewModel {
    private MutableLiveData<List<Word>> mWords;
    private AppDatabase mDb;

    public WordViewModel(@NonNull Application application) {
        super(application);

        mWords = new MutableLiveData<List<Word>>();
        mDb = AppDatabase.getInstance(application.getApplicationContext());
    }

    public LiveData<List<User>> getWords() {
        loadWords();

        return words;
    }

    private void loadWords() {
       return mDb.wordDao().getAll();
    }
}

and then your Activity will change to

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final TextView tv = findViewById(R.id.textview);

    WordViewModel viewModel = ViewModelProviders.of(this).get(WordViewModel.class);
    viewModel.getWords().observe(this, new Observer<List<Word>>() {
        @Override
        public void onChanged(@Nullable ResponseDataList resp) {
            StringBuilder builder = new StringBuilder();

            for (Word w : wordlist ) {
                builder.append(w.word).append(", ");
            }

            tv.setText(builder.toString());
        }
    });
}

Let me know if anything is not clear in comments

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM