Создание пользовательских событий жизненного цикла для фрагментов Android - PullRequest
0 голосов
/ 30 октября 2018

У меня есть приложение для Android, написанное с использованием Xamarin, но мой вопрос относится и к не Xamarin. У меня есть класс MainActivity (как действие), который просто размещает макет фрейма в виде контейнера фрагмента. Мое приложение состоит из нескольких фрагментов, по которым я перемещаюсь назад и вперед. Да, я знаю, что ViewPager подходит для этой задачи и решит мою проблему, но по причинам, выходящим за рамки этого поста, я не хочу использовать ViewPager.

Все, что у меня есть, это в основном простые кнопки (например, следующая и предыдущая), которые используются для навигации. При навигации я добавляю фрагменты в задний стек, если они еще не существуют. Если они существуют, я обязательно добавлю задний стек вместо создания нескольких дублирующих экземпляров. Поэтому, если в моем приложении только 4 фрагмента, в моем заднем стеке будет только 4 элемента.

Мой вопрос касается событий жизненного цикла. Как только фрагмент создается один раз, когда будут возникать события жизненного цикла (OnCreate и т. Д.), Они никогда не будут вызываться снова при простом переходе от фрагмента к фрагменту и обратно (при условии, что они были созданы один раз и сидят в заднем стеке).

Поэтому я ищу чистый способ вызывать событие для фрагмента каждый раз, когда он останавливается или возобновляется с помощью навигации, подобно onPause и onResume, которые обычно происходят.

Я немного прочитал и обнаружил, что не могу проверить скрытое свойство в этом случае, потому что это происходит только во время скрытия или показа фрагмента, и я не делаю этого здесь, получение заднего стека не вызывает скрытое свойство или событие.

Итак, я создал интерфейс, подобный этому:

interface ICustomFragmentLifecycle
{
    void onPauseFragment();
    void onResumeFragment();
}

Затем я удостоверяюсь, что каждый фрагмент реализует этот интерфейс, который дает мне методы паузы и возобновления для каждого фрагмента, где я могу выполнять работу, которую я хочу сделать.

Проблема в MainActivity, где я должен вызывать эти события. Каждый раз, когда нажимается кнопка для навигации, я получаю это на MainActivity, что хорошо, поэтому я могу действовать по нему и использовать его для вызова пользовательских событий в интерфейсе. Мне также нужно сделать что-то подобное с кнопкой возврата. Итак, вот как я обрабатываю кнопку возврата:

public override void OnBackPressed()
{
    //When the back button is pressed, we need to first pop the back stack.
    if(SupportFragmentManager.BackStackEntryCount > 0)
    {
            //First, raise the pause method on the current fragment
            RaiseCustomFragmentOnPause();

            if(SupportFragmentManager.BackStackEntryCount > 1)
                //Now we should resume the fragment that is showing
                RaiseCustomFragmentOnResume();
            SupportFragmentManager.PopBackStack();

            //Check and see if we just popped the last one and now there are none.
            if(SupportFragmentManager.BackStackEntryCount == 0)
                MainLayoutEnabled(true);

            return;
    }
 }

И, наконец, в методах, которые вызываются для вызова паузы или возобновления, это код:

    private void RaiseCustomFragmentOnPause()
    {
        //This will get the current fragment from the stack.
        var fragIdToPause = SupportFragmentManager.BackStackEntryCount - 1;
        var fragBackEntry = SupportFragmentManager.GetBackStackEntryAt(fragIdToPause);
        var fragTag = fragBackEntry.Name;

        ICustomFragmentLifecycle fragmentToPause = (ICustomFragmentLifecycle)SupportFragmentManager.FindFragmentByTag(fragTag);
        fragmentToPause.onPauseFragment();
    }

    private void RaiseCustomFragmentOnResume()
    {
        //This will get the previous fragment, before the current one, from the stack. 
        var fragIdToPause = SupportFragmentManager.BackStackEntryCount - 2;
        var fragBackEntry = SupportFragmentManager.GetBackStackEntryAt(fragIdToPause);
        var fragTag = fragBackEntry.Name;

        ICustomFragmentLifecycle fragmentToResume = (ICustomFragmentLifecycle)SupportFragmentManager.FindFragmentByTag(fragTag);
        fragmentToResume.onResumeFragment();
    }

Меня интересует, прежде всего, хороший ли это подход или есть что-то более изящное, чего мне не хватает. Конкретная проблема, с которой я сталкиваюсь, это то, что время от времени я получаю исключение нулевой ссылки методом

GetBackStackEntryAt ()

Я подозреваю, что мой метод получения текущих и предыдущих записей в стеке обратно, основанный только на вычитании одного (для текущего) и двух (для предыдущего), некорректен. Я пытался описать это в вызывающей стороне этих методов, методе кнопки «назад», проверяя, чтобы убедиться, что в стеке есть хотя бы один или два элемента, прежде чем я вызову их, но все равно кажется, что несинхронизировано и что-то испортилось.

Мысли

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...