ViewModel LiveData Emits Empty List After Screen Rotation in Android

53 Views Asked by At

I have an issue concerning the behavior of LiveData within my ViewModel during a screen rotation.

My application, structured around the MVVM pattern, includes an Activity which observes a LiveData<List> from a ViewModel which, in turn, fetches data from a Repository linked to a Room database.

Below are the involved code snippets:

The Activity onCreate:

ChatViewModel2.getInstance(this, topic).getTopicChatLiveData().observe(this, chatMessageDBS -> {
    chatAdapter.submitList(chatMessageDBS.stream().distinct().map(ChatMessageViewModel::createInstance).collect(Collectors.toList()));
});

The ViewModel:

public class ChatViewModel2 extends ViewModel {
    private final ChatMassagesRepository repository;
    private String topic;
    private static ChatViewModel2 instance;

    public ChatViewModel2(@NonNull String topic) {
        repository = new ChatMassagesRepository();
        this.topic = topic;
    }

    public static synchronized ChatViewModel2 getInstance(Context context, String topic) {
        if (instance == null) {
            instance = new ViewModelProvider((ViewModelStoreOwner) context, new ChatMassagesViewModelFactory(topic)).get(ChatViewModel2.class);
        }
        return instance;
    }

    public LiveData<List<ChatMessageDB>> getTopicChatLiveData() {
        LiveData<List<ChatMessageDB>> topicChatLiveData = repository.getAllRepliesByTopic(topic);
        return topicChatLiveData;
    }
}

The ViewModelFactory:

public class ChatMassagesViewModelFactory implements ViewModelProvider.Factory {
    private String topic;

    public ChatMassagesViewModelFactory(String topic) {
        this.topic = topic;
    }

    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
        if (modelClass.isAssignableFrom(ChatViewModel2.class)) {
            return (T) new ChatViewModel2(topic);
        }
        throw new IllegalArgumentException("Unknown ViewModel class");
    }
}

The Repository:

public class ChatMassagesRepository {
    ChatMessageDAO chatMessageDao;
    private static ChatMassagesRepository INSTANCE;

    public static ChatMassagesRepository getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new ChatMassagesRepository();
        }
        return INSTANCE;
    }

    public ChatMassagesRepository() {
        chatMessageDao= ChatDatabase.getInstance().chatMessageDao();
    }

    public LiveData<List<ChatMessageDB>> getAllRepliesByTopic(String topic){
        LiveData<List<ChatMessageDB>> replies = chatMessageDao.getTopicChat(topic);
        return  replies;
    }
}

And this is the getInstance from the Database class:

@NonNull
public static ChatDatabase getInstance(final Context context){
    synchronized (ChatDatabase.class) {
        if (INSTANCE == null) {
            INSTANCE = Room.databaseBuilder(context.getApplicationContext(), ChatDatabase.class, "teleconsole_chat_database").fallbackToDestructiveMigration().build();
        }
    }
    return INSTANCE;
}

public static ChatDatabase getInstance(){
    return getInstance(AppController.getInstance());
}

Everything works fine until the screen rotates. Post-rotation, the observer in the Activity receives an empty list. Any insight into why this is happening and how to rectify it would be greatly appreciated.

i also tried

        new ViewModelProvider(this, new ChatMassagesViewModelFactory(topic)).get(ChatViewModel2.class).getTopicChatLiveData().observe(this, chatMessageDBS ->
                chatAdapter.submitList(chatMessageDBS.stream().distinct().map(ChatMessageViewModel::createInstance).collect(Collectors.toList())));

but did not help

2

There are 2 best solutions below

0
On

i got the problem , that in the onDestroy i am deleting the list like this

    @Override
    protected void onDestroy() {super.onDestroy();
        Utils.asyncTask(() -> ChatDatabase.getInstance().reactionsDao().deleteTopicReactions(topic));
        Utils.asyncTask(() -> ChatDatabase.getInstance().chatMessageDao().deleteByTopic(topic));
        Utils.asyncTask(() -> ChatDatabase.getInstance().repliesDao().deleteByTopic(topic));
    }

and at configChanges the onDestroy is getting called so the database gets empty, so i am getting back a empty list

2
On

You can try using android:"configChanges:orientation" in your Manifest file to igonre screen rotation like this:

<activity
    android:name="ActivityName"
    android:configChanges="orientation"
    android:label="@string/your_label">

But this isn't the best approach. Link on docs: https://developer.android.com/guide/topics/resources/runtime-changes#restrict-activity

Please let me know if the solution helped.