Fix NPE when returning to profile from background.

Also generally improves saved-state management for Profile editor.
master
Alex Hart 2020-01-28 14:57:17 -04:00 committed by GitHub
parent e3878ffde7
commit 4ae7d56db4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 22 deletions

View File

@ -31,8 +31,10 @@ public class EditProfileActivity extends BaseActionBarActivity implements EditPr
setContentView(R.layout.profile_create_activity);
NavGraph graph = Navigation.findNavController(this, R.id.nav_host_fragment).getGraph();
Navigation.findNavController(this, R.id.nav_host_fragment).setGraph(graph, getIntent().getExtras());
if (bundle == null) {
NavGraph graph = Navigation.findNavController(this, R.id.nav_host_fragment).getGraph();
Navigation.findNavController(this, R.id.nav_host_fragment).setGraph(graph, getIntent().getExtras());
}
}
@Override

View File

@ -57,7 +57,8 @@ import static org.thoughtcrime.securesms.profiles.edit.EditProfileActivity.SHOW_
public class EditProfileFragment extends Fragment {
private static final String TAG = Log.tag(EditProfileFragment.class);
private static final String TAG = Log.tag(EditProfileFragment.class);
private static final String AVATAR_STATE = "avatar";
private Toolbar toolbar;
private View title;
@ -115,7 +116,7 @@ public class EditProfileFragment extends Fragment {
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
initializeResources(view);
initializeViewModel(requireArguments().getBoolean(EXCLUDE_SYSTEM, false));
initializeViewModel(requireArguments().getBoolean(EXCLUDE_SYSTEM, false), savedInstanceState != null);
initializeProfileName();
initializeProfileAvatar();
initializeUsername();
@ -123,6 +124,20 @@ public class EditProfileFragment extends Fragment {
requireActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
outState.putByteArray(AVATAR_STATE, viewModel.getAvatarSnapshot());
}
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
if (savedInstanceState != null && savedInstanceState.containsKey(AVATAR_STATE)) {
viewModel.setAvatar(savedInstanceState.getByteArray(AVATAR_STATE));
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
@ -181,9 +196,9 @@ public class EditProfileFragment extends Fragment {
}
}
private void initializeViewModel(boolean excludeSystem) {
EditProfileRepository repository = new EditProfileRepository(requireContext(), excludeSystem);
EditProfileViewModel.Factory factory = new EditProfileViewModel.Factory(repository);
private void initializeViewModel(boolean excludeSystem, boolean hasSavedInstanceState) {
EditProfileRepository repository = new EditProfileRepository(requireContext(), excludeSystem);
EditProfileViewModel.Factory factory = new EditProfileViewModel.Factory(repository, hasSavedInstanceState);
viewModel = ViewModelProviders.of(this, factory).get(EditProfileViewModel.class);
}
@ -246,17 +261,17 @@ public class EditProfileFragment extends Fragment {
}
private void initializeProfileName() {
viewModel.profileName().observe(this, profileName -> {
viewModel.givenName().observe(this, givenName -> updateFieldIfNeeded(this.givenName, givenName));
updateFieldIfNeeded(givenName, profileName.getGivenName());
updateFieldIfNeeded(familyName, profileName.getFamilyName());
viewModel.familyName().observe(this, familyName -> updateFieldIfNeeded(this.familyName, familyName));
viewModel.profileName().observe(this, profileName -> {
preview.setText(profileName.toString());
boolean validEntry = !profileName.isGivenNameEmpty();
finishButton.setEnabled(validEntry);
finishButton.setAlpha(validEntry ? 1f : 0.5f);
preview.setText(profileName.toString());
});
}

View File

@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.profiles.edit;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.core.util.Consumer;
import androidx.lifecycle.LiveData;
@ -22,19 +23,30 @@ class EditProfileViewModel extends ViewModel {
private final MutableLiveData<Optional<String>> internalUsername = new MutableLiveData<>();
private final EditProfileRepository repository;
private EditProfileViewModel(@NonNull EditProfileRepository repository) {
private EditProfileViewModel(@NonNull EditProfileRepository repository, boolean hasInstanceState) {
this.repository = repository;
repository.getCurrentUsername(internalUsername::postValue);
repository.getCurrentProfileName(name -> {
givenName.setValue(name.getGivenName());
familyName.setValue(name.getFamilyName());
});
repository.getCurrentAvatar(internalAvatar::setValue);
if (!hasInstanceState) {
repository.getCurrentProfileName(name -> {
givenName.setValue(name.getGivenName());
familyName.setValue(name.getFamilyName());
});
repository.getCurrentAvatar(internalAvatar::setValue);
}
}
public LiveData<String> givenName() {
return Transformations.distinctUntilChanged(givenName);
}
public LiveData<String> familyName() {
return Transformations.distinctUntilChanged(familyName);
}
public LiveData<ProfileName> profileName() {
return internalProfileName;
return Transformations.distinctUntilChanged(internalProfileName);
}
public LiveData<byte[]> avatar() {
@ -49,6 +61,11 @@ class EditProfileViewModel extends ViewModel {
return internalAvatar.getValue() != null;
}
@MainThread
public byte[] getAvatarSnapshot() {
return internalAvatar.getValue();
}
public void setGivenName(String givenName) {
this.givenName.setValue(givenName);
}
@ -73,16 +90,18 @@ class EditProfileViewModel extends ViewModel {
static class Factory implements ViewModelProvider.Factory {
private final EditProfileRepository repository;
private final boolean hasInstanceState;
Factory(EditProfileRepository repository) {
this.repository = repository;
Factory(@NonNull EditProfileRepository repository, boolean hasInstanceState) {
this.repository = repository;
this.hasInstanceState = hasInstanceState;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
//noinspection unchecked
return (T) new EditProfileViewModel(repository);
return (T) new EditProfileViewModel(repository, hasInstanceState);
}
}
}