Восстановление заднего стека Android после закрытия приложения - PullRequest
9 голосов
/ 27 июля 2011

Как лучше всего управлять / восстанавливать приложение стек назад между несколькими сеансами?

Пример рабочего процесса:

  1. Задание A началось (стек: A)
  2. Мероприятие B началось (стек: A B)
  3. Мероприятие C началось (стек: A B C)
  4. ...
  5. Пользователь какое-то время использует другое приложение (скажем, приложение GMail)
  6. ...
  7. Пользователь возвращается к моему приложению, но задний стек очищен Android.

На шаге 7 я хотел бы возобновить действие C, и если пользователь дважды нажмет кнопку «Назад», он вернется к действию B, а затем к действию A.

[Редактировать] Добавление деталей.

После шага 7, описанного выше, по умолчанию в Android происходит следующее:

  1. Задание A началось (стек: пусто, а C добавлено)

И я бы хотел, чтобы пользователь чувствовал, что он все еще использует тот же сеанс:

  1. Операция C возобновлена ​​(стек: A B C)
  2. Пользователь нажимает кнопку «Назад», операция B возобновляется (стек: A B)
  3. Пользователь нажимает кнопку «Назад», операция A возобновляется (стек: A)

Что было бы хорошим подходом к этой ситуации, избегая утечек памяти?

[Второе редактирование] Я разработал обходной путь, используя UIController класса commong для всех действий и LauncherActivity для делегирования логики UIController.

Поскольку мне нужно перестраивать задний стек только после запуска ActivityC, похоже, это решение работает нормально:

public class UIController
{
    private boolean _launched = false;

    static private final UIController __instance = new UIController();
    static public UIController getInstance() { return __instance; }

    // Enforces the Singleton Pattern by preventing external access to constructor
    private UIController() { }

    public void onActivityCreated(Activity activity) {
        if (!_launched)
        {
            if ( shouldRebuildStack() )
            {
                // Rebuild Activity stack

                // Npte : actually Android will add ActivityA and ActivityB to the stack
                // but will *NOT* create them right away. Only ActivityC will be 
                // created and resumed.
                // Since they are in the back stack, the other activities will be 
                // created by Android once needed.
                startActivity(activity, ActivityA.class);
                startActivity(activity, ActivityB.class);
                startActivity(activity, ActivityC.class);
            } else {
                // Starts default activity
                startActivity(activity, ActivityA.class);
            }

            _launched = true;
        }
    }

    public void onActivityResumed(Activity activity) {
        memorizeCurrentActivity( activity.getClass().toString() );
    }

    private void memorizeCurrentActivity( String className ) {
        // write className to preferences, disk, etc.
    }

    private boolean shouldRebuildStack() {
        String previousActivity = " [load info from file, preferences, etc.] ";
        return (previousActivity != null && previousActivity.equals("my.package.ActivityC"));
    }

    private void startActivity(Activity caller, Class newActivityClass)
    {
        Intent intent = new Intent(caller, newActivityClass);
        intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        caller.startActivity( intent );
    }
}

// This is the default activity in the AndroidManifest.xml
// This prevents ActivityA from starting right away if the UIController
// wants to rebuild the stack.
public class LauncherActivity() {
    protected void onCreate(Bundle data) {
        super.onCreate(data);
        UIController.getInstance().onActivityCreated(this);
        finish();
    }
}

public class ActivityA() {
    protected void onCreate(Bundle data) {
        super.onCreate(data);
        UIController.getInstance().onActivityCreated(this);
    }
    protected void onResume() {
        super.onResume();
        UIController.getInstance().onActivityResumed(this);
    }
}

public class ActivityB() {
    // onCreate() & onResume(), same as ActivityA
}

public class ActivityC() {
    // onCreate() & onResume(), same as ActivityA
}

public class LauncherActivity() {
    protected void onCreate(Bundle data) {
        super.onCreate(data);
        UIController.getInstance().onActivityCreated(this);
        finish();
    }
}

public class ActivityA() {
    protected void onCreate(Bundle data) {
        super.onCreate(data);
        UIController.getInstance().onActivityCreated(this);
    }
    protected void onResume() {
        super.onResume();
        UIController.getInstance().onActivityResumed(this);
    }
}

public class ActivityB() {
    // same as ActivityA
}

public class ActivityC() {
    // same as ActivityA
}

Если у кого-то есть лучшее решение, не стесняйтесь опубликовать его.

1 Ответ

5 голосов
/ 04 августа 2011

Звучит так, как будто вы должны установить значение true и позволить Android обрабатывать управление стеком активности.

android: alwaysRetainTaskState

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

...