diff options
8 files changed, 63 insertions, 31 deletions
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainActivity.java index 6d2623a91..56695ba72 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainActivity.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainActivity.java @@ -29,7 +29,6 @@ import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.AppCompatDelegate; import androidx.core.util.Pair; import androidx.core.view.GravityCompat; -import androidx.fragment.app.Fragment; import androidx.lifecycle.LiveData; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; @@ -361,20 +360,6 @@ public class MainActivity extends BrandedActivity implements DeleteStackListener } @Override - protected void onStop() { - // Clean up zombie fragments in case of system initiated process death. - // See linked issues in https://github.com/stefan-niedermann/nextcloud-deck/issues/478 - try { - for (Fragment fragment : getSupportFragmentManager().getFragments()) { - getSupportFragmentManager().beginTransaction().remove(fragment).commit(); - } - } catch (IllegalStateException e) { - DeckLog.warn("onSAveInstanceState has already been called."); - } - super.onStop(); - } - - @Override protected void onDestroy() { super.onDestroy(); if (tabLayoutHelper != null) { diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditActivity.java index 8cb13a865..c039b2952 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditActivity.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditActivity.java @@ -14,13 +14,12 @@ import android.view.MenuItem; import android.view.WindowManager; import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; +import androidx.appcompat.app.AppCompatActivity; import androidx.lifecycle.ViewModelProvider; import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayoutMediator; -import it.niedermann.nextcloud.deck.DeckLog; import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.databinding.ActivityEditBinding; import it.niedermann.nextcloud.deck.model.Account; @@ -279,22 +278,15 @@ public class EditActivity extends BrandedActivity { .setPositiveButton(R.string.simple_save, (dialog, whichButton) -> saveAndFinish()) .setNegativeButton(R.string.simple_discard, (dialog, whichButton) -> super.finish()).show(); } else { - super.finish(); + directFinish(); } } - @Override - protected void onStop() { - // Clean up zombie fragments in case of system initiated process death. - // See linked issues in https://github.com/stefan-niedermann/nextcloud-deck/issues/478 - try { - for (Fragment fragment : getSupportFragmentManager().getFragments()) { - getSupportFragmentManager().beginTransaction().remove(fragment).commit(); - } - } catch (IllegalStateException e) { - DeckLog.warn("onSAveInstanceState has already been called."); - } - super.onStop(); + /** + * Performs a call of {@link AppCompatActivity#finish()} without checking for changes + */ + public void directFinish() { + super.finish(); } @Override diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/activities/CardActivityFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/activities/CardActivityFragment.java index 929044ed0..08d960257 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/activities/CardActivityFragment.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/activities/CardActivityFragment.java @@ -10,6 +10,7 @@ import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.RecyclerView; +import it.niedermann.nextcloud.deck.DeckLog; import it.niedermann.nextcloud.deck.databinding.FragmentCardEditTabActivitiesBinding; import it.niedermann.nextcloud.deck.persistence.sync.SyncManager; import it.niedermann.nextcloud.deck.ui.card.EditCardViewModel; @@ -30,6 +31,13 @@ public class CardActivityFragment extends Fragment { binding = FragmentCardEditTabActivitiesBinding.inflate(inflater, container, false); final EditCardViewModel viewModel = new ViewModelProvider(requireActivity()).get(EditCardViewModel.class); + // This might be a zombie fragment with an empty EditCardViewModel after Android killed the activity (but not the fragment instance + // See https://github.com/stefan-niedermann/nextcloud-deck/issues/478 + if (viewModel.getFullCard() == null) { + DeckLog.logError(new IllegalStateException("Cannot populate " + CardActivityFragment.class.getSimpleName() + " because viewModel.getFullCard() is null")); + return binding.getRoot(); + } + if (!viewModel.isCreateMode()) { final SyncManager syncManager = new SyncManager(requireContext()); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java index f9574367f..f38795e19 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java @@ -65,6 +65,13 @@ public class CardAttachmentsFragment extends BrandedFragment implements Attachme binding = FragmentCardEditTabAttachmentsBinding.inflate(inflater, container, false); viewModel = new ViewModelProvider(requireActivity()).get(EditCardViewModel.class); + // This might be a zombie fragment with an empty EditCardViewModel after Android killed the activity (but not the fragment instance + // See https://github.com/stefan-niedermann/nextcloud-deck/issues/478 + if (viewModel.getFullCard() == null) { + DeckLog.logError(new IllegalStateException("Cannot populate " + CardAttachmentsFragment.class.getSimpleName() + " because viewModel.getFullCard() is null")); + return binding.getRoot(); + } + syncManager = new SyncManager(requireContext()); adapter = new CardAttachmentAdapter( requireContext(), diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java index c89847a23..5e61a57cd 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java @@ -8,6 +8,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.EditorInfo; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -16,10 +17,13 @@ import androidx.lifecycle.ViewModelProvider; import java.util.Date; +import it.niedermann.nextcloud.deck.DeckLog; +import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.databinding.FragmentCardEditTabCommentsBinding; import it.niedermann.nextcloud.deck.model.ocs.comment.DeckComment; import it.niedermann.nextcloud.deck.persistence.sync.SyncManager; import it.niedermann.nextcloud.deck.ui.branding.BrandedFragment; +import it.niedermann.nextcloud.deck.ui.card.EditActivity; import it.niedermann.nextcloud.deck.ui.card.EditCardViewModel; import static android.view.View.GONE; @@ -45,6 +49,20 @@ public class CardCommentsFragment extends BrandedFragment implements CommentEdit binding = FragmentCardEditTabCommentsBinding.inflate(inflater, container, false); viewModel = new ViewModelProvider(requireActivity()).get(EditCardViewModel.class); + + // This might be a zombie fragment with an empty EditCardViewModel after Android killed the activity (but not the fragment instance + // See https://github.com/stefan-niedermann/nextcloud-deck/issues/478 + if (viewModel.getFullCard() == null) { + DeckLog.logError(new IllegalStateException("Cannot populate " + CardCommentsFragment.class.getSimpleName() + " because viewModel.getFullCard() is null")); + if (requireActivity() instanceof EditActivity) { + Toast.makeText(getContext(), R.string.error_edit_activity_killed_by_android, Toast.LENGTH_LONG).show(); + ((EditActivity) requireActivity()).directFinish(); + } else { + requireActivity().finish(); + } + return binding.getRoot(); + } + syncManager = new SyncManager(requireActivity()); adapter = new CardCommentsAdapter(requireContext(), viewModel.getAccount(), requireActivity().getMenuInflater(), this, getChildFragmentManager()); binding.comments.setAdapter(adapter); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java index 502d1179a..a2a01b618 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java @@ -95,6 +95,14 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis dateFormat = getDateFormat(activity); viewModel = new ViewModelProvider(activity).get(EditCardViewModel.class); + + // This might be a zombie fragment with an empty EditCardViewModel after Android killed the activity (but not the fragment instance + // See https://github.com/stefan-niedermann/nextcloud-deck/issues/478 + if (viewModel.getFullCard() == null) { + DeckLog.logError(new IllegalStateException("Cannot populate " + CardDetailsFragment.class.getSimpleName() + " because viewModel.getFullCard() is null")); + return binding.getRoot(); + } + syncManager = new SyncManager(requireContext()); avatarSize = dpToPx(requireContext(), R.dimen.avatar_size); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/StackFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/StackFragment.java index 7b43d130c..2bc2888ae 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/StackFragment.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/StackFragment.java @@ -7,6 +7,7 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.LiveData; @@ -17,6 +18,7 @@ import androidx.recyclerview.widget.RecyclerView; import java.util.List; import it.niedermann.android.crosstabdnd.DragAndDropTab; +import it.niedermann.nextcloud.deck.DeckLog; import it.niedermann.nextcloud.deck.databinding.FragmentStackBinding; import it.niedermann.nextcloud.deck.model.full.FullCard; import it.niedermann.nextcloud.deck.persistence.sync.SyncManager; @@ -35,6 +37,7 @@ public class StackFragment extends BrandedFragment implements DragAndDropTab<Car private FragmentActivity activity; private OnScrollListener onScrollListener; + @Nullable private CardAdapter adapter = null; private LiveData<List<FullCard>> cardsLiveData; @@ -64,6 +67,13 @@ public class StackFragment extends BrandedFragment implements DragAndDropTab<Car final MainViewModel mainViewModel = new ViewModelProvider(activity).get(MainViewModel.class); final FilterViewModel filterViewModel = new ViewModelProvider(activity).get(FilterViewModel.class); + // This might be a zombie fragment with an empty MainViewModel after Android killed the activity (but not the fragment instance + // See https://github.com/stefan-niedermann/nextcloud-deck/issues/478 + if (mainViewModel.getCurrentAccount() == null) { + DeckLog.logError(new IllegalStateException("Cannot populate " + StackFragment.class.getSimpleName() + " because mainViewModel.getCurrentAccount() is null")); + return binding.getRoot(); + } + syncManager = new SyncManager(activity); adapter = new CardAdapter(requireContext(), getChildFragmentManager(), mainViewModel.getCurrentAccount(), mainViewModel.getCurrentBoardLocalId(), stackId, mainViewModel.currentBoardHasEditPermission(), syncManager, this, (requireActivity() instanceof SelectCardListener) ? (SelectCardListener) requireActivity() : null); @@ -106,6 +116,7 @@ public class StackFragment extends BrandedFragment implements DragAndDropTab<Car return binding.getRoot(); } + @Nullable @Override public CardAdapter getAdapter() { return adapter; @@ -118,7 +129,9 @@ public class StackFragment extends BrandedFragment implements DragAndDropTab<Car @Override public void applyBrand(int mainColor, int textColor) { - this.adapter.applyBrand(mainColor, textColor); + if (this.adapter != null) { + this.adapter.applyBrand(mainColor, textColor); + } } public static Fragment newInstance(long stackId) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0fe6513ff..22f61c724 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -231,6 +231,7 @@ <string name="server_misconfigured">Server misconfigured</string> <string name="server_error">Server error</string> <string name="shared_error">Sharing content from 3rd-party apps is not yet fully supported. Please try to download it first and then share it from you native file manager or gallery.</string> + <string name="error_edit_activity_killed_by_android">Android finished the edit mode because it needed more system resources for other apps.</string> <string name="error_dialog_title">Oh no - What now? 🙁</string> <string name="error_dialog_tip_token_mismatch_retry">Please try to force close the app and restart it again. There might have been an incorrect connection to the Nextcloud app.</string> |